-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path04.rhm
157 lines (137 loc) · 4.25 KB
/
04.rhm
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#lang rhombus/static/and_meta
import:
"util/advent_of_code.rhm" as aoc
"util/misc.rhm" open
lib("racket/base.rkt") as rkt:
only #{procedure-rename}
@example_input(test_input1){
MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX
}
annot.macro 'Posn': 'Pair.of(NonnegInt, NonnegInt)'
class Grid(lines :: List.of(String), width :: NonnegInt, height :: NonnegInt):
property rows :~ Range: 0 .. height
property cols :~ Range: 0 .. width
constructor (s :: String):
let ls = s.split("\n")
super(ls, ls[0].length(), ls.length())
method get(r :: NonnegInt, c :: NonnegInt):
lines[r][c]
class WordState(row :: NonnegInt,
col :: NonnegInt,
// (NonnegInt, NonnegInt) -> maybe(WordState)
// or #false
_next):
method next():
if _next
| _next(row, col)
| this
fun make_next_fun(who, dr :: Int, dc :: Int):
fun (g :: Grid):
def g_rows = g.rows
def g_cols = g.cols
fun _next(r, c):
def new_r = r + dr
def new_c = c + dc
g_rows.has_element(new_r)
&& g_cols.has_element(new_c)
&& WordState(new_r, new_c, next)
// rename this to make WordState more readable
def next = rkt.#{procedure-rename}(_next, who)
next
def n = make_next_fun(#'n, -1, 0)
def ne = make_next_fun(#'ne, -1, 1)
def e = make_next_fun(#'e, 0, 1)
def se = make_next_fun(#'se, 1, 1)
def s = make_next_fun(#'s, 1, 0)
def sw = make_next_fun(#'sw, 1, -1)
def w = make_next_fun(#'w, 0, -1)
def nw = make_next_fun(#'nw, -1, -1)
fun get_puzzle_input():
aoc.fetch_input(aoc.find_session(), 2024, 4)
fun run1(input):
def g = Grid(input)
// RRR: why don't these properties statinfo propagate?
def init_state :~ List.of(WordState):
block:
use_dynamic
for List:
each r: g.rows
each c: g.cols
each dir: [n, ne, e, se, s, sw, w, nw]
WordState(r, c, dir(g))
def result :~ List:
block:
def xma_state:
for values(state :: List = init_state) (ch: "XMA"):
for List:
each WordState(r, c, next): state
keep_when g.get(r, c) == ch
def new = next(r, c)
keep_when new
new
for List (WordState(r,c, _) && st: xma_state):
keep_when g.get(r, c) == Char"S"
st
result.length()
check run1(test_input1) ~is 18
module part1:
def input = get_puzzle_input()
run1(input)
// This almost generalizes to part 1 (initial k test needs to change)
fun make_next_x_fun(steps :: List):
fun(grid :: Grid):
fun make_next_x_step(dr :: Int, dc :: Int, ch :: Char, knext):
def g_rows = grid.rows
def g_cols = grid.cols
fun next(r, c) :~ WordState:
def new_r = r + dr
def new_c = c + dc
g_rows.has_element(new_r)
&& g_cols.has_element(new_c)
&& (block:
#//println(@str{checking for @ch at @new_r @new_c ==> @(grid.get(new_r, new_c))})
grid.get(new_r, new_c) == ch)
&& WordState(new_r, new_c, knext)
next
def t:
for values(k = #false):
each:
[ch, dr, dc]: steps.reverse()
make_next_x_step(dr, dc, ch, k)
fun(r, c):
grid.get(r, c) == Char"A"
&& WordState(r, c, t)
def t_mas_mas = make_next_x_fun([[Char"M", -1,-1], [Char"M", 0,2], [Char"S", 2,0], [Char"S", 0,-2]])
def t_mas_sam = make_next_x_fun([[Char"M", -1,-1], [Char"S", 0,2], [Char"S", 2,0], [Char"M", 0,-2]])
def t_sam_mas = make_next_x_fun([[Char"S", -1,-1], [Char"M", 0,2], [Char"M", 2,0], [Char"S", 0,-2]])
def t_sam_sam = make_next_x_fun([[Char"S", -1,-1], [Char"S", 0,2], [Char"M", 2,0], [Char"M", 0,-2]])
fun run2(input :: String):
def grid = Grid(input)
def init_state :: List.of(WordState):
block:
use_dynamic
for List:
each r: grid.rows
each c: grid.cols
each dir: [t_mas_mas, t_mas_sam, t_sam_mas, t_sam_sam]
WordState(r, c, dir(grid))
def result:
for values(cur_state :~ List.of(WordState) = init_state) (i: 0..5):
for List (s: cur_state):
def next = s.next()
keep_when next
next
result.length()
check run2(test_input1) ~is 9
module part2:
def input = get_puzzle_input()
run2(input)