; the last prime digit
(import (rnrs hashtables (6)))
(define (make-matrix rows columns . value)
(do ((m (make-vector rows)) (i 0 (+ i 1)))
((= i rows) m)
(if (null? value)
(vector-set! m i (make-vector columns))
(vector-set! m i (make-vector columns (car value))))))
(define (matrix-ref m i j) (vector-ref (vector-ref m i) j))
(define (matrix-set! m i j x) (vector-set! (vector-ref m i) j x))
(define (primegen)
(let ((ps #f) (p #f) (q #f) (c #f) (d (make-eq-hashtable)))
(lambda ()
(define (add m s)
(do () ((not (hashtable-ref d m #f))) (set! m (+ m s)))
(hashtable-set! d m s))
(cond ((not p) (set! p #t) 2) ((not q) (set! q #t) 3)
(else (when (not ps) (set! ps (primegen)) (set! c 5)
(set! p (and (ps) (ps))) (set! q (* p p)))
(let loop ()
(cond ((hashtable-ref d c #f) =>
(lambda (s)
(hashtable-delete! d c)
(add (+ c s) s)
(set! c (+ c 2)) (loop)))
((< c q) (let ((x c)) (set! c (+ c 2)) x))
(else (add (+ c p p) (+ p p))
(set! p (ps)) (set! q (* p p))
(set! c (+ c 2)) (loop)))))))))
(define (grimes n)
(let ((ps (primegen)) (counts (make-matrix 4 4 0)))
(ps) (ps) (ps) ; discard 2,3,5
(let loop ((prev (ps)) (n (- n 4)))
(if (zero? n) counts
(let ((curr (modulo (ps) 10)))
(matrix-set! counts (quotient prev 3) (quotient curr 3)
(+ 1 (matrix-ref counts (quotient prev 3) (quotient curr 3))))
(loop curr (- n 1)))))))
(display (grimes 1000))