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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
use std::env;
use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;
use std::process;
use std::collections::HashMap;
type State = HashMap<i64, char>;
type RuleKey = (char, char, char, char, char);
type Rules = HashMap<RuleKey, char>;
static ITERATIONS: usize = 150;
fn parse_initial_state(line: &String) -> (State, i64, i64) {
let initial: Vec<char> = line[15..].chars().collect();
let mut state: State = State::new();
for (i, &ch) in initial.iter().enumerate() {
state.insert(i as i64, ch);
}
let c = initial.len() as i64;
state.insert(-1, '.');
state.insert(-2, '.');
state.insert(c, '.');
state.insert(c + 1, '.');
(state, 0, c + 1)
}
fn parse_rule(rules: &mut Rules, line: &String) {
let chs: Vec<char> = line.chars().collect();
let res: char = chs[chs.len() - 1];
let p = chs[0..6].to_vec();
let rule_key = (p[0], p[1], p[2], p[3], p[4]);
rules.insert(rule_key, res);
}
fn eval_rules(state: &State, rules: &Rules, i: i64) -> char {
let prev2 = if state.contains_key(&(i - 2)) { state[&(i - 2)] } else { '.' };
let prev1 = if state.contains_key(&(i - 1)) { state[&(i - 1)] } else { '.' };
let cur = if state.contains_key(&i) { state[&i] } else { '.' };
let next1 = if state.contains_key(&(i + 1)) { state[&(i + 1)] } else { '.' };
let next2 = if state.contains_key(&(i + 2)) { state[&(i + 2)] } else { '.' };
rules[&(prev2, prev1, cur, next1, next2)]
}
fn draw_state(state: &State, iteration: usize) {
let mut keys: Vec<i64> = state.keys().map(|&k| k).collect();
keys.sort();
print!("{}: ", iteration);
for k in &keys {
print!("{} ", state[k]);
}
print!("\n");
}
fn sum_state(state: &State) -> i64 {
let mut total = 0;
for (i, &ch) in state {
if ch == '#' {
total += i;
}
}
total
}
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("Wrong number of arguments. Provide a file name and worker count.");
process::exit(1);
}
let filename = &args[1];
println!("Using file {} as input.", filename);
let f = match File::open(filename) {
Ok(file) => file,
Err(e) => {
println!("Failed to open file {}. {:?}", filename, e);
process::exit(1);
}
};
let file = BufReader::new(&f);
let lines: Vec<String> = file.lines()
.map(|line| line.expect("Could not parse line."))
.collect();
let mut initial_state: State = State::new();
let (mut i1, mut i2): (i64, i64) = (0, 0);
let mut rules: Rules = HashMap::new();
for (i, line) in lines.iter().enumerate() {
match i {
0 => {
let tuple = parse_initial_state(&line);
initial_state = tuple.0;
i1 = tuple.1;
i2 = tuple.2;
}
1 => { }
_ => { parse_rule(&mut rules, &line); }
}
}
assert_ne!(initial_state.len(), 0);
let mut prev_state = initial_state;
let mut prev_sum = 0;
// draw_state(&prev_state, 0);
for iteration in 0..ITERATIONS {
let mut new_state = prev_state.clone();
if prev_state[&(i1 + 1)] == '#' {
new_state.insert(i1 - 1, '.');
new_state.insert(i1 - 2, '.');
i1 -= 2;
}
if prev_state[&(i2 - 1)] == '#' {
new_state.insert(i2 + 1, '.');
new_state.insert(i2 + 2, '.');
i2 += 2;
}
let keys: Vec<i64> = new_state.keys().map(|&k| k).collect();
for key in keys {
let val = eval_rules(&prev_state, &rules, key);
new_state.insert(key, val);
}
// if iteration % 1000 == 0 {
// println!("Iteration: {}", iteration);
// }
let sum = sum_state(&new_state);
let diff = sum - prev_sum;
println!("It: {}, sum: {}, diff: {}", iteration + 1, sum, diff);
prev_sum = sum;
// draw_state(&new_state, iteration);
prev_state = new_state;
}
let last_state = prev_state;
let total = sum_state(&last_state);
println!("Result: {}", total);
let iters2 = 50000000000u64;
let result2 = 9152 + (iters2 - 140) * 52;
println!("Result 2: {}", result2);
}
|