Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
Daniel Flanagan | e7cc1df936 |
|
@ -1,115 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(10);
|
|
||||||
show_answers(part1(&input), part2(&input));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part1(input: &str) -> usize {
|
|
||||||
println!("{input}");
|
|
||||||
let mut sum = 0;
|
|
||||||
let map: Vec<Vec<u8>> = input
|
|
||||||
.lines()
|
|
||||||
.map(|l| l.bytes().map(|b| b - b'0').collect())
|
|
||||||
.collect();
|
|
||||||
for (y, row) in map.iter().enumerate() {
|
|
||||||
for (x, height) in row.iter().enumerate() {
|
|
||||||
let mut scores = HashSet::new();
|
|
||||||
if *height == 0 {
|
|
||||||
capture_scores(&map, *height, x, y, &mut scores);
|
|
||||||
sum += scores.len();
|
|
||||||
}
|
|
||||||
println!("{x} {y} {height}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
fn capture_scores(
|
|
||||||
map: &Vec<Vec<u8>>,
|
|
||||||
height: u8,
|
|
||||||
x: usize,
|
|
||||||
y: usize,
|
|
||||||
scores: &mut HashSet<(usize, usize)>,
|
|
||||||
) {
|
|
||||||
if height == 9 {
|
|
||||||
scores.insert((x, y));
|
|
||||||
println!("found a 9");
|
|
||||||
}
|
|
||||||
for (nx, ny) in [
|
|
||||||
(x + 1, y),
|
|
||||||
(x.saturating_sub(1), y),
|
|
||||||
(x, y + 1),
|
|
||||||
(x, y.saturating_sub(1)),
|
|
||||||
] {
|
|
||||||
if nx >= map[0].len() || ny >= map.len() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let next_height = map[ny][nx];
|
|
||||||
if next_height.saturating_sub(height) == 1 {
|
|
||||||
println!("{height} -> {next_height} at {nx},{ny}");
|
|
||||||
capture_scores(map, next_height, nx, ny, scores)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part2(input: &str) -> usize {
|
|
||||||
println!("{input}");
|
|
||||||
let mut sum = 0;
|
|
||||||
let map: Vec<Vec<u8>> = input
|
|
||||||
.lines()
|
|
||||||
.map(|l| l.bytes().map(|b| b - b'0').collect())
|
|
||||||
.collect();
|
|
||||||
for (y, row) in map.iter().enumerate() {
|
|
||||||
for (x, height) in row.iter().enumerate() {
|
|
||||||
if *height == 0 {
|
|
||||||
sum += find_paths_to_nines(&map, *height, x, y);
|
|
||||||
}
|
|
||||||
println!("{x} {y} {height}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_paths_to_nines(map: &Vec<Vec<u8>>, height: u8, x: usize, y: usize) -> usize {
|
|
||||||
let mut sum = 0;
|
|
||||||
if height == 9 {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
for (nx, ny) in [
|
|
||||||
(x + 1, y),
|
|
||||||
(x.saturating_sub(1), y),
|
|
||||||
(x, y + 1),
|
|
||||||
(x, y.saturating_sub(1)),
|
|
||||||
] {
|
|
||||||
if nx >= map[0].len() || ny >= map.len() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let next_height = map[ny][nx];
|
|
||||||
if next_height.saturating_sub(height) == 1 {
|
|
||||||
println!("{height} -> {next_height} at {nx},{ny}");
|
|
||||||
sum += find_paths_to_nines(map, next_height, nx, ny)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let input = r#"89010123
|
|
||||||
78121874
|
|
||||||
87430965
|
|
||||||
96549874
|
|
||||||
45678903
|
|
||||||
32019012
|
|
||||||
01329801
|
|
||||||
10456732"#;
|
|
||||||
assert_eq!(part1(input), 36);
|
|
||||||
assert_eq!(part2(input), 81);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(11);
|
|
||||||
show_answers(part1(&input), part2(&input));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part1(input: &str) -> usize {
|
|
||||||
stone_blinks(input, 25)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stone_blinks(input: &str, count: usize) -> usize {
|
|
||||||
let mut stones: Vec<usize> = input
|
|
||||||
.trim()
|
|
||||||
.split(" ")
|
|
||||||
.map(|s| s.parse().unwrap())
|
|
||||||
.collect();
|
|
||||||
let mut next_stones = vec![];
|
|
||||||
for blink in 0..count {
|
|
||||||
println!("{blink} {}", stones.len());
|
|
||||||
for (_i, s) in stones.iter().enumerate() {
|
|
||||||
// next_stones.push(*s)
|
|
||||||
if *s == 0 {
|
|
||||||
next_stones.push(1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let ss = s.to_string();
|
|
||||||
if ss.len() % 2 == 0 {
|
|
||||||
let mid = ss.len() / 2;
|
|
||||||
let (s1, s2) = (ss[0..mid].parse().unwrap(), ss[mid..].parse().unwrap());
|
|
||||||
next_stones.push(s1);
|
|
||||||
next_stones.push(s2);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
next_stones.push(s * 2024)
|
|
||||||
}
|
|
||||||
stones = next_stones;
|
|
||||||
next_stones = vec![];
|
|
||||||
}
|
|
||||||
stones.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part2(input: &str) -> usize {}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let input = r#"125 17"#;
|
|
||||||
assert_eq!(part1(input), 55312);
|
|
||||||
assert_eq!(part2(input), 0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,29 +24,30 @@ impl FromStr for Report {
|
||||||
|
|
||||||
impl Report {
|
impl Report {
|
||||||
fn is_safe(&self, skip_index: Option<usize>) -> bool {
|
fn is_safe(&self, skip_index: Option<usize>) -> bool {
|
||||||
let mut ordering: Option<Ordering> = None;
|
let mut index_sequence: Box<dyn Iterator<Item = &i64>> = if let Some(i) = skip_index {
|
||||||
let skip_index = skip_index.unwrap_or(self.levels.len() + 1);
|
Box::new(
|
||||||
let max = if skip_index < self.levels.len() {
|
self.levels[0..i]
|
||||||
self.levels.len() - 2
|
.iter()
|
||||||
|
.chain(self.levels[i + 1..self.levels.len()].iter())
|
||||||
|
.into_iter(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
self.levels.len() - 1
|
Box::new(self.levels.iter())
|
||||||
};
|
};
|
||||||
|
let a = index_sequence.next().unwrap();
|
||||||
for i in 0..max {
|
let b = index_sequence.next().unwrap();
|
||||||
let mut ai = i;
|
let ordering = a.cmp(b);
|
||||||
let mut bi = ai + 1;
|
if ordering == Ordering::Equal {
|
||||||
if ai >= skip_index {
|
|
||||||
ai += 1
|
|
||||||
};
|
|
||||||
if bi >= skip_index {
|
|
||||||
bi += 1
|
|
||||||
};
|
|
||||||
let (a, b) = (self.levels[ai], self.levels[bi]);
|
|
||||||
if !Self::safe_level_pair(a, b, &ordering) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ordering == None {
|
if !Self::safe_level_pair(*a, *b, ordering) {
|
||||||
ordering = Some(a.cmp(&b))
|
return false;
|
||||||
|
}
|
||||||
|
println!("{a} {b} {ordering:?} {skip_index:?}");
|
||||||
|
while let (a, Some(b)) = (b, index_sequence.next()) {
|
||||||
|
println!("{a} {b} {ordering:?}");
|
||||||
|
if !Self::safe_level_pair(*a, *b, ordering) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,25 +55,13 @@ impl Report {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_safe_with_any_single_level_removed(&self) -> bool {
|
fn is_safe_with_any_single_level_removed(&self) -> bool {
|
||||||
for i in 0..self.levels.len() {
|
(0..self.levels.len())
|
||||||
if self.is_safe(Some(i)) {
|
.into_iter()
|
||||||
return true;
|
.any(|i| self.is_safe(Some(i)))
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn safe_level_pair(a: i64, b: i64, kind: &Option<Ordering>) -> bool {
|
fn safe_level_pair(a: i64, b: i64, kind: Ordering) -> bool {
|
||||||
if a == b {
|
kind == a.cmp(&b) && (a - b).abs() <= 3
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (a - b).abs() > 3 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if kind.map(|o| o == a.cmp(&b)) == Some(false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,130 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(3);
|
|
||||||
show_answers(sum_muls(&input), sum_muls_with_do_and_dont(&input));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sum_muls(input: &str) -> usize {
|
|
||||||
let mut sum = 0;
|
|
||||||
|
|
||||||
// this string slice will be how we keep track of what is "left" to parse
|
|
||||||
// though it would likely be easier to use an index and slice as needed :shrug:
|
|
||||||
let mut s = &input[..];
|
|
||||||
|
|
||||||
// look for the next valid mul operation
|
|
||||||
while let Some(i) = s.find("mul(") {
|
|
||||||
// re-slice to the remaining string
|
|
||||||
s = &s[i + 4..];
|
|
||||||
|
|
||||||
// variables to contain our operands
|
|
||||||
let mut left: Option<usize> = None;
|
|
||||||
let mut right: Option<usize> = None;
|
|
||||||
|
|
||||||
// variable to contain our currently-parsing token, as we will continue
|
|
||||||
// from here one character at a time
|
|
||||||
let mut token = &s[0..0];
|
|
||||||
|
|
||||||
for c in s.chars() {
|
|
||||||
match c {
|
|
||||||
// any digit simply gets "appended" to our token (in reality, we are just increasing the length of the token slice)
|
|
||||||
'0'..='9' => {
|
|
||||||
token = &s[0..token.len() + 1];
|
|
||||||
// the problem indicates that numbers may not be longer than
|
|
||||||
// 3 digits, so if we encounter one, we break out of this
|
|
||||||
// loop and head to the next mul operation
|
|
||||||
if token.len() > 3 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// once we hit a comma, we check that we don't already have
|
|
||||||
// a left operand then parse the number (which we can unwrap
|
|
||||||
// since we are assuring we are dealing with digits above,
|
|
||||||
// though we could easily optimize that out with bit of
|
|
||||||
// arithmetic), advance through our string slice, and reset our
|
|
||||||
// currently-parsing token
|
|
||||||
',' => {
|
|
||||||
if left.is_some() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
left = Some(token.parse().unwrap());
|
|
||||||
s = &s[token.len() + 1..];
|
|
||||||
token = &s[0..0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// pretty much the same logic for finding a comma, but for the
|
|
||||||
// right operand
|
|
||||||
')' => {
|
|
||||||
if right.is_some() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
right = Some(token.parse().unwrap());
|
|
||||||
s = &s[token.len() + 1..];
|
|
||||||
token = &s[0..0];
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let (Some(left), Some(right)) = (left, right) {
|
|
||||||
sum += left * right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sum_muls_with_do_and_dont(input: &str) -> usize {
|
|
||||||
// the gist of this function is that we look for string segments that are
|
|
||||||
// between do() and don't() operations and only sum_muls for those NOT
|
|
||||||
// between a don't() and do()
|
|
||||||
let mut sum = 0;
|
|
||||||
let mut s = &input[..];
|
|
||||||
|
|
||||||
// since there may be a case where the last do() or don't() is a do(),
|
|
||||||
// we need to know whether or not to parse the "remainder" after we have
|
|
||||||
// processed the last don't() segment which may have ended with a do()
|
|
||||||
let mut mul_rest = true;
|
|
||||||
while let Some(i) = s.find("don't()") {
|
|
||||||
// once we find a don't, we know we want to sum_muls for everything up
|
|
||||||
// to the current position
|
|
||||||
sum += sum_muls(&s[0..i]);
|
|
||||||
|
|
||||||
// then we can advance our slice
|
|
||||||
s = &s[i..];
|
|
||||||
mul_rest = false;
|
|
||||||
if let Some(i) = s.find("do()") {
|
|
||||||
// if we find a do(), set our mul_rest flag appropriately, advance
|
|
||||||
// along the slice, and head to the next iteration (or be done in
|
|
||||||
// the loop)
|
|
||||||
s = &s[i..];
|
|
||||||
mul_rest = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we "ended" with a d(), we want to sum_muls for the rest of the slice
|
|
||||||
if mul_rest {
|
|
||||||
sum += sum_muls(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
assert_eq!(
|
|
||||||
sum_muls("xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"),
|
|
||||||
161
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
sum_muls_with_do_and_dont(
|
|
||||||
"xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"
|
|
||||||
),
|
|
||||||
48
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,126 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(4);
|
|
||||||
let grid: Vec<Vec<u8>> = input
|
|
||||||
.trim()
|
|
||||||
.lines()
|
|
||||||
.map(|l| l.trim().bytes().collect())
|
|
||||||
.collect();
|
|
||||||
show_answers(count_xmas(&grid), count_mas_x(&grid));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn count_xmas(grid: &Vec<Vec<u8>>) -> usize {
|
|
||||||
let height = grid.len();
|
|
||||||
let width = grid[0].len();
|
|
||||||
let mut counter = 0;
|
|
||||||
|
|
||||||
const XMAS: (u8, u8, u8, u8) = (b'X', b'M', b'A', b'S');
|
|
||||||
const SAMX: (u8, u8, u8, u8) = (b'S', b'A', b'M', b'X');
|
|
||||||
|
|
||||||
for (y, line) in grid.iter().enumerate() {
|
|
||||||
for (x, letter) in line.iter().enumerate() {
|
|
||||||
// let near_left_edge = x < 3;
|
|
||||||
let near_top_edge = y < 3;
|
|
||||||
let near_right_edge = x >= width - 3;
|
|
||||||
let near_bottom_edge = y >= height - 3;
|
|
||||||
|
|
||||||
if !near_right_edge && !near_top_edge {
|
|
||||||
// north-west
|
|
||||||
let ray = (
|
|
||||||
*letter,
|
|
||||||
grid[y - 1][x + 1],
|
|
||||||
grid[y - 2][x + 2],
|
|
||||||
grid[y - 3][x + 3],
|
|
||||||
);
|
|
||||||
if ray == XMAS || ray == SAMX {
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !near_right_edge {
|
|
||||||
// west
|
|
||||||
let ray = (*letter, grid[y][x + 1], grid[y][x + 2], grid[y][x + 3]);
|
|
||||||
if ray == XMAS || ray == SAMX {
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !near_right_edge && !near_bottom_edge {
|
|
||||||
// south-west
|
|
||||||
let ray = (
|
|
||||||
*letter,
|
|
||||||
grid[y + 1][x + 1],
|
|
||||||
grid[y + 2][x + 2],
|
|
||||||
grid[y + 3][x + 3],
|
|
||||||
);
|
|
||||||
if ray == XMAS || ray == SAMX {
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !near_bottom_edge {
|
|
||||||
// south
|
|
||||||
let ray = (*letter, grid[y + 1][x], grid[y + 2][x], grid[y + 3][x]);
|
|
||||||
if ray == XMAS || ray == SAMX {
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
counter
|
|
||||||
}
|
|
||||||
|
|
||||||
fn count_mas_x(grid: &Vec<Vec<u8>>) -> usize {
|
|
||||||
let mut counter = 0;
|
|
||||||
let (width, height) = (grid[0].len(), grid.len());
|
|
||||||
for y in 1..height - 1 {
|
|
||||||
for x in 1..width - 1 {
|
|
||||||
// 'A' will always be in the middle, so we can easily just look for
|
|
||||||
// middle 'A' occurences and then check for opposing 'S' and 'M'
|
|
||||||
// characters
|
|
||||||
if grid[y][x] != b'A' {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check opposing cross-characters
|
|
||||||
let ray1 = (grid[y - 1][x - 1], grid[y + 1][x + 1]);
|
|
||||||
let ray2 = (grid[y + 1][x - 1], grid[y - 1][x + 1]);
|
|
||||||
if (ray1 == (b'M', b'S') || ray1 == (b'S', b'M'))
|
|
||||||
&& (ray2 == (b'M', b'S') || ray2 == (b'S', b'M'))
|
|
||||||
{
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
counter
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let input = r#"MMMSXXMASM
|
|
||||||
MSAMXMSMSA
|
|
||||||
AMXSXMAAMM
|
|
||||||
MSAMASMSMX
|
|
||||||
XMASAMXAMM
|
|
||||||
XXAMMXXAMA
|
|
||||||
SMSMSASXSS
|
|
||||||
SAXAMASAAA
|
|
||||||
MAMMMXMMMM
|
|
||||||
MXMXAXMASX"#;
|
|
||||||
|
|
||||||
let grid: Vec<Vec<u8>> = input
|
|
||||||
.trim()
|
|
||||||
.lines()
|
|
||||||
.map(|l| l.trim().bytes().collect())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
assert_eq!(count_xmas(&grid), 18);
|
|
||||||
assert_eq!(count_mas_x(&grid), 9);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,133 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(5);
|
|
||||||
let update: ManualUpdate = input.parse().unwrap();
|
|
||||||
show_answers(update.part1(), update.part2());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct ManualUpdate {
|
|
||||||
rules: HashMap<i64, HashSet<i64>>,
|
|
||||||
updates: Vec<Vec<i64>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for ManualUpdate {
|
|
||||||
type Err = ParseIntError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let (rules_string, updates_string) = s.split_once("\n\n").unwrap();
|
|
||||||
let mut rules: HashMap<i64, HashSet<i64>> = HashMap::new();
|
|
||||||
let mut updates = vec![];
|
|
||||||
for rule in rules_string.lines() {
|
|
||||||
let (left, right) = rule.split_once("|").unwrap();
|
|
||||||
let (left, right): (i64, i64) = (left.parse()?, right.parse()?);
|
|
||||||
|
|
||||||
rules.entry(left).or_default().insert(right);
|
|
||||||
}
|
|
||||||
for update in updates_string.lines() {
|
|
||||||
updates.push(
|
|
||||||
update
|
|
||||||
.split(",")
|
|
||||||
.map(|page| page.parse())
|
|
||||||
.collect::<Result<Vec<i64>, Self::Err>>()?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self { rules, updates })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ManualUpdate {
|
|
||||||
fn part1(&self) -> i64 {
|
|
||||||
self.updates
|
|
||||||
.iter()
|
|
||||||
.filter(|update| self.is_update_valid(update))
|
|
||||||
.map(Self::middle_page_number)
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part2(&self) -> i64 {
|
|
||||||
self.updates
|
|
||||||
.iter()
|
|
||||||
.filter(|update| !self.is_update_valid(update))
|
|
||||||
.map(|update| self.sort_update(update))
|
|
||||||
.map(|sorted_update| Self::middle_page_number(&sorted_update))
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn middle_page_number(update: &Vec<i64>) -> i64 {
|
|
||||||
update[update.len() / 2]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_update_valid(&self, update: &Vec<i64>) -> bool {
|
|
||||||
// work through pages in an update backwards
|
|
||||||
for (i, page) in update.iter().rev().enumerate() {
|
|
||||||
// so we can loop through each previous page
|
|
||||||
for previous_page in update[0..update.len() - i].iter().rev() {
|
|
||||||
if let Some(failure_pages) = self.rules.get(page) {
|
|
||||||
if failure_pages.contains(previous_page) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sort_update(&self, update: &Vec<i64>) -> Vec<i64> {
|
|
||||||
let mut sorted_update = update.clone();
|
|
||||||
sorted_update.sort_by(|a, b| {
|
|
||||||
if let Some(after_pages) = self.rules.get(a) {
|
|
||||||
if after_pages.contains(b) {
|
|
||||||
return Ordering::Less;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ordering::Greater;
|
|
||||||
});
|
|
||||||
sorted_update
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let manual_update: ManualUpdate = "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"
|
|
||||||
.parse()
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(manual_update.part1(), 143);
|
|
||||||
assert_eq!(manual_update.part2(), 123);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,193 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(6);
|
|
||||||
let mut lab: Lab = input.parse().unwrap();
|
|
||||||
let mut lab2: Lab = input.parse().unwrap();
|
|
||||||
show_answers(
|
|
||||||
lab.num_steps_until_guard_leaves_lab(),
|
|
||||||
lab2.num_positions_of_new_obstructions_that_cause_guard_loop(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq, Eq, Hash, Clone)]
|
|
||||||
struct Vec2 {
|
|
||||||
x: i64,
|
|
||||||
y: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Vec2 {
|
|
||||||
fn new(x: i64, y: i64) -> Self {
|
|
||||||
Self { x, y }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add(&self, v: &Vec2) -> Self {
|
|
||||||
Self::new(self.x + v.x, self.y + v.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Vec2 {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "Vec2({}, {})", self.x, self.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Obstruction {
|
|
||||||
pos: Vec2,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
|
||||||
struct Guard {
|
|
||||||
pos: Vec2,
|
|
||||||
vel: Vec2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Guard {
|
|
||||||
fn turn(&mut self) {
|
|
||||||
// too lazy for trig today I guess
|
|
||||||
if self.vel.x > 0 && self.vel.y > 0 {
|
|
||||||
self.vel.x *= -1;
|
|
||||||
} else if self.vel.x < 0 && self.vel.y > 0 {
|
|
||||||
self.vel.y *= -1;
|
|
||||||
} else if self.vel.x < 0 && self.vel.y < 0 {
|
|
||||||
self.vel.x *= -1;
|
|
||||||
} else if self.vel.x > 0 && self.vel.y < 0 {
|
|
||||||
self.vel.y *= -1;
|
|
||||||
} else if self.vel.y != 0 {
|
|
||||||
self.vel.x = self.vel.y * -1;
|
|
||||||
self.vel.y = 0;
|
|
||||||
} else if self.vel.x != 0 {
|
|
||||||
self.vel.y = self.vel.x;
|
|
||||||
self.vel.x = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Lab {
|
|
||||||
obstructions: Vec<Obstruction>,
|
|
||||||
guard: Guard,
|
|
||||||
size: Vec2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Lab {
|
|
||||||
type Err = Infallible;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mut size = Vec2::default();
|
|
||||||
let mut obstructions = vec![];
|
|
||||||
let mut guard: Option<Guard> = None;
|
|
||||||
for (y, line) in s.lines().enumerate() {
|
|
||||||
size.y += 1;
|
|
||||||
size.x = line.len() as i64; // whatever - still linear ;)
|
|
||||||
for (x, c) in line.bytes().enumerate() {
|
|
||||||
match c {
|
|
||||||
b'#' => obstructions.push(Obstruction {
|
|
||||||
pos: Vec2::new(x as i64, y as i64),
|
|
||||||
}),
|
|
||||||
b'^' => {
|
|
||||||
guard = Some(Guard {
|
|
||||||
pos: Vec2::new(x as i64, y as i64),
|
|
||||||
vel: Vec2::new(0, -1),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Lab {
|
|
||||||
size,
|
|
||||||
guard: guard.unwrap(),
|
|
||||||
obstructions,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Lab {
|
|
||||||
fn step(&mut self) {
|
|
||||||
// move guard
|
|
||||||
let next_pos = self.guard.pos.add(&self.guard.vel);
|
|
||||||
self.guard.pos = next_pos;
|
|
||||||
|
|
||||||
// after moving, check if we need to turn
|
|
||||||
// TODO: obstructions should lookup by position instead of this
|
|
||||||
// broad-phase "check each one each time" slow business
|
|
||||||
while self.has_obstacle_at(&self.guard.pos.add(&self.guard.vel)) {
|
|
||||||
self.guard.turn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn contains(&self, pos: &Vec2) -> bool {
|
|
||||||
(0..self.size.x).contains(&pos.x) && (0..self.size.y).contains(&pos.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn num_steps_until_guard_leaves_lab(&mut self) -> usize {
|
|
||||||
let mut visited = HashSet::new();
|
|
||||||
visited.insert(self.guard.pos.clone());
|
|
||||||
while self.contains(&self.guard.pos) {
|
|
||||||
self.step();
|
|
||||||
visited.insert(self.guard.pos.clone());
|
|
||||||
}
|
|
||||||
visited.len() - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_obstacle_at(&self, pos: &Vec2) -> bool {
|
|
||||||
self.obstructions.iter().any(|o| o.pos == *pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn num_positions_of_new_obstructions_that_cause_guard_loop(&mut self) -> usize {
|
|
||||||
let mut positions_with_cycles_detected = 0;
|
|
||||||
let mut visited = HashSet::new();
|
|
||||||
visited.insert(self.guard.clone());
|
|
||||||
// TODO: avoid super brute force
|
|
||||||
for x in 0..self.size.x {
|
|
||||||
for y in 0..self.size.y {
|
|
||||||
println!("Simulating at {x} {y}...");
|
|
||||||
let mut alternate_visited = visited.clone();
|
|
||||||
let mut alternate_lab = self.clone();
|
|
||||||
alternate_lab.obstructions.push(Obstruction {
|
|
||||||
pos: Vec2::new(x, y),
|
|
||||||
});
|
|
||||||
while alternate_lab.contains(&alternate_lab.guard.pos) {
|
|
||||||
alternate_lab.step();
|
|
||||||
if alternate_visited.contains(&alternate_lab.guard) {
|
|
||||||
positions_with_cycles_detected += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
alternate_visited.insert(alternate_lab.guard.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
positions_with_cycles_detected
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let input = "
|
|
||||||
....#.....
|
|
||||||
.........#
|
|
||||||
..........
|
|
||||||
..#.......
|
|
||||||
.......#..
|
|
||||||
..........
|
|
||||||
.#..^.....
|
|
||||||
........#.
|
|
||||||
#.........
|
|
||||||
......#..."
|
|
||||||
.trim();
|
|
||||||
let mut lab: Lab = input.parse().unwrap();
|
|
||||||
let mut lab2 = lab.clone();
|
|
||||||
assert_eq!(lab.num_steps_until_guard_leaves_lab(), 41);
|
|
||||||
assert_eq!(
|
|
||||||
lab2.num_positions_of_new_obstructions_that_cause_guard_loop(),
|
|
||||||
6
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
use std::slice::Windows;
|
|
||||||
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(7);
|
|
||||||
show_answers(
|
|
||||||
sum_possibly_valid_tests(&input, &add_and_mul),
|
|
||||||
sum_possibly_valid_tests(&input, &add_and_mul_and_concat),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sum_possibly_valid_tests(input: &str, f: &dyn Fn(Vec<usize>, &usize) -> Vec<usize>) -> usize {
|
|
||||||
let mut sum = 0;
|
|
||||||
for l in input.lines() {
|
|
||||||
let (target, operands) = l.split_once(':').unwrap();
|
|
||||||
let target: usize = target.parse().unwrap();
|
|
||||||
let operands: Vec<usize> = operands
|
|
||||||
.trim()
|
|
||||||
.split(" ")
|
|
||||||
.map(|s| s.parse().unwrap())
|
|
||||||
.collect();
|
|
||||||
if operands
|
|
||||||
.iter()
|
|
||||||
.skip(1)
|
|
||||||
.fold(vec![operands[0]], f)
|
|
||||||
.iter()
|
|
||||||
.any(|n| *n == target)
|
|
||||||
{
|
|
||||||
sum += target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_and_mul(lefts: Vec<usize>, right: &usize) -> Vec<usize> {
|
|
||||||
let mut result = vec![];
|
|
||||||
for left in lefts {
|
|
||||||
result.push(left + right);
|
|
||||||
result.push(left * right);
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_and_mul_and_concat(lefts: Vec<usize>, right: &usize) -> Vec<usize> {
|
|
||||||
let mut result = vec![];
|
|
||||||
for left in lefts {
|
|
||||||
result.push(left + right);
|
|
||||||
result.push(left * right);
|
|
||||||
result.push(format!("{}{}", left, right).parse().unwrap());
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
assert_eq!(
|
|
||||||
sum_possibly_valid_tests(
|
|
||||||
"190: 10 19
|
|
||||||
3267: 81 40 27
|
|
||||||
83: 17 5
|
|
||||||
156: 15 6
|
|
||||||
7290: 6 8 6 15
|
|
||||||
161011: 16 10 13
|
|
||||||
192: 17 8 14
|
|
||||||
21037: 9 7 18 13
|
|
||||||
292: 11 6 16 20",
|
|
||||||
&add_and_mul
|
|
||||||
),
|
|
||||||
3749
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
sum_possibly_valid_tests(
|
|
||||||
"190: 10 19
|
|
||||||
3267: 81 40 27
|
|
||||||
83: 17 5
|
|
||||||
156: 15 6
|
|
||||||
7290: 6 8 6 15
|
|
||||||
161011: 16 10 13
|
|
||||||
192: 17 8 14
|
|
||||||
21037: 9 7 18 13
|
|
||||||
292: 11 6 16 20",
|
|
||||||
&add_and_mul_and_concat
|
|
||||||
),
|
|
||||||
11387
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(8);
|
|
||||||
show_answers(part1(&input), part2(&input));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part1(input: &str) -> usize {
|
|
||||||
let mut map: HashMap<u8, HashSet<(i64, i64)>> = HashMap::new();
|
|
||||||
let mut antinodes: HashSet<(i64, i64)> = HashSet::new();
|
|
||||||
let (width, height) = (
|
|
||||||
input.lines().count() as i64,
|
|
||||||
input.lines().next().unwrap().len() as i64,
|
|
||||||
);
|
|
||||||
for (y, line) in input.lines().enumerate() {
|
|
||||||
for (x, c) in line.bytes().enumerate() {
|
|
||||||
if c == b'.' {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
map.entry(c)
|
|
||||||
.or_insert_with(|| HashSet::new())
|
|
||||||
.insert((x as i64, y as i64));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for nodes in map.values() {
|
|
||||||
println!("{nodes:?}");
|
|
||||||
for (i, (x1, y1)) in nodes.iter().enumerate() {
|
|
||||||
for (j, (x2, y2)) in nodes.iter().enumerate() {
|
|
||||||
if i == j {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let (dx, dy) = (x1 - x2, y1 - y2);
|
|
||||||
let (a1x, a1y) = (x1 + dx, y1 + dy);
|
|
||||||
let (a2x, a2y) = (x2 - dx, y2 - dy);
|
|
||||||
if a1x >= 0 && a1x < width && a1y >= 0 && a1y < height {
|
|
||||||
antinodes.insert((a1x, a1y));
|
|
||||||
}
|
|
||||||
if a2x >= 0 && a2x < width && a2y >= 0 && a2y < height {
|
|
||||||
antinodes.insert((a2x, a2y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
antinodes.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part2(input: &str) -> usize {
|
|
||||||
let mut map: HashMap<u8, HashSet<(i64, i64)>> = HashMap::new();
|
|
||||||
let mut antinodes: HashSet<(i64, i64)> = HashSet::new();
|
|
||||||
let (width, height) = (
|
|
||||||
input.trim().lines().count() as i64,
|
|
||||||
input.lines().next().unwrap().trim().len() as i64,
|
|
||||||
);
|
|
||||||
for (y, line) in input.lines().enumerate() {
|
|
||||||
for (x, c) in line.bytes().enumerate() {
|
|
||||||
if c == b'.' {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
map.entry(c)
|
|
||||||
.or_insert_with(|| HashSet::new())
|
|
||||||
.insert((x as i64, y as i64));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for nodes in map.values() {
|
|
||||||
for (i, (x1, y1)) in nodes.iter().enumerate() {
|
|
||||||
for (j, (x2, y2)) in nodes.iter().enumerate() {
|
|
||||||
antinodes.insert((*x1, *y1));
|
|
||||||
antinodes.insert((*x2, *y2));
|
|
||||||
if i == j {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let (dx, dy) = (x1 - x2, y1 - y2);
|
|
||||||
let (mut a1x, mut a1y) = (x1 + dx, y1 + dy);
|
|
||||||
while a1x >= 0 && a1x < width && a1y >= 0 && a1y < height {
|
|
||||||
antinodes.insert((a1x, a1y));
|
|
||||||
println!("{a1x} {a1y} {}", antinodes.len());
|
|
||||||
a1x += dx;
|
|
||||||
a1y += dy;
|
|
||||||
}
|
|
||||||
let (mut a2x, mut a2y) = (x2 - dx, y2 - dy);
|
|
||||||
while a2x >= 0 && a2x < width && a2y >= 0 && a2y < height {
|
|
||||||
antinodes.insert((a2x, a2y));
|
|
||||||
println!("{a2x} {a2y} {}", antinodes.len());
|
|
||||||
a2x -= dx;
|
|
||||||
a2y -= dy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
antinodes.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let input = "............
|
|
||||||
........0...
|
|
||||||
.....0......
|
|
||||||
.......0....
|
|
||||||
....0.......
|
|
||||||
......A.....
|
|
||||||
............
|
|
||||||
............
|
|
||||||
........A...
|
|
||||||
.........A..
|
|
||||||
............
|
|
||||||
............";
|
|
||||||
assert_eq!(part1(input), 14);
|
|
||||||
assert_eq!(part2(input), 34);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
mod prelude;
|
|
||||||
pub use crate::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let input = day_input(9);
|
|
||||||
show_answers(part1(&input), part2(&input));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Disk {
|
|
||||||
blocks: Vec<Option<usize>>,
|
|
||||||
files: Vec<(usize, u8)>,
|
|
||||||
free_blocks: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Disk {
|
|
||||||
type Err = Infallible;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mut blocks: Vec<Option<usize>> = vec![];
|
|
||||||
let mut files = vec![];
|
|
||||||
let mut free_blocks: usize = 0;
|
|
||||||
for (i, len) in s.trim().bytes().map(|len| len - b'0').enumerate() {
|
|
||||||
// every other iteration is "free space"
|
|
||||||
let file_id = if i % 2 == 0 {
|
|
||||||
Some((i / 2) as usize)
|
|
||||||
} else {
|
|
||||||
free_blocks += len as usize;
|
|
||||||
None
|
|
||||||
};
|
|
||||||
if file_id.is_some() {
|
|
||||||
files.push((blocks.len(), len));
|
|
||||||
}
|
|
||||||
for _ in 0..len {
|
|
||||||
blocks.push(file_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Self {
|
|
||||||
files,
|
|
||||||
blocks,
|
|
||||||
free_blocks,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Disk {
|
|
||||||
fn checksum(&self) -> usize {
|
|
||||||
self.blocks
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, b)| i * b.unwrap_or_default())
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part1(input: &str) -> usize {
|
|
||||||
let mut disk: Disk = input.parse().unwrap();
|
|
||||||
let mut right = disk.blocks.len() - 1;
|
|
||||||
for left in 0..(right.clone() - disk.free_blocks + 1) {
|
|
||||||
if disk.blocks[left].is_some() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
while disk.blocks[right].is_none() {
|
|
||||||
right -= 1;
|
|
||||||
}
|
|
||||||
(disk.blocks[left], disk.blocks[right]) = (disk.blocks[right], disk.blocks[left]);
|
|
||||||
}
|
|
||||||
|
|
||||||
disk.checksum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn part2(input: &str) -> usize {
|
|
||||||
let mut disk: Disk = input.parse().unwrap();
|
|
||||||
for (cur_i, len) in disk.files.iter().rev() {
|
|
||||||
for left in 0..*cur_i {
|
|
||||||
if disk.blocks[left..(left + (*len as usize))]
|
|
||||||
.iter()
|
|
||||||
.all(|f| f.is_none())
|
|
||||||
{
|
|
||||||
for i in 0..*len {
|
|
||||||
let i = i as usize;
|
|
||||||
(disk.blocks[left + i], disk.blocks[cur_i + i]) =
|
|
||||||
(disk.blocks[cur_i + i], disk.blocks[left + i])
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disk.checksum()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let input = r#"2333133121414131402"#;
|
|
||||||
assert_eq!(part1(input), 1928);
|
|
||||||
assert_eq!(part2(input), 2858);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,9 +2,6 @@ use std::path::{Path, PathBuf};
|
||||||
pub use std::{
|
pub use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
collections::HashSet,
|
|
||||||
convert::Infallible,
|
|
||||||
fmt::Display,
|
|
||||||
fs::File,
|
fs::File,
|
||||||
io::Read,
|
io::Read,
|
||||||
iter::zip,
|
iter::zip,
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
mod prelude;
|
mod prelude;
|
||||||
pub use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let input = day_input(DAY);
|
Day5::show(day_input(5), day_input(5))
|
||||||
show_answers(part1(&input), part2(&input));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part1(input: &str) -> i64 {
|
struct Day5 {}
|
||||||
|
impl AoCSolution for Day5 {
|
||||||
|
type Input = String;
|
||||||
|
type Solution = usize;
|
||||||
|
|
||||||
|
fn part1(input: Self::Input) -> Self::Solution {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(input: &str) -> i64 {
|
fn part2(input: Self::Input) -> Self::Solution {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -21,7 +26,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let input = r#""#;
|
let input = r#""#;
|
||||||
assert_eq!(part1(input), 1);
|
assert_eq!(Day2::part1(input.into()), 1);
|
||||||
assert_eq!(part2(input), 0);
|
assert_eq!(Day2::part2(input.into()), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue