#!/usr/local/bin/chicken-csi -ss (import (chicken io)) (define (sum lst) (apply + lst)) (define (prio c) (if (char-upper-case? c) (- (char->integer c) 38) ; #\A -> 65 - 38 = 27 (- (char->integer c) 96))) ; \#a -> 97 - 96 = 1 (define (append-if-absent x lst) (if (member x lst) lst (cons x lst))) ; (1 2 3 4) -> ((1 2) (3 4)) (define (bisect lst) (let ((len (length lst))) (define (bi lst a b) (cond ((null? lst) (list a b)) ((> (length lst) (/ len 2)) (bi (cdr lst) (append-if-absent (car lst) a) b)) (else (bi (cdr lst) a (append-if-absent (car lst) b))))) (bi lst '() '()))) (define (score-pack pk) (let* ((parts (bisect pk)) (l (car parts)) (r (cadr parts))) (sum (map (lambda (x) (if (member x r) (prio x) 0)) l)))) ; lots of member checks.. could use a better data structure ; than linked lists (hash tables) if this was slow / large input (define (uniq lst) (if (null? lst) lst (if (member (car lst) (cdr lst)) (uniq (cdr lst)) (cons (car lst) (uniq (cdr lst)))))) (define (score-group a b c) (sum (map (lambda (x) (if (and (member x b) (member x c)) (prio x) 0)) a))) (define (part-2 packs) (let loop ((i 0) (score 0) (pks (map uniq packs))) (if (null? pks) score (if (= (modulo i 3) 0) (loop (add1 i) (+ score (score-group (car pks) (cadr pks) (caddr pks))) (cdr pks)) (loop (add1 i) score (cdr pks)))))) (define (main args) (let* ((lines (read-lines)) (packs (map string->list lines)) (scores-1 (map score-pack packs)) (score-2 (part-2 packs))) (print (sum scores-1)) (print score-2)))