Skip to content

Commit a27130f

Browse files
authored
Merge pull request #75 from hypirion/jn-day-08
Day 8 in Standard ML
2 parents d06ce38 + d44f14c commit a27130f

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

days/day-08/solutions/day08.sml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use "../../../util.sml";
2+
3+
local
4+
structure IS = IntSet
5+
in
6+
7+
datatype Op = ACC | JMP | NOP
8+
9+
fun opFromString "acc" = ACC
10+
| opFromString "jmp" = JMP
11+
| opFromString "nop" = NOP
12+
| opFromString s = raise Fail $ "opFromString - bad input: " ^ s
13+
14+
fun toInstruction s =
15+
case String.tokens (fn c => c = #" ") s of
16+
[a, b] => (opFromString a, valOf $ Int.fromString b)
17+
| _ => raise Fail $ "bad input: " ^ s
18+
19+
datatype TerminationReason = STOPPED of int
20+
| INF_LOOP of int
21+
22+
fun programResult (STOPPED n) = n
23+
| programResult (INF_LOOP n) = n
24+
25+
fun run (program : (Op * int) RList.Coll) : TerminationReason =
26+
let fun go seen pc acc =
27+
if IS.contains pc seen then
28+
INF_LOOP acc
29+
else if RList.size program <= pc then
30+
STOPPED acc
31+
else
32+
let val seen' = IS.insert pc seen
33+
in
34+
case RList.get (pc, program) of
35+
(ACC, n) => go seen' (pc + 1) (acc + n)
36+
| (JMP, n) => go seen' (pc + n) acc
37+
| (NOP, _) => go seen' (pc + 1) acc
38+
end
39+
in
40+
go IS.empty 0 0
41+
end
42+
43+
fun flip (ACC, n) = NONE
44+
| flip (JMP, n) = SOME (NOP, n)
45+
| flip (NOP, n) = SOME (JMP, n)
46+
47+
fun findFlip program i =
48+
case flip $ RList.get (i, program) of
49+
NONE => findFlip program (i+1)
50+
| SOME newOp =>
51+
case run (RList.set (i, newOp, program)) of
52+
INF_LOOP _ => findFlip program (i+1)
53+
| STOPPED n => n
54+
55+
fun main () =
56+
let val program = TextIO.inputAll TextIO.stdIn
57+
>> String.tokens (fn c => c = #"\n")
58+
>> List.map toInstruction
59+
>> RList.fromList
60+
in
61+
println $ Int.toString $ programResult $ run program;
62+
println $ Int.toString $ findFlip program 0
63+
end
64+
handle Subscript => println "boo"
65+
end

days/day-08/test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ D=$(dirname $(realpath $0))
66

77
echo ""
88
echo "--- Day 8: Handheld Halting ---"
9+
$D/../../languages/sml.sh $D/input.txt $D/output.txt $D/solutions/day08.sml
910
$D/../../languages/deno.sh $D/input.txt $D/output.txt $D/solutions/day08.ts
1011
echo ""

util.sml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,80 @@ val size = Map.size
138138
fun fromList list = List.foldl (fn (v, s) => insert v s) empty list
139139
end
140140

141+
structure UncountedRList =
142+
struct
143+
datatype 'a Tree = Leaf of 'a | Node of 'a * 'a Tree * 'a Tree
144+
type 'a Coll = (int * 'a Tree) list
145+
146+
val empty = []
147+
fun isEmpty ts = null ts
148+
149+
fun cons (x, ts as (w1, t1) :: (w2, t2) :: ts') =
150+
if w1 = w2 then
151+
(1 + w1 + w2, Node (x, t1, t2)) :: ts'
152+
else
153+
(1, Leaf x) :: ts
154+
| cons (x, ts) = (1, Leaf x) :: ts
155+
156+
fun head ((1, Leaf x) :: _) = x
157+
| head ((_, Node (x, _, _)) :: _) = x
158+
| head _ = raise Empty
159+
160+
fun tail ((1, Leaf _) :: ts) = ts
161+
| tail ((w, Node (x, t1, t2)) :: ts) = (w div 2, t1) :: (w div 2, t2) :: ts
162+
| tail _ = raise Empty
163+
164+
fun getTree (1, 0, Leaf x) = x
165+
| getTree (w, i, Leaf x) = raise Subscript
166+
| getTree (w, 0, Node (x, t1, t2)) = x
167+
| getTree (w, i, Node (x, t1, t2)) =
168+
169+
if i <= w div 2 then
170+
getTree (w div 2, i - 1, t1)
171+
else
172+
getTree (w div 2, i - 1 - w div 2, t2)
173+
174+
fun setTree (1, 0, y, Leaf x) = Leaf y
175+
| setTree (w, i, y, Leaf x) = raise Subscript
176+
| setTree (w, 0, y, Node (x, t1, t2)) = Node (y, t1, t2)
177+
| setTree (w, i, y, Node (x, t1, t2)) =
178+
if i <= w div 2 then
179+
Node (x, setTree (w div 2, i - 1, y, t1), t2)
180+
else
181+
Node (x, t1, setTree (w div 2, i - 1 - w div 2, y, t2))
182+
183+
fun get (i, []) = raise Subscript
184+
| get (i, (w, t) :: ts) =
185+
if i < w then
186+
getTree (w, i, t)
187+
else
188+
get (i - w, ts)
189+
190+
fun set (i, y, []) = raise Subscript
191+
| set (i, y, (w, t) :: ts) =
192+
if i < w then
193+
(w, setTree (w, i, y, t)) :: ts
194+
else
195+
(w, t) :: set (i - w, y, ts)
196+
end
197+
198+
structure RList =
199+
struct
200+
type 'a Coll = (int * 'a UncountedRList.Coll)
201+
202+
val empty = (0, UncountedRList.empty)
203+
fun isEmpty (0, _) = true
204+
| isEmpty _ = false
205+
fun size (n, _) = n
206+
207+
fun cons (x, (n, s)) = (n+1, UncountedRList.cons (x, s))
208+
fun head (_, s) = UncountedRList.head s
209+
fun tail (n, s) = (n - 1, UncountedRList.tail s)
210+
fun get (i, (n, s)) = UncountedRList.get (i, s)
211+
fun set (i, y, (n, s)) = (n, UncountedRList.set (i, y, s))
212+
fun fromList list = List.foldr cons empty list
213+
end
214+
141215
structure CharMap = Map(
142216
struct
143217
type t = char
@@ -153,3 +227,11 @@ structure StringMap = Map(
153227
end)
154228

155229
structure StringSet = Set(StringMap)
230+
231+
structure IntMap = Map(
232+
struct
233+
type t = int
234+
val cmp = Int.compare
235+
end)
236+
237+
structure IntSet = Set(IntMap)

0 commit comments

Comments
 (0)