diff options
Diffstat (limited to 'cube-conundrum/cc.scm')
-rw-r--r-- | cube-conundrum/cc.scm | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/cube-conundrum/cc.scm b/cube-conundrum/cc.scm new file mode 100644 index 0000000..de62808 --- /dev/null +++ b/cube-conundrum/cc.scm @@ -0,0 +1,110 @@ +(define-module (cc) + #:use-module (srfi srfi-1) + #:export (cc + filter-possible-games + games->at-least + game->seen + draw->colors + take-max-instances)) + + +(define (cc str red green blue) + "Given STR, a list of games and their +corresponding draws, as well as RED, GREEN, +and BLUE, the total amount of cubes actually +possessed, return the sum of the possible game +ids, as well as the total power." + (let ((games (games->at-least str))) + (cons + (apply + (map car + (filter-possible-games games + (list red green blue)))) + (calculate-total-power games)))) + +(define (calculate-total-power games) + "Given an alist of games, calculates the total +'power'. The power of one game is product the minimum +number of cubes required to make the game possible." + (apply + (map (lambda (x) + (apply * (cdr x))) + games))) + +(define (filter-possible-games games have-rgb) + (filter (lambda (x) + (list<=? (cdr x) have-rgb)) + games)) + +(define (list<=? lst1 lst2) + (cond + ((null? lst1) #t) + ((null? lst2) #f) + ((< (car lst2) (car lst1)) #f) + (#t (list<=? (cdr lst1) (cdr lst2))))) + +(define (games->at-least str) + "Given STR containing a new-line separated list +of games and their corresponding draws, returns an +alist containing the game identifiers as keys and a +list numbers of each cube that must be present for +the game to be possible." + (let ((ret '())) + (map (lambda (line) + (unless (string-null? line) + (let* ((gd-pair (string-split line #\:)) + (num (string->number (substring (car gd-pair) 5))) + (draws (cadr gd-pair))) + (set! ret (acons num (game->seen draws) ret))))) + (string-split + (string-trim-both str char-set:whitespace) + #\newline)) + ret)) + +(define (game->seen str) + "Given a single round of draws: + +8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red + +Produces a list of numbers representing the +maximum amount of each color seen at a time: +'(20 13 6)" + (let loop ((draws (string-split str #\;)) (cur-rgb '(0 0 0))) + (if (null? draws) + cur-rgb + (loop (cdr draws) + (take-max-instances + cur-rgb + (draw->colors (car draws))))))) + +(define (draw->colors str) + "Given a string of a single draw, i.e.: +3 blue, 4 red + +returns a list of numbers representing the +corresponding RGB: + +'(4 0 3)" + (let loop ((colors (string-split str #\,)) + (red 0) (green 0) (blue 0)) + (if (or (null? colors) + (zero? (string-length (car colors)))) + (list red green blue) + (let* ((nc-pair (string-split (string-trim (car colors)) #\space)) + (num (string->number (car nc-pair))) + (color (cadr nc-pair))) + (cond + ((equal? color "red") + (set! red num)) + ((equal? color "green") + (set! green num)) + ((equal? color "blue") + (set! blue num))) + (loop (cdr colors) red green blue))))) + +(define (take-max-instances cur-rgb new-rgb) + "Given two lists representing a count +of RGB cubes, return a new list that is +the max of each element-wise." + (map (lambda (c-pair) + (max (car c-pair) + (cadr c-pair))) + (zip cur-rgb new-rgb))) |