-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution.swift
78 lines (63 loc) · 1.98 KB
/
Solution.swift
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
struct Value: Hashable, CustomStringConvertible {
let value: Int
var description: String {
return String(value)
}
}
struct StateId: Hashable, CustomStringConvertible {
let symbol: Character
var description: String {
return String(symbol)
}
}
struct Action {
let write: Value
let move: Int
let continueWith: StateId
}
struct Instructions {
let instructions: [Value: Action]
}
struct Program {
let beginIn: StateId
let steps: Int
let instructions: [StateId: Instructions]
func run() -> State {
var state = State(currentState: beginIn, currentCursor: 0, tape: [:])
for step in 0..<steps {
state = state.next(using: instructions)
if step % 100_000 == 0 {
print("Step \(step)")
}
}
return state
}
}
struct State {
let currentState: StateId
let currentCursor: Int
let tape: [Int: Value]
func valueAtCursor() -> Value {
return tape[currentCursor] ?? Value(value: 0)
}
func next(using instructions: [StateId: Instructions]) -> State {
let currentValue = valueAtCursor()
guard let action = instructions[currentState]?.instructions[currentValue] else {
fatalError("No instructions available for current state \(currentState) and value \(currentValue)")
}
let newEntries = [currentCursor: action.write]
let updatedTape = tape.merging(newEntries) { (_, new) in new }
let updatedCursor: Int = currentCursor + action.move
let updatedState = action.continueWith
return State(currentState: updatedState, currentCursor: updatedCursor, tape: updatedTape)
}
func diagnosticChecksum() -> Int {
return tape.countIf { value -> Bool in
value.value == 1
}
}
}
func solve(input: String) -> Int {
let program = parse(input: input)
return program.run().diagnosticChecksum()
}