1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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)))
|