|
| 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 |
0 commit comments