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
|
extern crate advent_of_code_2017;
use advent_of_code_2017::*;
extern crate regex;
use regex::Regex;
use std::slice::Iter;
use std::collections::HashSet;
fn main() {
let args = AdventArgs::init();
let program = parse(&args.input);
let mut position: i32 = 0;
let mut state = program.state(program.start).expect("Started out of program bounds");
let mut tape = HashSet::new();
for _ in 0..program.iterations {
let instruction = if tape.contains(&position) {
&state.if1
} else {
&state.if0
};
if instruction.write {
tape.insert(position);
} else {
tape.remove(&position);
}
position += instruction.offset;
state = program.state(instruction.next).expect("Redirected to unknown state");
}
println!("{}", tape.len());
}
fn parse(input: &Vec<String>) -> Program {
let state_re = Regex::new(r"state (\w)").unwrap();
let iterations_re = Regex::new(r"(\d+) steps").unwrap();
let write_re = Regex::new(r"Write the value (\d)").unwrap();
let move_re = Regex::new(r"Move one slot to the (\w+)").unwrap();
let mut lines = input.iter();
let start = parse_char(&mut lines, &state_re);
let iterations = parse_number(&mut lines, &iterations_re);
let mut states = Vec::new();
while let Some(heading) = lines.next() {
states.push(State {
id: state_re.captures(heading).unwrap()[1].chars().next().unwrap(),
if0: parse_instruction(&mut lines, &write_re, &move_re, &state_re),
if1: parse_instruction(&mut lines, &write_re, &move_re, &state_re)
});
}
Program {
start: start,
iterations: iterations,
states: states
}
}
fn parse_char(lines: &mut Iter<String>, re: &Regex) -> char {
re.captures(
lines.next().unwrap()
).unwrap()[1].chars().next().unwrap()
}
fn parse_number(lines: &mut Iter<String>, re: &Regex) -> u32 {
re.captures(
lines.next().unwrap()
).unwrap()[1].parse().unwrap()
}
fn parse_direction(lines: &mut Iter<String>, re: &Regex) -> i32 {
if re.captures(
lines.next().unwrap()
).unwrap()[1] == *"left" {
-1
} else {
1
}
}
fn parse_bool(lines: &mut Iter<String>, re: &Regex) -> bool {
re.captures(
lines.next().unwrap()
).unwrap()[1] == *"1"
}
fn parse_instruction(lines: &mut Iter<String>, write_re: &Regex, offset_re: &Regex, next_re: &Regex) -> Instruction {
lines.next();
Instruction {
write: parse_bool(lines, &write_re),
offset: parse_direction(lines, &offset_re),
next: parse_char(lines, &next_re)
}
}
#[derive(Debug)]
struct Program {
start: char,
iterations: u32,
states: Vec<State>
}
impl Program {
fn state(&self, i: char) -> Option<&State> {
self.states.iter().find(|s| s.id == i)
}
}
#[derive(Debug)]
struct State {
id: char,
if0: Instruction,
if1: Instruction
}
#[derive(Debug)]
struct Instruction {
write: bool,
offset: i32,
next: char
}
|