day14 part2
This commit is contained in:
parent
97d8acbad8
commit
bece6b708b
92
src/day14.rs
92
src/day14.rs
@ -1,6 +1,8 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
enum Rock {
|
enum Rock {
|
||||||
Round,
|
Round,
|
||||||
Square,
|
Square,
|
||||||
@ -43,10 +45,8 @@ fn part1(input: &Vec<Vec<Rock>>) -> usize {
|
|||||||
Rock::Round => {
|
Rock::Round => {
|
||||||
cur_weight -= 1;
|
cur_weight -= 1;
|
||||||
load += cur_weight;
|
load += cur_weight;
|
||||||
//println!("{}", cur_weight);
|
|
||||||
},
|
},
|
||||||
Rock::Square => {
|
Rock::Square => {
|
||||||
//println!("{}", input[0].len() - i);
|
|
||||||
cur_weight = input[0].len() - i;
|
cur_weight = input[0].len() - i;
|
||||||
},
|
},
|
||||||
Rock::None => continue
|
Rock::None => continue
|
||||||
@ -56,10 +56,80 @@ fn part1(input: &Vec<Vec<Rock>>) -> usize {
|
|||||||
load
|
load
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[aoc(day14, part2)]
|
#[aoc(day14, part2)]
|
||||||
// fn part2(input: &Vec<Vec<Rock>>) -> String {
|
fn part2(input: &Vec<Vec<Rock>>) -> usize {
|
||||||
// todo!()
|
let mut seen_at = HashMap::new();
|
||||||
// }
|
let mut next_y = Vec::<usize>::new();
|
||||||
|
let mut map = input.to_vec();
|
||||||
|
|
||||||
|
// Functions to get a Rock using a rotated coordinate space
|
||||||
|
let cycle_parts: &[(Box<dyn Fn(&mut Vec<Vec<Rock>>, usize, usize) -> &mut Rock>, _, _); 4] = &[
|
||||||
|
(Box::new(|map: &mut Vec<Vec<Rock>>, x: usize, y: usize| &mut map[y][x]),
|
||||||
|
map[0].len(), map.len()),
|
||||||
|
(Box::new(|map: &mut Vec<Vec<Rock>>, x: usize, y: usize| &mut map[x][y]),
|
||||||
|
map.len(), map[0].len()),
|
||||||
|
(Box::new(|map: &mut Vec<Vec<Rock>>, x: usize, y: usize| { let h = map.len(); &mut map[h - 1 - y][x] }),
|
||||||
|
map[0].len(), map.len()),
|
||||||
|
(Box::new(|map: &mut Vec<Vec<Rock>>, x: usize, y: usize| { let w = map[0].len(); &mut map[x][w - 1 - y] }),
|
||||||
|
map.len(), map[0].len()),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut cycle = 0;
|
||||||
|
const END: u32 = 1000000000;
|
||||||
|
while cycle < END {
|
||||||
|
// Handle tilts in each direction
|
||||||
|
for (getter, width, height) in cycle_parts {
|
||||||
|
next_y.clear();
|
||||||
|
next_y.resize(*width, 0);
|
||||||
|
for y in 0..*height {
|
||||||
|
for x in 0..*width {
|
||||||
|
let item = getter(&mut map, x, y);
|
||||||
|
match *item {
|
||||||
|
Rock::None => {}
|
||||||
|
Rock::Square => {
|
||||||
|
next_y[x] = y + 1;
|
||||||
|
}
|
||||||
|
Rock::Round => {
|
||||||
|
*item = Rock::None;
|
||||||
|
*getter(&mut map, x, next_y[x]) = Rock::Round;
|
||||||
|
next_y[x] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// More compact representation of the current state, for saving in hashmap
|
||||||
|
let key = map.iter().enumerate().flat_map(|(y, line)| {
|
||||||
|
line.iter().enumerate().filter_map(move |(x, &ref rock)| {
|
||||||
|
if rock == &Rock::Round {
|
||||||
|
Some((x as u8, y as u8))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
cycle += 1;
|
||||||
|
if let Some(seen_at_cycle) = seen_at.insert(key, cycle) {
|
||||||
|
// Current state was identical to one we'd already seen, we can skip forward
|
||||||
|
let diff = cycle - seen_at_cycle;
|
||||||
|
let remaining = END - cycle;
|
||||||
|
let skipped = remaining / diff * diff;
|
||||||
|
cycle += skipped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let height = map.len();
|
||||||
|
|
||||||
|
map.into_iter().enumerate().flat_map(|(y, line)| line.into_iter().filter_map(move |rock| {
|
||||||
|
if rock == Rock::Round {
|
||||||
|
Some(height - y)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -82,8 +152,8 @@ O.#..O.#.#
|
|||||||
assert_eq!(part1(&parse(EX)), 136);
|
assert_eq!(part1(&parse(EX)), 136);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn part2_example() {
|
fn part2_example() {
|
||||||
// assert_eq!(part2(&parse(EX)), "<RESULT>");
|
assert_eq!(part2(&parse(EX)), 64);
|
||||||
// }
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user