aboutsummaryrefslogtreecommitdiff
path: root/aoc/2021/day04/part01.neb
blob: 49b4a7a17adae3ea30eedbb44846d81b74297d9c (plain)
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
;; https://adventofcode.com/2021/day/4

; good candidate for loop-acc
(func get-all-boards (inp)
    (def ret (list))
    (for-count (/ (length inp) 5)
        (redef ret (append ret
            (get-board (slice inp (+ (* 5 (- _idx_ 1)) 1) 5)))))
    ret)

(func get-board (inp)
    (map get-row inp))

; each row is a string of items
; separated by (potentially) several spaces
; return a list of just the strings
(func get-row (row)
    (filter
        (lambda (x)
            (not (eq? "" x)))
        (split row " ")))
            

(func process-boards (inp)
    (def raw-boards
        (filter
            (lambda (x) (not (eq? "" x)))
            inp))
    (get-all-boards raw-boards))

(def lines
    (map strip
        (read-lines "input.txt")))

(def moves (split (first lines) ",")) ; moves is the first line
(def boards (process-boards (rest lines)))

; this is a helper to work with zippers
; probably good to have in the stdlib
(func unzip (lst idx)
    (list
        (reverse
            (slice lst 1 idx))
        (slice lst (+ 1 idx))))

(func has-won-row (row)
    (apply and row))

(func has-won (board moves)
    (def checked (check-board board moves))
    (def winner #false)

    ; check rows
    ; no break statement means we have to check everything,
    ; even after a winner is found
    ; can also use a while, but that would require more redefs
    (for-each checked
        (if (has-won-row _item_)
            (redef winner #true)))

    ; no break here means we check columns even if we won on rows

    ; check columns
    (for-count 5
        (if (has-won-row
                (map 
                    (lambda (x) (first (slice x _idx_ 1)))
                    checked))
            (redef winner #true)))

    winner)
    

(func check-board (board moves)
    (func check-row (row)
        (map
            (lambda (x)
                (in? x moves))
            row))
    (map check-row board))


; how do we better iterate through this list?
; called/next would be perfect for a zipper
(def cur (list (list) moves))  ; init zip
(def winner #false)
(while (not winner)
    (redef cur (unzip moves (+ 1 (length (first cur)))))
    (print (->string cur))
    (print (->string
        (map
            (lambda (x) (has-won x (first cur)))
            boards)))
    ;(def checked (check-board (first boards) (first cur)))
    ;(print (->string checked))
    (if (nil? (last cur))
        (redef winner #true))
    )

(print (->string moves))
;(print (->string (unzip moves 2)))