-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday09.rs
More file actions
166 lines (145 loc) · 4.08 KB
/
Copy pathday09.rs
File metadata and controls
166 lines (145 loc) · 4.08 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#[derive(Debug)]
struct Interval {
start: usize,
end: usize,
idx: Option<usize>,
}
impl Interval {
pub fn len(&self) -> usize {
self.end - self.start
}
pub fn move_to(&mut self, idx: usize) {
let delta = self.len();
self.start = idx;
self.end = idx + delta;
}
pub fn shorten(&mut self, delta: usize) -> bool {
if delta > self.len() {
return false;
}
self.start += delta;
true
}
pub fn checksum(&self) -> Option<usize> {
match self.idx {
Some(idx) => Some((self.start..self.end).map(|i| i * idx).sum()),
None => None,
}
}
}
fn parse_input01(input: &str) -> (Vec<(usize, usize)>, Vec<usize>) {
let mut content_idx: usize = 0;
let mut fs_idx: usize = 0;
let mut empty: bool = false;
let mut filesystem: Vec<(usize, usize)> = Vec::new();
let mut empty_spaces: Vec<usize> = Vec::new();
for character in input.lines().next().unwrap().trim().chars() {
let size = character.to_string().parse::<usize>().unwrap();
if empty {
empty = false;
for _ in 0..size {
empty_spaces.push(fs_idx);
fs_idx += 1;
}
} else {
empty = true;
for _ in 0..size {
filesystem.push((fs_idx, content_idx));
fs_idx += 1;
}
content_idx += 1;
}
}
filesystem.reverse();
(filesystem, empty_spaces)
}
fn parse_input02(input: &str) -> (Vec<Interval>, Vec<Interval>) {
let mut blocks = Vec::new();
let mut empty_blocks = Vec::new();
let mut empty = false;
let mut fs_idx: usize = 0;
let mut content_idx: usize = 0;
for character in input.lines().next().unwrap().trim().chars() {
let size = character.to_string().parse::<usize>().unwrap();
if empty {
empty = false;
empty_blocks.push(Interval {
start: fs_idx,
end: fs_idx + size,
idx: None,
});
} else {
empty = true;
blocks.push(Interval {
start: fs_idx,
end: fs_idx + size,
idx: Some(content_idx),
});
content_idx += 1;
}
fs_idx += size
}
(blocks, empty_blocks)
}
pub fn task01(input: &str) -> String {
let (mut filesystem, empty_spaces) = parse_input01(input);
for (idx, &empty_space) in empty_spaces.iter().enumerate() {
if filesystem[idx].0 <= empty_space {
break;
}
filesystem[idx].0 = empty_space;
}
filesystem.sort_by(|a, b| a.0.cmp(&b.0));
filesystem
.iter()
.map(|(fs_idx, content_idx)| *fs_idx * *content_idx)
.sum::<usize>()
.to_string()
}
pub fn task02(input: &str) -> String {
let (mut blocks, mut empty_blocks) = parse_input02(input);
for block in blocks.iter_mut().rev() {
for empty_block in empty_blocks.iter_mut() {
if empty_block.len() < block.len() {
continue;
}
if empty_block.start > block.start {
break;
}
block.move_to(empty_block.start);
empty_block.shorten(block.len());
break;
}
}
blocks.sort_by(|a, b| a.start.cmp(&b.start));
blocks
.iter()
.map(|block| block.checksum().unwrap())
.sum::<usize>()
.to_string()
}
#[cfg(test)]
mod tests {
use super::super::fs_utils::{read_example, read_input};
use super::*;
#[test]
fn test_task01() {
let input = read_example(9, 1);
assert_eq!(task01(&input), "1928");
}
#[test]
fn run_task01() {
let input = read_input(9);
assert_eq!(task01(&input), "6216544403458");
}
#[test]
fn test_task02() {
let input = read_example(9, 1);
assert_eq!(task02(&input), "2858");
}
#[test]
fn run_task02() {
let input = read_input(9);
assert_eq!(task02(&input), "6237075041489");
}
}