3 [clojure.contrib.math :only (sqrt expt)]
4 [clojure.contrib.trace :only (dotrace)]))
10 (* n (factorial (- n 1)))))
12 ;; stack friendly version
17 (recur (- x 1) (* acc x)))))
21 (reduce * (range 1 (inc n))))
24 ;; user> (dotrace [factorial] (factorial 3))
25 ;; TRACE t2701: (factorial 3)
26 ;; TRACE t2702: | (factorial 2)
27 ;; TRACE t2703: | | (factorial 1)
28 ;; TRACE t2703: | | => 1
29 ;; TRACE t2702: | => 2
35 ;; sicp.chapter1.ch1_2> (dotrace [factorial] (factorial 6))
36 ;; TRACE t2778: (factorial 6)
37 ;; TRACE t2779: | (factorial 5)
38 ;; TRACE t2780: | | (factorial 4)
39 ;; TRACE t2781: | | | (factorial 3)
40 ;; TRACE t2782: | | | | (factorial 2)
41 ;; TRACE t2783: | | | | | (factorial 1)
42 ;; TRACE t2783: | | | | | => 1
43 ;; TRACE t2782: | | | | => 2
44 ;; TRACE t2781: | | | => 6
45 ;; TRACE t2780: | | => 24
46 ;; TRACE t2779: | => 120
47 ;; TRACE t2778: => 720
52 ;; sicp.chapter1.ch1_2> (dotrace [factorial2] (factorial2 6))
53 ;; TRACE t2806: (factorial2 6)
54 ;; TRACE t2806: => 720
58 (defn fact-iter [product counter max-count]
59 (if (> counter max-count)
61 (fact-iter (* product counter)
69 ;; user> (dotrace [factorial fact-iter] (factorial 6))
70 ;; TRACE t2378: (factorial 6)
71 ;; TRACE t2379: | (fact-iter 1 1 6)
72 ;; TRACE t2380: | | (fact-iter 1 2 6)
73 ;; TRACE t2381: | | | (fact-iter 2 3 6)
74 ;; TRACE t2382: | | | | (fact-iter 6 4 6)
75 ;; TRACE t2383: | | | | | (fact-iter 24 5 6)
76 ;; TRACE t2384: | | | | | | (fact-iter 120 6 6)
77 ;; TRACE t2385: | | | | | | | (fact-iter 720 7 6)
78 ;; TRACE t2385: | | | | | | | => 720
79 ;; TRACE t2384: | | | | | | => 720
80 ;; TRACE t2383: | | | | | => 720
81 ;; TRACE t2382: | | | | => 720
82 ;; TRACE t2381: | | | => 720
83 ;; TRACE t2380: | | => 720
84 ;; TRACE t2379: | => 720
85 ;; TRACE t2378: => 720
89 ;; observation: clojure loop-recur construct is essentially the same as
90 ;; the iterative version.
96 (inc (++ (dec a) b))))
99 ;; This version is a recursive process, where the previous call increments
100 ;; the sum by 1 and each call decrement the first operand by 1.
102 ;; user> (dotrace [++] (++ 4 5))
103 ;; TRACE t3745: (++ 4 5)
104 ;; TRACE t3746: | (++ 3 5)
105 ;; TRACE t3747: | | (++ 2 5)
106 ;; TRACE t3748: | | | (++ 1 5)
107 ;; TRACE t3749: | | | | (++ 0 5)
108 ;; TRACE t3749: | | | | => 5
109 ;; TRACE t3748: | | | => 6
110 ;; TRACE t3747: | | => 7
111 ;; TRACE t3746: | => 8
119 (++ (dec a) (inc b))))
123 ;; user> (dotrace [++] (++ 4 5))
124 ;; TRACE t3766: (++ 4 5)
125 ;; TRACE t3767: | (++ 3 6)
126 ;; TRACE t3768: | | (++ 2 7)
127 ;; TRACE t3769: | | | (++ 1 8)
128 ;; TRACE t3770: | | | | (++ 0 9)
129 ;; TRACE t3770: | | | | => 9
130 ;; TRACE t3769: | | | => 9
131 ;; TRACE t3768: | | => 9
132 ;; TRACE t3767: | => 9
138 ;; ackerman functions
155 (defn f [n] (A 0 n)) ; f(n) = 2n
156 (defn g [n] (A 1 n)) ; g(n) = 2^n
159 ;; = A (0, A (1, n-1)) = f (A(1,n-1))
162 ;; = f (f (f ... f (1,(n- (n-1)))))
168 (defn h [n] (A 2 n)) ; h(n) = 2^(n^2)
170 ;; section 1.2.2: Tree Recursion
174 :else (+ (fib (- n 1))
178 (defn fib-iter [a b count]
181 (fib-iter (+ a b) a (dec count))))
186 ;; example: counting changes
187 (defn first-denomination [kinds-of-coins]
188 (cond (= kinds-of-coins 1) 1
189 (= kinds-of-coins 2) 5
190 (= kinds-of-coins 3) 10
191 (= kinds-of-coins 4) 25
192 (= kinds-of-coins 5) 50))
195 (defn first-denomination [kinds-of-coins]
196 ({1 1 2 5 3 10 4 25 5 50} kinds-of-coins))
198 (defn cc [amount kinds-of-coins]
200 (or (< amount 0) (= kinds-of-coins 0)) 0
201 :else (+ (cc amount (- kinds-of-coins 1))
203 (first-denomination kinds-of-coins))
206 (defn count-change [amount]
209 ;; exercise 1.11: A function f is defined by the rule that f(n) = n if n < 3
210 ;; and f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) if n> 3.
211 ;; Write a procedure that computes f by means of a recursive
212 ;; process. Write a procedure that computes f by means of an
213 ;; iterative process.
222 ;; user> (map f (range 10))
223 ;; (0 1 2 4 11 25 59 142 335 796)
226 ;; ex 1.11: iterative version
227 (defn f-iter [count prev0 prev1 prev2]
244 ;; ex 1.11: iterative version with let
245 (defn f-iter [count prev0 prev1 prev2]
246 (let [res (+ prev0 (* 2 prev1) (* 3 prev2))]
254 ;; exercise 1.12. The following pattern of numbers is called Pascal's triangle.
260 ;; ...................
262 ;; The numbers at the edge of the triangle are all 1, and each
263 ;; number inside the triangle is the sum of the two numbers above
264 ;; it. Write a procedure that computes elements of Pascal's triangle
265 ;; by means of a recursive process.
266 (defn pascal [row col]
268 (if (or (= col 0) (= row col))
270 (+ (pascal (dec row) col)
271 (pascal (dec row) (dec col))))))
275 See the pdfs in the directory for the answers.
280 (let [phi (/ (+ 1 (sqrt 5)) 2)]
281 (/ (expt phi n) (sqrt 5))))
284 ;; user> (map fib-approx (range 10))
285 ;; (0.4472135954999579 0.7236067977499789 1.1708203932499368 1.8944271909999157 3.065247584249853 4.959674775249769 8.024922359499623 12.984597134749393 21.009519494249016 33.99411662899841)
288 ;; exercise 1.14: tree of (count-changes 11)
290 See the pdf for the tree representation.
294 ;; order of size and computation
295 ;; see PDF, but below is the trace tree.
297 ;; user> (use 'clojure.contrib.trace)
299 ;; user> (dotrace [count-change cc] (count-change 11))
300 ;; TRACE t2609: (count-change 11)
301 ;; TRACE t2610: | (cc 11 5)
302 ;; TRACE t2611: | | (cc 11 4)
303 ;; TRACE t2612: | | | (cc 11 3)
304 ;; TRACE t2613: | | | | (cc 11 2)
305 ;; TRACE t2614: | | | | | (cc 11 1)
306 ;; TRACE t2615: | | | | | | (cc 11 0)
307 ;; TRACE t2615: | | | | | | => 0
308 ;; TRACE t2616: | | | | | | (cc 10 1)
309 ;; TRACE t2617: | | | | | | | (cc 10 0)
310 ;; TRACE t2617: | | | | | | | => 0
311 ;; TRACE t2618: | | | | | | | (cc 9 1)
312 ;; TRACE t2619: | | | | | | | | (cc 9 0)
313 ;; TRACE t2619: | | | | | | | | => 0
314 ;; TRACE t2620: | | | | | | | | (cc 8 1)
315 ;; TRACE t2621: | | | | | | | | | (cc 8 0)
316 ;; TRACE t2621: | | | | | | | | | => 0
317 ;; TRACE t2622: | | | | | | | | | (cc 7 1)
318 ;; TRACE t2623: | | | | | | | | | | (cc 7 0)
319 ;; TRACE t2623: | | | | | | | | | | => 0
320 ;; TRACE t2624: | | | | | | | | | | (cc 6 1)
321 ;; TRACE t2625: | | | | | | | | | | | (cc 6 0)
322 ;; TRACE t2625: | | | | | | | | | | | => 0
323 ;; TRACE t2626: | | | | | | | | | | | (cc 5 1)
324 ;; TRACE t2627: | | | | | | | | | | | | (cc 5 0)
325 ;; TRACE t2627: | | | | | | | | | | | | => 0
326 ;; TRACE t2628: | | | | | | | | | | | | (cc 4 1)
327 ;; TRACE t2629: | | | | | | | | | | | | | (cc 4 0)
328 ;; TRACE t2629: | | | | | | | | | | | | | => 0
329 ;; TRACE t2630: | | | | | | | | | | | | | (cc 3 1)
330 ;; TRACE t2631: | | | | | | | | | | | | | | (cc 3 0)
331 ;; TRACE t2631: | | | | | | | | | | | | | | => 0
332 ;; TRACE t2632: | | | | | | | | | | | | | | (cc 2 1)
333 ;; TRACE t2633: | | | | | | | | | | | | | | | (cc 2 0)
334 ;; TRACE t2633: | | | | | | | | | | | | | | | => 0
335 ;; TRACE t2634: | | | | | | | | | | | | | | | (cc 1 1)
336 ;; TRACE t2635: | | | | | | | | | | | | | | | | (cc 1 0)
337 ;; TRACE t2635: | | | | | | | | | | | | | | | | => 0
338 ;; TRACE t2636: | | | | | | | | | | | | | | | | (cc 0 1)
339 ;; TRACE t2636: | | | | | | | | | | | | | | | | => 1
340 ;; TRACE t2634: | | | | | | | | | | | | | | | => 1
341 ;; TRACE t2632: | | | | | | | | | | | | | | => 1
342 ;; TRACE t2630: | | | | | | | | | | | | | => 1
343 ;; TRACE t2628: | | | | | | | | | | | | => 1
344 ;; TRACE t2626: | | | | | | | | | | | => 1
345 ;; TRACE t2624: | | | | | | | | | | => 1
346 ;; TRACE t2622: | | | | | | | | | => 1
347 ;; TRACE t2620: | | | | | | | | => 1
348 ;; TRACE t2618: | | | | | | | => 1
349 ;; TRACE t2616: | | | | | | => 1
350 ;; TRACE t2614: | | | | | => 1
351 ;; TRACE t2637: | | | | | (cc 6 2)
352 ;; TRACE t2638: | | | | | | (cc 6 1)
353 ;; TRACE t2639: | | | | | | | (cc 6 0)
354 ;; TRACE t2639: | | | | | | | => 0
355 ;; TRACE t2640: | | | | | | | (cc 5 1)
356 ;; TRACE t2641: | | | | | | | | (cc 5 0)
357 ;; TRACE t2641: | | | | | | | | => 0
358 ;; TRACE t2642: | | | | | | | | (cc 4 1)
359 ;; TRACE t2643: | | | | | | | | | (cc 4 0)
360 ;; TRACE t2643: | | | | | | | | | => 0
361 ;; TRACE t2644: | | | | | | | | | (cc 3 1)
362 ;; TRACE t2645: | | | | | | | | | | (cc 3 0)
363 ;; TRACE t2645: | | | | | | | | | | => 0
364 ;; TRACE t2646: | | | | | | | | | | (cc 2 1)
365 ;; TRACE t2647: | | | | | | | | | | | (cc 2 0)
366 ;; TRACE t2647: | | | | | | | | | | | => 0
367 ;; TRACE t2648: | | | | | | | | | | | (cc 1 1)
368 ;; TRACE t2649: | | | | | | | | | | | | (cc 1 0)
369 ;; TRACE t2649: | | | | | | | | | | | | => 0
370 ;; TRACE t2650: | | | | | | | | | | | | (cc 0 1)
371 ;; TRACE t2650: | | | | | | | | | | | | => 1
372 ;; TRACE t2648: | | | | | | | | | | | => 1
373 ;; TRACE t2646: | | | | | | | | | | => 1
374 ;; TRACE t2644: | | | | | | | | | => 1
375 ;; TRACE t2642: | | | | | | | | => 1
376 ;; TRACE t2640: | | | | | | | => 1
377 ;; TRACE t2638: | | | | | | => 1
378 ;; TRACE t2651: | | | | | | (cc 1 2)
379 ;; TRACE t2652: | | | | | | | (cc 1 1)
380 ;; TRACE t2653: | | | | | | | | (cc 1 0)
381 ;; TRACE t2653: | | | | | | | | => 0
382 ;; TRACE t2654: | | | | | | | | (cc 0 1)
383 ;; TRACE t2654: | | | | | | | | => 1
384 ;; TRACE t2652: | | | | | | | => 1
385 ;; TRACE t2655: | | | | | | | (cc -4 2)
386 ;; TRACE t2655: | | | | | | | => 0
387 ;; TRACE t2651: | | | | | | => 1
388 ;; TRACE t2637: | | | | | => 2
389 ;; TRACE t2613: | | | | => 3
390 ;; TRACE t2656: | | | | (cc 1 3)
391 ;; TRACE t2657: | | | | | (cc 1 2)
392 ;; TRACE t2658: | | | | | | (cc 1 1)
393 ;; TRACE t2659: | | | | | | | (cc 1 0)
394 ;; TRACE t2659: | | | | | | | => 0
395 ;; TRACE t2660: | | | | | | | (cc 0 1)
396 ;; TRACE t2660: | | | | | | | => 1
397 ;; TRACE t2658: | | | | | | => 1
398 ;; TRACE t2661: | | | | | | (cc -4 2)
399 ;; TRACE t2661: | | | | | | => 0
400 ;; TRACE t2657: | | | | | => 1
401 ;; TRACE t2662: | | | | | (cc -9 3)
402 ;; TRACE t2662: | | | | | => 0
403 ;; TRACE t2656: | | | | => 1
404 ;; TRACE t2612: | | | => 4
405 ;; TRACE t2663: | | | (cc -14 4)
406 ;; TRACE t2663: | | | => 0
407 ;; TRACE t2611: | | => 4
408 ;; TRACE t2664: | | (cc -39 5)
409 ;; TRACE t2664: | | => 0
410 ;; TRACE t2610: | => 4
416 ;; TODO: orders of growth in space and number of steps.
418 ;; exercise 1.15: sin (x) calculation
419 ;; a. How many times is the procedure p applied when (sine 12.15)
421 ;; b. What is the order of growth in space and number of steps (as
422 ;; a function of a) used by the process generated by the sine
423 ;; procedure when (sine a) is evaluated?
424 (defn p [x] (- (* 3 x) (* 4 (cube x))))
427 (if (not (> (myabs angle) 0.1))
429 (p (sine (/ angle 3.0)))))
431 ;; solution to (a) => 5
433 ;; user> (dotrace [p] (sine 12.15))
434 ;; TRACE t2490: (p 0.049999999999999996)
435 ;; TRACE t2490: => 0.1495
436 ;; TRACE t2491: (p 0.1495)
437 ;; TRACE t2491: => 0.4351345505
438 ;; TRACE t2492: (p 0.4351345505)
439 ;; TRACE t2492: => 0.9758465331678772
440 ;; TRACE t2493: (p 0.9758465331678772)
441 ;; TRACE t2493: => -0.7895631144708228
442 ;; TRACE t2494: (p -0.7895631144708228)
443 ;; TRACE t2494: => -0.39980345741334
448 ;; both space and number of steps grows as log3(a) -> log a to the base 3.
451 ;; a * (1/3)^n <= 0.1
452 ;; => take log to the base 3 on both the sides.
454 ;; Note: Finding the order of space in a recursive process is sort of, equiv
455 ;; to finding the number of deferred operations. Which is in-turn the
456 ;; same as the depth of the evaluation tree.
458 ;; 1.2.4: exponentiation
462 (defn expt-iter [base counter product]
475 (* b (myexpt b (dec n)))))
478 (defn fast-expt [b n]
480 (even? n) (square (fast-expt b (/ n 2)))
481 :else (* b (fast-expt b (dec n)))))
487 (defn expt-iter [b n a]
489 (even? n) (expt-iter (square b) (/ n 2) a)
490 :else (expt-iter b (- n 1) (* a b))))
496 (+ a (mult a (- b 1)))))
499 ;; product = 2 * (a * (b/2)) for even b
500 ;; = a + (a * (b - 1)) for odd b
501 (defn fast-mult [a b]
504 (even? b) (twice (fast-mult a (half b)))
505 :else (+ a (fast-mult a (- b 1)))))
507 ;; exercise 1.18: iterative multiply thru addition
508 ;; the idea is to keep a state variable.
509 (defn fast-mult-iter [a b k]
511 (even? b) (fast-mult-iter (twice a) (half b) k)
512 :else (fast-mult-iter a (- b 1) (+ k a))))
514 (defn fast-mult-new [a b]
515 (fast-mult-iter a b 0))
518 ;; user> (dotrace [fast-mult-new fast-mult-iter] (fast-mult-new 2 3))
519 ;; TRACE t2915: (fast-mult-new 2 3)
520 ;; TRACE t2916: | (fast-mult-iter 2 3 0)
521 ;; TRACE t2917: | | (fast-mult-iter 2 2 2)
522 ;; TRACE t2918: | | | (fast-mult-iter 4 1 2)
523 ;; TRACE t2919: | | | | (fast-mult-iter 4 0 6)
524 ;; TRACE t2919: | | | | => 6
525 ;; TRACE t2918: | | | => 6
526 ;; TRACE t2917: | | => 6
527 ;; TRACE t2916: | => 6
532 ;; exercise 1.19: fast fibonacci
533 ;; see the pdf of the notebook scan for the derivation of p' and q'
534 (defn ffib-iter [a b p q count]
540 (+ (* 2 p q) (* q q))
542 :else (ffib-iter (+ (* b q) (* a q) (* a p))
549 (ffib-iter 1 0 0 1 n))
551 ;;; Section 1.2.5: GCD
555 (mygcd b (rem a b))))
559 ;; normal order - 18, applicative order - 4.
561 ;; too lazy to scan things from the notebook. May be I should instead
564 ;;; section 1.2.6 Primality testing.
566 (= (smallest-divisor n) n))
568 (defn smallest-divisor [n]
571 (defn find-divisor [n test-divisor]
572 (cond (> (square test-divisor) n) n
573 (divides? test-divisor n) test-divisor
574 :else (find-divisor n (inc test-divisor))))
579 ;; fermat's little theorem
580 (defn expmod [base exp m]
582 (even? exp) (rem (square (expmod base (/ exp 2) m))
584 :else (rem (* base (expmod base (dec exp) m))
587 (defn fermat-test [n]
588 (try-it (+ 1 (rand-int (- n 1))) n))
591 (= a (expmod a n n)))
593 (defn fast-prime? [n times]
594 (cond (= times 0) true
595 (fermat-test n) (fast-prime? n (dec times))
600 user> (smallest-divisor 199)
602 user> (smallest-divisor 1999)
604 user> (smallest-divisor 19999)
609 (defn timed-prime-test [n]
612 (start-prime-test n (System/nanoTime)))
614 (defn start-prime-test [n start-time]
616 (report-prime (- (System/nanoTime) start-time))))
618 (defn report-prime [elapsed-time]
620 (print elapsed-time))
622 (defn search-for-primes [a b]
624 (even? a) (search-for-primes (+ 1 a) b)
625 (timed-prime-test a) (search-for-primes (+ 2 a) b)
626 :else (search-for-primes (+ 2 a) b)))
628 ;;; three smallest primes greater than 1000
630 (take 3 (filter #(prime? %) (iterate inc 1000)))
633 ;=> 0.9642028750000001
635 ;;; > 10,000: 10007, 10009, 10037
636 (take 3 (filter #(prime? %) (iterate inc 10000)))
637 ;=> (10007 10009 10037)
639 ;=> 1.5897884999999998
641 ;;; > 100,000: 100003, 100019, 100043
642 (take 3 (filter #(prime? %) (iterate inc 100000)))
643 ;=> (100003 100019 100043)
645 ;=> 1.8525091250000003
647 ;;; > 1,000,000: 1000003, 1000033, 1000037
648 (take 3 (filter #(prime? %) (iterate inc 1000000)))
649 ;=> (1000003 1000033 1000037)
653 ;; time taken seem to increase as the range increases.
654 ;; but they are totally random on the jvm, so I can't find
655 ;; the exact relation.
658 user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 1000))))
671 Total runtime: 0.28404500000000005
672 Highest time : 0.083949
673 Lowest time : 0.019416
674 Average : 0.022585000000000008
675 (0.083949 0.019416 0.023257 0.020394 0.024165 0.024514 0.024374 0.020813 0.021721 0.021442)
676 user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 10000))))
689 Total runtime: 0.26462800000000003
690 Highest time : 0.067118
691 Lowest time : 0.020533
692 Average : 0.022122125000000006
693 (0.067118 0.022698 0.024095 0.023537 0.020533 0.020882 0.020603 0.021372 0.020603 0.023187)
694 user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 100000))))
697 (100003 100019 100043)
698 (100003 100019 100043)
699 (100003 100019 100043)
700 (100003 100019 100043)
701 (100003 100019 100043)
702 (100003 100019 100043)
703 (100003 100019 100043)
704 (100003 100019 100043)
705 (100003 100019 100043)
706 (100003 100019 100043)
707 Total runtime: 0.265118
708 Highest time : 0.073263
709 Lowest time : 0.020254
710 Average : 0.021450125000000004
711 (0.073263 0.023048 0.023467 0.021022 0.020394 0.020254 0.021302 0.020812 0.020743 0.020813)
714 ;;; can't make out any sqrt(10) relation between the numbers. may be because
715 ;;; jvm compilation is doing some behind the scene tricks.
718 (defn next-divisor [n]
724 (defn find-divisor [n test-divisor]
725 (cond (> (square test-divisor) n) n
726 (divides? test-divisor n) test-divisor
727 :else (find-divisor n (next-divisor test-divisor))))
730 I can't see any noticable difference in the speed.
735 (microbench 10 (take 3 (filter #(fast-prime? %) (iterate inc 1000))))
737 "I did not observe any difference".
741 (defn expmod [base exp m]
742 (rem (fast-expt base exp) m))
745 In the case of the original expmod implementation, square and remainder
746 calls are interspersed, so square always deals with a small number, whereas
747 with the above way, we do a series of squaring and then in the end take
748 remainder. Squaring of big numbers are very inefficient as the CPU has to
749 do multi-byte arithmetic which consumes many cycles.
751 So the new version is several times slower than the original.
756 "Instead of calling (square x), Louis now makes does (* x x). In the former,
757 case, x is evaluated only once, where as in the second, x gets evaluated
758 2x, 4x, 8x, 16x and so on (for any x which is recursive). So, if the original
759 computation is considered T(log_n), then the new process T(n). This can also
760 be illustrated with the call tree."
765 "Some notes on Carmichael numbers: Carmichael numbers are those that fail
766 Fermat little test. That is, for any n in the Carmichael set,
768 (fermat-test n) => true."
770 (defn brute-force-fermat-test [n]
775 (try-it a n) (try-all (inc a) n)
778 "all the given numbers pass the above test, i.e. for every a < n,
779 a^n mod n === a mod n"
780 user> (brute-force-fermat-test 561)
782 user> (brute-force-fermat-test 1105)
784 user> (brute-force-fermat-test 1729)
786 user> (brute-force-fermat-test 2465)
788 user> (brute-force-fermat-test 2821)
790 user> (brute-force-fermat-test 6601)
795 (defn expmod2 [base exp m]
797 (even? exp) (square-test (expmod2 base (/ exp 2) m) m)
798 :else (rem (* base (expmod2 base (dec exp) m))
801 (defn square-test [x m]
802 (if (and (not (or (= x 1) (= x (- m 1))))
803 (= (rem (square x) m) 1))
807 (defn miller-rabin-test [n]
808 (try-it (+ 2 (rand-int (- n 2)))
812 (= (expmod2 a (- n 1) n) 1))
815 "If the random number generated (a) is 1, then this returns false
816 positives. So generate random numbers between 2 and n-1. (is this
817 assumption correct?) "