(import (scheme base) (scheme file) (scheme process-context) (scheme write)) (include "../common.scm") (define (direction->arithmetic direction) (cond ((char=? direction #\L) -) ((char=? direction #\R) +))) (define (part1 file) (with-input-from-file file (lambda () (let loop ((dial 50) (line (read-line)) (zeros 0)) (if (eof-object? line) (number->string zeros) (let* ((direction (string-ref line 0)) (distance (string->number (substring line 1 (string-length line)))) (new-dial (modulo ((direction->arithmetic direction) dial distance) 100))) (loop new-dial (read-line) (if (zero? new-dial) (+ 1 zeros) zeros)))))))) (define (pseudo-modulo/count-wraps a b) (let loop ((n a) (wraps 0)) (cond ((zero? n) (values n (+ 1 wraps))) ((negative? n) (loop (+ n b) (+ 1 wraps))) ((= n b) (values 0 (+ 1 wraps))) ((> n b) (loop (- n b) (+ 1 wraps))) (else (values n wraps))))) ;; Could be improved... (define (part2 file) (with-input-from-file file (lambda () (let loop ((dial 50) (zeros 0) (line (read-line))) (if (eof-object? line) (number->string zeros) (let* ((direction (string-ref line 0)) (distance (string->number (substring line 1 (string-length line)))) (dial+-distance ((direction->arithmetic direction) dial distance))) (let-values (((new-dial add-zeros) (pseudo-modulo/count-wraps dial+-distance 100))) (loop new-dial (+ zeros add-zeros (if (and (zero? dial) (negative? dial+-distance)) -1 0)) (read-line))))))))) (for-each print (map part1 (command-line-arguments))) (for-each print (map part2 (command-line-arguments)))