; blockchain
(define (fold-left op base xs)
(if (null? xs)
base
(fold-left op (op base (car xs)) (cdr xs))))
(define (range . args)
(case (length args)
((1) (range 0 (car args) (if (negative? (car args)) -1 1)))
((2) (range (car args) (cadr args) (if (< (car args) (cadr args)) 1 -1)))
((3) (let ((le? (if (negative? (caddr args)) >= <=)))
(let loop ((x(car args)) (xs '()))
(if (le? (cadr args) x)
(reverse xs)
(loop (+ x (caddr args)) (cons x xs))))))
(else (error 'range "unrecognized arguments"))))
(define seed 20180525)
(define (random) (set! seed (modulo (* 16807 seed) 2147483647)) seed)
(define (randint n) (floor (* n (random) (/ 2147483647))))
(define (shuffle x)
(do ((v (list->vector x)) (n (length x) (- n 1)))
((zero? n) (vector->list v))
(let* ((r (randint n)) (t (vector-ref v r)))
(vector-set! v r (vector-ref v (- n 1)))
(vector-set! v (- n 1) t))))
(define t (list->vector (shuffle (range 256))))
(define (pearson8 str)
(fold-left (lambda (n h) (vector-ref t (modulo (+ n h) 256)))
0 (map char->integer (string->list str))))
(define (index block) (vector-ref block 0))
(define (datum block) (vector-ref block 1))
(define (phash block) (vector-ref block 2))
(define (chash block) (vector-ref block 3))
(define (hash index datum phash)
(pearson8 (string-append (number->string index) datum (number->string phash))))
(define genesis (vector 0 "Genesis Block" 0 (hash 0 "Genesis Block" 0)))
(define (adjoin chain datum)
(let ((index (+ (index (car chain)) 1)) (phash (chash (car chain))))
(cons (vector index datum phash (hash index datum phash)) chain)))
(define (validate? chain)
(define (valid? curr prev)
(and (= (index curr) (+ (index prev) 1))
(= (phash curr) (chash prev))
(= (hash (index curr) (datum curr) (phash curr)) (chash curr))))
(if (null? (cdr chain)) (equal? (car chain) genesis)
(and (valid? (car chain) (cadr chain)) (validate? (cdr chain)))))
(define b (list genesis))
(set! b (adjoin b "Pearson Hashing"))
(set! b (adjoin b "Floyd's Triangle"))
(set! b (adjoin b "Billing Period"))
(set! b (adjoin b "Sum Embedded Numbers"))
(set! b (adjoin b "Help Wanted: Report Generator"))
(display b) (newline)
(display (validate? b)) (newline)