mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-26 13:20:32 +01:00
Implementation day 23 part 2.
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
use num_integer::Integer;
|
||||||
|
|
||||||
use crate::Solution;
|
use crate::Solution;
|
||||||
|
|
||||||
fn read_input(input: &mut dyn Read) -> Vec<u8> {
|
fn read_input(input: &mut dyn Read) -> Vec<u8> {
|
||||||
@@ -23,9 +25,16 @@ fn read_input(input: &mut dyn Read) -> Vec<u8> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn target_num(mut current: u8, picked_up: &[u8]) -> u8 {
|
fn target_num<T>(mut current: T, maximum: T, picked_up: &[T]) -> T
|
||||||
|
where
|
||||||
|
T: Integer + Copy,
|
||||||
|
{
|
||||||
loop {
|
loop {
|
||||||
let next = if current == 1 { 9 } else { current - 1 };
|
let next = if current.is_one() {
|
||||||
|
maximum
|
||||||
|
} else {
|
||||||
|
current - T::one()
|
||||||
|
};
|
||||||
|
|
||||||
if !picked_up.contains(&next) {
|
if !picked_up.contains(&next) {
|
||||||
return next;
|
return next;
|
||||||
@@ -43,7 +52,7 @@ fn play_game(numbers: &mut [u8], times: usize) -> String {
|
|||||||
assert!(numbers.len() >= 5); // Helps the compiler
|
assert!(numbers.len() >= 5); // Helps the compiler
|
||||||
|
|
||||||
for _ in 0..times {
|
for _ in 0..times {
|
||||||
let target = target_num(numbers[0], &numbers[1..4]);
|
let target = target_num(numbers[0], 9, &numbers[1..4]);
|
||||||
let target_pos = numbers.iter().position(|&c| c == target).unwrap();
|
let target_pos = numbers.iter().position(|&c| c == target).unwrap();
|
||||||
|
|
||||||
numbers[1..=target_pos].rotate_left(3);
|
numbers[1..=target_pos].rotate_left(3);
|
||||||
@@ -59,6 +68,51 @@ fn play_game(numbers: &mut [u8], times: usize) -> String {
|
|||||||
stringify_state(&numbers[1..])
|
stringify_state(&numbers[1..])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn play_game_large(numbers: &[u8], to_play: usize, maximum: u32) -> Vec<u32> {
|
||||||
|
let mut next = vec![0; maximum as usize + 1];
|
||||||
|
|
||||||
|
// Initialize the specified numbers
|
||||||
|
for pair in numbers.windows(2) {
|
||||||
|
next[pair[0] as usize] = pair[1] as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if numbers.len() < maximum as usize {
|
||||||
|
// Add the remaining numbers to the loop
|
||||||
|
next[*numbers.last().unwrap() as usize] = 10;
|
||||||
|
|
||||||
|
for (i, pos) in next.iter_mut().enumerate().skip(10) {
|
||||||
|
*pos = i as u32 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop it around until the first spot
|
||||||
|
next[maximum as usize] = numbers[0] as u32;
|
||||||
|
} else {
|
||||||
|
next[*numbers.last().unwrap() as usize] = numbers[0] as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut active = numbers[0] as u32;
|
||||||
|
|
||||||
|
for _ in 0..to_play {
|
||||||
|
//print_state(active, &next);
|
||||||
|
|
||||||
|
let picked = [
|
||||||
|
next[active as usize],
|
||||||
|
next[next[active as usize] as usize],
|
||||||
|
next[next[next[active as usize] as usize] as usize],
|
||||||
|
];
|
||||||
|
|
||||||
|
let target = target_num(active, maximum as u32, &picked);
|
||||||
|
|
||||||
|
next[active as usize] = next[picked[2] as usize];
|
||||||
|
next[picked[2] as usize] = next[target as usize];
|
||||||
|
next[target as usize] = picked[0];
|
||||||
|
|
||||||
|
active = next[active as usize];
|
||||||
|
}
|
||||||
|
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Day23;
|
pub struct Day23;
|
||||||
|
|
||||||
@@ -67,18 +121,34 @@ impl Solution for Day23 {
|
|||||||
let mut numbers = read_input(input);
|
let mut numbers = read_input(input);
|
||||||
play_game(&mut numbers, 100)
|
play_game(&mut numbers, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn part2(&mut self, input: &mut dyn Read) -> String {
|
||||||
|
let numbers = read_input(input);
|
||||||
|
|
||||||
|
let result = play_game_large(&numbers, 10_000_000, 1_000_000);
|
||||||
|
|
||||||
|
let total = result[1] as u64 * result[result[1] as usize] as u64;
|
||||||
|
total.to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::test_implementation;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const SAMPLE: &[u8] = b"389125467";
|
const SAMPLE: &[u8] = b"389125467";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sample_part1() {
|
fn sample_part1() {
|
||||||
let sample = read_input(&mut SAMPLE.as_ref());
|
let sample = read_input(&mut SAMPLE.clone());
|
||||||
assert_eq!("92658374", &play_game(&mut sample.clone(), 10));
|
assert_eq!("92658374", &play_game(&mut sample.clone(), 10));
|
||||||
assert_eq!("67384529", &play_game(&mut sample.clone(), 100));
|
assert_eq!("67384529", &play_game(&mut sample.clone(), 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
test_implementation!(Day23, 2, SAMPLE, 149245887792u64);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,14 +72,14 @@ macro_rules! test_implementation {
|
|||||||
($impl:ident, 1, $source:ident, $output:expr) => {
|
($impl:ident, 1, $source:ident, $output:expr) => {
|
||||||
let mut implementation = $impl::default();
|
let mut implementation = $impl::default();
|
||||||
|
|
||||||
let result = implementation.part1(&mut $source.as_ref());
|
let result = implementation.part1(&mut $source.clone());
|
||||||
assert_eq!($output.to_string(), result);
|
assert_eq!($output.to_string(), result);
|
||||||
};
|
};
|
||||||
|
|
||||||
($impl:ident, 2, $source:ident, $output:expr) => {
|
($impl:ident, 2, $source:ident, $output:expr) => {
|
||||||
let mut implementation = $impl::default();
|
let mut implementation = $impl::default();
|
||||||
|
|
||||||
let result = implementation.part2(&mut $source.as_ref());
|
let result = implementation.part2(&mut $source.clone());
|
||||||
assert_eq!($output.to_string(), result);
|
assert_eq!($output.to_string(), result);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user