exercises_p2.ipynb (6952B)
1 { 2 "cells": [ 3 { 4 "cell_type": "code", 5 "execution_count": null, 6 "id": "ef154598-e0d1-4721-a171-f8cdb8340bc8", 7 "metadata": {}, 8 "outputs": [], 9 "source": [ 10 "(* 15\n", 11 "\n", 12 "NEW IDEA: recursion that stops when it is close enough, because floats cannot\n", 13 "be compared for equality.\n", 14 "\n", 15 "newton_sqrt x approximates the square root of x >= 0 by Newton's method. Start\n", 16 "from a guess and repeatedly improve it with\n", 17 "\n", 18 " next = (guess +. x /. guess) /. 2.\n", 19 "\n", 20 "Stop when the guess is good enough, when abs_float (guess *. guess -. x) is\n", 21 "below a small tolerance such as 1e-10. Note that x itself works as a starting\n", 22 "guess, except for x = 0.\n", 23 "\n", 24 "Do not write guess *. guess = x. Floats are approximations, that test would\n", 25 "loop forever, and it is the same reason 0.1 +. 0.2 = 0.3 is false in every\n", 26 "language with binary floats.\n", 27 "\n", 28 "newton_sqrt 2.0 is about 1.4142135, newton_sqrt 81.0 = 9.0,\n", 29 "newton_sqrt 0.0 = 0.0.\n", 30 "\n", 31 "Afterwards try newton_sqrt 1e12 and work out why an absolute tolerance of\n", 32 "1e-10 cannot terminate there. A double has about 16 significant digits, so near\n", 33 "1e12 the gap between neighbouring representable values is already larger than\n", 34 "1e-10. Fixing it means comparing relatively, for instance stopping when\n", 35 "successive guesses barely change.\n", 36 "\n", 37 "*)" 38 ] 39 }, 40 { 41 "cell_type": "code", 42 "execution_count": 54, 43 "id": "11e1e0c3-1f65-4251-998a-69804398e6a3", 44 "metadata": {}, 45 "outputs": [ 46 { 47 "data": { 48 "text/plain": [ 49 "val abs_diff : float -> float -> float = <fun>\n" 50 ] 51 }, 52 "execution_count": 54, 53 "metadata": {}, 54 "output_type": "execute_result" 55 }, 56 { 57 "data": { 58 "text/plain": [ 59 "val newton_sqrt : float -> float = <fun>\n" 60 ] 61 }, 62 "execution_count": 54, 63 "metadata": {}, 64 "output_type": "execute_result" 65 } 66 ], 67 "source": [ 68 "let abs_diff x y = abs_float (x -. y);;\n", 69 "\n", 70 "let newton_sqrt x = \n", 71 " let rec go guess = \n", 72 " let diff = abs_diff x (guess *. guess) in\n", 73 " if diff < 0.0000000001\n", 74 " then guess\n", 75 " else go ((guess +. x /. guess) /. 2.)\n", 76 " in go x;;\n" 77 ] 78 }, 79 { 80 "cell_type": "code", 81 "execution_count": 55, 82 "id": "1c13de25-3a65-4c53-be93-30aeaa43e3f4", 83 "metadata": {}, 84 "outputs": [ 85 { 86 "name": "stdout", 87 "output_type": "stream", 88 "text": [ 89 "- : unit = ()\n", 90 "Findlib has been successfully loaded. Additional directives:\n", 91 " #require \"package\";; to load a package\n", 92 " #list;; to list the available packages\n", 93 " #camlp4o;; to load camlp4 (standard syntax)\n", 94 " #camlp4r;; to load camlp4 (revised syntax)\n", 95 " #predicates \"p,q,...\";; to set these predicates\n", 96 " Topfind.reset();; to force that packages will be reloaded\n", 97 " #thread;; to enable threads\n", 98 "\n", 99 "- : unit = ()\n" 100 ] 101 } 102 ], 103 "source": [ 104 "#use \"topfind\";;\n", 105 "#require \"qcheck\";;" 106 ] 107 }, 108 { 109 "cell_type": "code", 110 "execution_count": 56, 111 "id": "c54a0a4c-a9f0-4ebd-bd59-d7fc331b51ad", 112 "metadata": {}, 113 "outputs": [ 114 { 115 "data": { 116 "text/plain": [ 117 "val abs_diff : float -> float -> float = <fun>\n" 118 ] 119 }, 120 "execution_count": 56, 121 "metadata": {}, 122 "output_type": "execute_result" 123 } 124 ], 125 "source": [ 126 "let abs_diff x y = abs_float (x -. y);;" 127 ] 128 }, 129 { 130 "cell_type": "code", 131 "execution_count": 57, 132 "id": "3bc48b8e-6aee-4438-9db0-561c4045ce99", 133 "metadata": {}, 134 "outputs": [ 135 { 136 "data": { 137 "text/plain": [ 138 "- : float = 2.00000000000451061\n" 139 ] 140 }, 141 "execution_count": 57, 142 "metadata": {}, 143 "output_type": "execute_result" 144 } 145 ], 146 "source": [ 147 "newton_sqrt 2. *. newton_sqrt 2." 148 ] 149 }, 150 { 151 "cell_type": "code", 152 "execution_count": 58, 153 "id": "f307630e-b1a1-45a1-a42f-6a934f0602dd", 154 "metadata": {}, 155 "outputs": [ 156 { 157 "data": { 158 "text/plain": [ 159 "- : bool = true\n" 160 ] 161 }, 162 "execution_count": 58, 163 "metadata": {}, 164 "output_type": "execute_result" 165 } 166 ], 167 "source": [ 168 "(abs_diff 2. ((newton_sqrt 2.) *. (newton_sqrt 2.))) < 0.01" 169 ] 170 }, 171 { 172 "cell_type": "code", 173 "execution_count": 59, 174 "id": "04f59f1f-fbb1-40f3-a8e8-67dc1aa54231", 175 "metadata": {}, 176 "outputs": [], 177 "source": [ 178 "(* 16\n", 179 "\n", 180 "NEW IDEA: two accumulators tracking the best answer so far, the functional\n", 181 "version of keeping a running maximum.\n", 182 "\n", 183 "busiest_collatz lo hi returns which n in the range lo..hi takes the most\n", 184 "Collatz steps to reach 1. On a tie, return the smallest such n.\n", 185 "\n", 186 "*)" 187 ] 188 }, 189 { 190 "cell_type": "code", 191 "execution_count": 103, 192 "id": "2030e995-98d6-4ca4-b450-d50004487746", 193 "metadata": {}, 194 "outputs": [ 195 { 196 "data": { 197 "text/plain": [ 198 "val busiest_collatz : int -> int -> int = <fun>\n" 199 ] 200 }, 201 "execution_count": 103, 202 "metadata": {}, 203 "output_type": "execute_result" 204 } 205 ], 206 "source": [ 207 "let busiest_collatz lo hi = \n", 208 " let rec col_calc n = \n", 209 " if n = 1 then 1 else\n", 210 " if n mod 2 = 0 \n", 211 " then ((col_calc (n / 2))) + 1\n", 212 " else ((col_calc ((3 * n) + 1))) + 1\n", 213 " in \n", 214 " let rec go best_num best_count current_num =\n", 215 " if current_num < lo then best_num\n", 216 " else\n", 217 " let current_count = (col_calc current_num) in\n", 218 " if current_count >= best_count\n", 219 " then go current_num current_count (current_num - 1)\n", 220 " else\n", 221 " go best_num best_count (current_num - 1)\n", 222 " in go 0 0 hi" 223 ] 224 }, 225 { 226 "cell_type": "code", 227 "execution_count": 106, 228 "id": "a17b339d-0d3b-455c-8f31-2c6d10251134", 229 "metadata": {}, 230 "outputs": [ 231 { 232 "data": { 233 "text/plain": [ 234 "- : int = 837799\n" 235 ] 236 }, 237 "execution_count": 106, 238 "metadata": {}, 239 "output_type": "execute_result" 240 } 241 ], 242 "source": [ 243 "busiest_collatz 1 1000000" 244 ] 245 } 246 ], 247 "metadata": { 248 "kernelspec": { 249 "display_name": "OCaml default", 250 "language": "OCaml", 251 "name": "ocaml-jupyter" 252 }, 253 "language_info": { 254 "codemirror_mode": "text/x-ocaml", 255 "file_extension": ".ml", 256 "mimetype": "text/x-ocaml", 257 "name": "OCaml", 258 "nbconverter_exporter": null, 259 "pygments_lexer": "OCaml", 260 "version": "4.14.2" 261 } 262 }, 263 "nbformat": 4, 264 "nbformat_minor": 5 265 }