diff options
-rw-r--r-- | closure/closure-test.scm | 59 | ||||
-rw-r--r-- | closure/closure.scm | 32 | ||||
-rw-r--r-- | coin-sums/cs-test.scm | 45 | ||||
-rw-r--r-- | coin-sums/cs.scm | 27 | ||||
-rw-r--r-- | iterative-add/iterative-add-test.scm | 20 | ||||
-rw-r--r-- | iterative-add/iterative-add.scm | 15 | ||||
-rw-r--r-- | number-spiral-diagonals/README.org | 34 | ||||
-rw-r--r-- | number-spiral-diagonals/nsd-test.scm | 58 | ||||
-rw-r--r-- | number-spiral-diagonals/nsd.scm | 27 |
9 files changed, 282 insertions, 35 deletions
diff --git a/closure/closure-test.scm b/closure/closure-test.scm new file mode 100644 index 0000000..ae10b67 --- /dev/null +++ b/closure/closure-test.scm @@ -0,0 +1,59 @@ +;; -*- compile-command: "guile -L . closure-test.scm"; -*- +(use-modules (srfi srfi-64) + (closure)) + +(define iterative-add-generator-1 + (iterative-add)) + +(define iterative-add-generator-2 + (iterative-add)) + +(test-begin "harness") + +(test-equal "add 0 to 1" + 1 + (iterative-add-generator-1 1)) + +(test-equal "add 1 to 2" + 3 + (iterative-add-generator-1 2)) + +(test-equal "add 2 to 6" + 8 + (iterative-add-generator-1 6)) + +(test-equal "add 6 to 5" + 11 + (iterative-add-generator-1 5)) + +(test-equal "add 0 to 2" + 2 + (iterative-add-generator-2 2)) + +(test-equal "add 2 to 2" + 4 + (iterative-add-generator-2 2)) + + +(set-store (string->list "abcdefghijklmnopqrstuvwxyz")) + +;;; never returns, but manual validation shows +;;; the function works. Bug in testing library? +;; (test-equal "peek-char first" +;; #\a +;; (peek-char)) + +(test-equal "advance-char first" + #\a + (advance-char)) + +(test-equal "advance-char second" + #\b + (advance-char)) + +;; (test-equal "peek-char second" +;; #\c +;; (peek-char)) + + +(test-end "harness") diff --git a/closure/closure.scm b/closure/closure.scm new file mode 100644 index 0000000..9dec47e --- /dev/null +++ b/closure/closure.scm @@ -0,0 +1,32 @@ +(define-module (closure) + #:export (iterative-add + set-store + peek-store + advance-char)) + +(define (iterative-add) + "Given NUM, returns NUM plus the previous +supplied NUM." + (let ((prev-num 0)) + (lambda num + (let ((result + (+ (car num) prev-num))) + (set! prev-num (car num)) + result)))) + +(define set-store #f) +(define peek-char #f) +(define advance-char #f) + +(let ((store '())) + (set! set-store + (lambda (lst) + (set! store lst))) + (set! peek-char + (lambda () + (car store))) + (set! advance-char + (lambda () + (let ((ret (car store))) + (set! store (cdr store)) + ret)))) diff --git a/coin-sums/cs-test.scm b/coin-sums/cs-test.scm new file mode 100644 index 0000000..30fe65c --- /dev/null +++ b/coin-sums/cs-test.scm @@ -0,0 +1,45 @@ +;; -*- compile-command: "guile -L . cs-test.scm"; -*- +(use-modules (srfi srfi-64) + (cs)) + + +(test-begin "harness") + +(define den '(1)) + +(test-equal "make one from ones" + '(1) + (cs 1 den)) + +(test-equal "make two from ones" + '(1 1) + (cs 2 den)) + +(set! den '(1 2)) + +(test-equal "make one from ones, twos" + '(1) + (cs 1 den)) + +(test-equal "make two from ones, twos" + '(1 2) + (cs 2 den)) + +(set! den '(2 3 5)) + +(test-equal "make 3 from twos, threes, fives" + '(0 1 1) + (cs 3 den)) + +(test-equal "make 5 from twos, threes, fives" + '(0 1 1 1 2) + (cs 5 den)) + +(set! den '(1 2 5 10 20 50 100 200)) + +(test-equal "make 8 from pence" + '(1 2 2 3 4 5 6 7 8 11 12 15 16) + (cs 13 den)) + + +(test-end "harness") diff --git a/coin-sums/cs.scm b/coin-sums/cs.scm new file mode 100644 index 0000000..1df83e9 --- /dev/null +++ b/coin-sums/cs.scm @@ -0,0 +1,27 @@ +(define-module (cs) + #:export (cs)) + +(define (cs limit denominations) + "Given DENOMINATIONS of available coins, +calculates the total number of different coins +which combine to LIMIT worth." + + (define (count-coins coins ut) + "Calculates the total of combinations with +the lowest coin denomination first, then recursively +adds coins of increasing worth, indexing previous results. +This is the dynamic programming approach." + (if (null? coins) + ut + (let ((coin (car coins))) + (for-each (lambda (a) + (vector-set! ut a (+ (vector-ref ut a) + (vector-ref ut (- a coin))))) + (iota (- (1+ limit) coin) coin 1)) + (count-coins (cdr coins) ut)))) + + (let ((ut (make-vector (1+ limit) 0))) + (vector-set! ut 0 1) + (cdr (vector->list (count-coins + (filter (lambda (x) (>= limit x)) denominations) + ut))))) diff --git a/iterative-add/iterative-add-test.scm b/iterative-add/iterative-add-test.scm deleted file mode 100644 index d318570..0000000 --- a/iterative-add/iterative-add-test.scm +++ /dev/null @@ -1,20 +0,0 @@ -;; -*- compile-command: "guile -L . iterative-add-test.scm"; -*- -(use-modules (srfi srfi-64) - (iterative-add)) - - -(test-begin "harness") - -(test-equal "add 0 to 1" - 1 - (iterative-add-generator 1)) - -(test-equal "add 1 to 2" - 3 - (iterative-add-generator 2)) - -(test-equal "add 2 to 6" - 8 - (iterative-add-generator 6)) - -(test-end "harness") diff --git a/iterative-add/iterative-add.scm b/iterative-add/iterative-add.scm deleted file mode 100644 index 45c6cf9..0000000 --- a/iterative-add/iterative-add.scm +++ /dev/null @@ -1,15 +0,0 @@ -(define-module (iterative-add) - #:export (iterative-add-generator)) - -(define iterative-add - (let ((prev-num 0)) - (lambda (num) - (let ((result - (+ num prev-num))) - (set! prev-num num) - result)))) - -(define (iterative-add-generator num) - "Adds the previously received -number to the current one." - (iterative-add num)) diff --git a/number-spiral-diagonals/README.org b/number-spiral-diagonals/README.org new file mode 100644 index 0000000..b3daba9 --- /dev/null +++ b/number-spiral-diagonals/README.org @@ -0,0 +1,34 @@ +* Solver for https://projecteuler.net/problem=28 + +The above problem displays an interesting looking square of numbers (generated by counting up from one in a spiral pattern) and asks us to sum the diagonal for a very large square. + +In some cases to my detriment, I always try to look for a magical formula that will solve every problem. + +In this case, that is possible! We need only recognize that the numbers we are asked to sum belong to a sequence: + +The sequence: {1, 3, 5, 7, 9, 13, 17, 21, 25, 31, 37, 43, 49, 57...} + +We see that all of the numbers are odd. Further, we see that the first four numbers in the sequence are spaced two numbers apart. The next four numbers are all four numbers apart, then six numbers, then eight, etc. + +** Solution + +My solution is to implement a formula that can generate number /N/ (zero-indexed) in the sequence given the F_N_-1 (in other words, the preceeding number in the sequence. The formula is this: + +F_n = F_n_-1 + 2 * (((n-1) // 4) + 1) + +Here is an example of calculating the ninth number in the sequence (25): + +(zero indexed!) +F_8 = F_7 + 2 * ((8-1) // 4) + 1) +F_8 = 21 + 2 * (1 + 1) +F_8 = 25 + +And the tenth number: + +F_9 = F_8 + 2 * ((9-1) // 4) + 1) +F_9 = 25 + 2 * (2 + 1) +F_9 = 25 + 6 +F_9 = 31 + + +The scheme itself looks nicer than the formula. diff --git a/number-spiral-diagonals/nsd-test.scm b/number-spiral-diagonals/nsd-test.scm new file mode 100644 index 0000000..bcad616 --- /dev/null +++ b/number-spiral-diagonals/nsd-test.scm @@ -0,0 +1,58 @@ +;; -*- compile-command: "guile -L . nsd-test.scm"; -*- +(use-modules (srfi srfi-64) + (nsd)) + + +(test-begin "harness") + + +(test-equal "calculate-seq-length 1x1" + 1 + (calculate-seq-length 1)) + +(test-equal "calculate-seq-length 3x3" + 5 + (calculate-seq-length 3)) + +(test-equal "calculate-seq-length 5x5" + 9 + (calculate-seq-length 5)) + +(test-equal "nsd-generator size 1" + '(1) + (nsd-generator 1)) + +(test-equal "nsd-generator size 2" + '(1 3) + (nsd-generator 2)) + +(test-equal "nsd-generator max two inc" + '(1 3 5 7 9) + (nsd-generator 5)) + +(test-equal "nsd-generator four inc" + '(1 3 5 7 9 13) + (nsd-generator 6)) + +(test-equal "nsd-generator six inc" + '(1 3 5 7 9 13 17 21 25 31) + (nsd-generator 10)) + +(test-equal "nsd-generator eight inc" + '(1 3 5 7 9 13 17 21 25 31 37 43 49 57) + (nsd-generator 14)) + +(test-equal "nsd add 1x1" + 1 + (nsd 1)) + +(test-equal "nsd add 3x3" + 25 + (nsd 3)) + +(test-equal "nsd add 7x7" + 261 + (nsd 7)) + + +(test-end "harness") diff --git a/number-spiral-diagonals/nsd.scm b/number-spiral-diagonals/nsd.scm new file mode 100644 index 0000000..9d4bfe3 --- /dev/null +++ b/number-spiral-diagonals/nsd.scm @@ -0,0 +1,27 @@ +(define-module (nsd) + #:export (nsd + nsd-generator + calculate-seq-length)) + + +(define (nsd n) + "Given dimension N of a square, calculates and sums +an appropriately sized sequence." + (apply + (nsd-generator (calculate-seq-length n)))) + +(define (nsd-generator k) + "Generates a sequence of numbers corresponding to the +diagonals in a square. See README for more details on how +this is used to solve the problem." + (let loop ((i 0) + (lst '(1))) + (if (>= (1+ i) k) + (reverse lst) + (loop (1+ i) + (cons (+ (car lst) (* 2 (1+ (quotient i 4)))) lst))))) + +(define (calculate-seq-length n) + "Calculates the size of the sequence. This is equal to +the length of the two diagonals, minus one for the overlapping +center." + (1- (* 2 n))) |