#!/usr/local/bin/chicken-csi -ss (import (chicken string) (chicken port) (chicken irregex) (chicken sort) (chicken io)) (define (parse line) ;; HACK: Instead of writing a parser, leverage (read) (let* ((t1 (irregex-replace/all "\\[" line "(")) (t2 (irregex-replace/all "]" t1 ")")) (t3 (irregex-replace/all "," t2 " "))) (with-input-from-string t3 (lambda () (read))))) (define (good? pair) (let ((l (car pair)) (r (cadr pair))) (cond ((and (null? l) (null? r)) '()) ; passed the check ((null? l) #t) ; left ran out first ((null? r) #f) ; right ran out first ((and (number? l) (number? r)) (cond ((< l r) #t) ((> l r) #f) (else '()))) ; null => keep checking ((number? l) (good? (list (list l) r))) ((number? r) (good? (list l (list r)))) ; compare items in lists (else (let ((g (good? (list (car l) (car r))))) (cond ((null? g) (good? (list (cdr l) (cdr r)))) ((eq? g #f) #f) ((eq? g #t) #t) (else "Bad result"))))))) (define (parse-pairs lines) (let loop ((lines lines)) (if (null? lines) '() (let ((left (parse (car lines))) (right (parse (cadr lines)))) ; NOTE: not robust to bad input... (cdddr) (cons (list left right) (loop (cdddr lines))))))) (define (parse-all lines) (let loop ((lines (append lines '("[[2]]" "[[6]]")))) (if (null? lines) '() (if (equal? (car lines) "") (loop (cdr lines)) (cons (parse (car lines)) (loop (cdr lines))))))) (define (score pairs) (let loop ((sum 0) (i 1) (ps pairs)) (if (null? ps) sum (if (good? (car ps)) (loop (+ i sum) (add1 i) (cdr ps)) (loop sum (add1 i) (cdr ps)))))) (define (index lst obj) ;; why 1 indexed, advent of code?? (let loop ((i 1) (items lst)) (cond ((null? items) #f) ((equal? (car items) obj) i) (else (loop (add1 i) (cdr items)))))) (define (signal all) (let ((sorted (sort all (lambda (x y) (good? (list x y)))))) (* (index sorted '((2))) (index sorted '((6)))))) (define (main args) (let* ((lines (read-lines)) (pairs (parse-pairs lines)) (all (parse-all lines))) (print (score pairs)) (print (signal all))))