8
[aoc20.git] / 8 / one.icl
1 module one
2
3 import StdEnv
4
5 read :: *File -> [Instr]
6 read f
7 # (l, f) = freadline f
8 | l.[size l - 1] <> '\n' = []
9 = [toInstr [c\\c<-:l | c <> '\n']:read f]
10 where
11 toInstr ['nop ':rs] = Nop (toInt (toString rs))
12 toInstr ['acc ':rs] = Acc (toInt (toString rs))
13 toInstr ['jmp ':rs] = Jmp (toInt (toString rs))
14
15 :: Instr = Nop Int | Acc Int | Jmp Int
16
17 Start w
18 # (io, w) = stdio w
19 # instr = read io
20 # instr = {c\\c<-instr}
21 = (one instr, two instr)
22
23 one = fst o interpret
24 two = hd o filter snd o map interpret o nopjump 0
25
26 nopjump :: Int {Instr} -> [{Instr}]
27 nopjump pc is
28 | pc == size is = []
29 = case is.[pc] of
30 Nop i = [update {i\\i<-:is} pc (Jmp i):nopjump (pc+1) is]
31 Jmp i = [update {i\\i<-:is} pc (Nop i):nopjump (pc+1) is]
32 _ = nopjump (pc+1) is
33
34 interpret :: {Instr} -> (Int, Bool)
35 interpret instr = int [] 0 0
36 where
37 int vis pc acc
38 | pc >= size instr = (acc, True)
39 | isMember pc vis = (acc, False)
40 = case instr.[pc] of
41 Nop _ = int [pc:vis] (1 + pc) acc
42 Acc i = int [pc:vis] (1 + pc) (i + acc)
43 Jmp i = int [pc:vis] (i + pc) acc