-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday05.rs
125 lines (108 loc) · 2.58 KB
/
day05.rs
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
pub fn part1(input: &str) -> String {
let (rules, updates) = parse_input(input);
updates
.into_iter()
.map(|update| {
if update_is_valid(&update, &rules) {
update[update.len() / 2]
} else {
0
}
})
.sum::<u32>()
.to_string()
}
pub fn part2(input: &str) -> String {
let (rules, updates) = parse_input(input);
updates
.into_iter()
.map(|mut update| {
if update_is_valid(&update, &rules) {
return 0;
}
loop {
for &(left, right) in &rules {
let left_pos = update.iter().position(|&x| x == left);
let right_pos = update.iter().rposition(|&x| x == right);
if let (Some(l), Some(r)) = (left_pos, right_pos) {
if l > r {
update.swap(l, r);
}
}
}
if update_is_valid(&update, &rules) {
break;
}
}
update[update.len() / 2]
})
.sum::<u32>()
.to_string()
}
fn parse_input(input: &str) -> (Vec<(u32, u32)>, Vec<Vec<u32>>) {
let mut parts = input.split("\n\n");
let rules = parts.next().unwrap();
let updates = parts.next().unwrap();
let rules: Vec<_> = rules
.lines()
.map(|rule| {
let (l, r) = rule.split_once("|").unwrap();
(l.parse::<u32>().unwrap(), r.parse::<u32>().unwrap())
})
.collect();
let updates: Vec<Vec<u32>> = updates
.lines()
.map(|update| update.split(",").map(|n| n.parse().unwrap()).collect())
.collect();
(rules, updates)
}
fn update_is_valid(update: &[u32], rules: &[(u32, u32)]) -> bool {
rules.iter().all(|&(left, right)| {
let left_pos = update.iter().position(|&x| x == left);
let right_pos = update.iter().rposition(|&x| x == right);
match (left_pos, right_pos) {
(Some(l), Some(r)) => l <= r,
_ => true,
}
})
}
#[cfg(test)]
mod tests {
use super::*;
const TEST_INPUT: &str = r#"47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13
75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47
"#;
#[test]
fn test_part1() {
assert_eq!(part1(TEST_INPUT), "143");
}
#[test]
fn test_part2() {
assert_eq!(part2(TEST_INPUT), "123");
}
}