-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday10.rs
129 lines (104 loc) · 3.19 KB
/
day10.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
126
127
128
129
//! [Day 10: The Stars Align](https://adventofcode.com/2018/day/10)
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_sign_loss)]
use aoc::ocr::scan_6x10;
struct Puzzle {
pos: Vec<(i32, i32)>,
vel: Vec<(i32, i32)>,
message: String,
seconds: u32,
}
impl Puzzle {
const fn new() -> Self {
Self {
pos: vec![],
vel: vec![],
message: String::new(),
seconds: 0,
}
}
/// Get the puzzle input.
fn configure(&mut self, data: &str) {
for line in data.lines() {
let row: Vec<_> = line.split(['<', '>', ',']).collect();
self.pos.push((
row[1].trim().parse().unwrap(),
row[2].trim().parse().unwrap(),
));
self.vel.push((
row[4].trim().parse().unwrap(),
row[5].trim().parse().unwrap(),
));
}
}
fn solve(&mut self, verbose: bool) {
let mut pos = self.pos.clone();
let mut prev_height = i32::MAX;
for seconds in 0.. {
let mut ymin = i32::MAX;
let mut ymax = i32::MIN;
for (i, (vx, vy)) in self.vel.iter().enumerate() {
pos[i].0 += vx;
pos[i].1 += vy;
ymin = ymin.min(pos[i].1);
ymax = ymax.max(pos[i].1);
}
let height = ymax - ymin + 1;
if prev_height < height {
// height increases : time to stop
// rollback last move
for (i, (vx, vy)) in self.vel.iter().enumerate() {
pos[i].0 -= vx;
pos[i].1 -= vy;
}
self.seconds = seconds;
break;
}
prev_height = height;
}
let xmin = pos.iter().map(|p| p.0).min().unwrap();
let xmax = pos.iter().map(|p| p.0).max().unwrap();
let ymin = pos.iter().map(|p| p.1).min().unwrap();
let ymax = pos.iter().map(|p| p.1).max().unwrap();
let width = (xmax - xmin + 1) as usize;
let height = (ymax - ymin + 1) as usize;
let mut lcd = vec![vec!['.'; width]; height];
for p in &pos {
let x = (p.0 - xmin) as usize;
let y = (p.1 - ymin) as usize;
lcd[y][x] = '#';
}
let lcd = lcd
.iter()
.map(|row| row.iter().collect::<String>())
.collect::<Vec<String>>()
.join("\n");
if verbose {
println!("{lcd}");
}
if height == 10 {
self.message = scan_6x10(&lcd);
}
if self.message.len() != 8 {
println!("{lcd}");
println!("decoded: {}", self.message);
std::process::exit(2);
}
}
/// Solve part one.
fn part1(&self) -> String {
self.message.clone()
}
/// Solve part two.
const fn part2(&self) -> u32 {
self.seconds
}
}
fn main() {
let args = aoc::parse_args();
let mut puzzle = Puzzle::new();
puzzle.configure(&args.input);
puzzle.solve(args.verbose);
println!("{}", puzzle.part1());
println!("{}", puzzle.part2());
}