mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Reimplement day 14 with infinite streams.
This commit is contained in:
@@ -1,25 +1,50 @@
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use common::Solution;
|
|
||||||
use common::read_single_input;
|
use common::read_single_input;
|
||||||
|
use common::Solution;
|
||||||
|
|
||||||
|
struct ResultStream {
|
||||||
|
elves: [usize; 2],
|
||||||
|
state: Vec<u8>,
|
||||||
|
next: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResultStream {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ResultStream {
|
||||||
|
elves: [0, 1],
|
||||||
|
state: vec![3, 7],
|
||||||
|
next: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for ResultStream {
|
||||||
|
type Item = u8;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
||||||
|
let state = &mut self.state;
|
||||||
|
if self.next == state.len() {
|
||||||
|
let elves = &mut self.elves;
|
||||||
|
let n = state[elves[0]] + state[elves[1]];
|
||||||
|
if n >= 10 {
|
||||||
|
state.push(1);
|
||||||
|
}
|
||||||
|
state.push(n % 10);
|
||||||
|
|
||||||
|
elves[0] = (elves[0] + 1 + state[elves[0]] as usize) % state.len();
|
||||||
|
elves[1] = (elves[1] + 1 + state[elves[1]] as usize) % state.len();
|
||||||
|
};
|
||||||
|
let n = Some(state[self.next]);
|
||||||
|
self.next += 1;
|
||||||
|
n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn skill_after(n: usize) -> u64 {
|
fn skill_after(n: usize) -> u64 {
|
||||||
let mut state = vec![3u8, 7];
|
let state = ResultStream::new();
|
||||||
let mut elves = [0, 1];
|
|
||||||
|
|
||||||
while state.len() < n + 10 {
|
|
||||||
let result = state[elves[0]] + state[elves[1]];
|
|
||||||
if result >= 10 {
|
|
||||||
state.push(result / 10);
|
|
||||||
}
|
|
||||||
state.push(result % 10);
|
|
||||||
|
|
||||||
elves[0] = (elves[0] + state[elves[0]] as usize + 1) % state.len();
|
|
||||||
elves[1] = (elves[1] + state[elves[1]] as usize + 1) % state.len();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut skill = 0;
|
let mut skill = 0;
|
||||||
for d in state.into_iter().skip(n).take(10) {
|
for d in state.skip(n).take(10) {
|
||||||
skill *= 10;
|
skill *= 10;
|
||||||
skill += d as u64;
|
skill += d as u64;
|
||||||
}
|
}
|
||||||
@@ -27,37 +52,18 @@ fn skill_after(n: usize) -> u64 {
|
|||||||
skill
|
skill
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_current(mut current: usize, by: usize, base: usize) -> usize {
|
|
||||||
current *= 10;
|
|
||||||
current %= base;
|
|
||||||
current += by;
|
|
||||||
current
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_first(n: usize, len: usize) -> usize {
|
fn find_first(n: usize, len: usize) -> usize {
|
||||||
let mut state = vec![3u8, 7];
|
|
||||||
let mut elves = [0, 1];
|
|
||||||
let mut current = 37;
|
|
||||||
let mod_base = 10usize.pow(len as u32);
|
let mod_base = 10usize.pow(len as u32);
|
||||||
|
let mut current = 0;
|
||||||
|
|
||||||
loop {
|
for (i, b) in ResultStream::new().enumerate() {
|
||||||
let result = state[elves[0]] + state[elves[1]];
|
current = (current * 10) % mod_base;
|
||||||
if result >= 10 {
|
current += b as usize;
|
||||||
current = update_current(current, result as usize / 10, mod_base);
|
|
||||||
if current == n {
|
|
||||||
return state.len() - len + 1;
|
|
||||||
}
|
|
||||||
state.push(result / 10);
|
|
||||||
}
|
|
||||||
current = update_current(current, result as usize % 10, mod_base);
|
|
||||||
if current == n {
|
if current == n {
|
||||||
return state.len() - len + 1;
|
return i - len + 1;
|
||||||
}
|
}
|
||||||
state.push(result % 10);
|
|
||||||
|
|
||||||
elves[0] = (elves[0] + state[elves[0]] as usize + 1) % state.len();
|
|
||||||
elves[1] = (elves[1] + state[elves[1]] as usize + 1) % state.len();
|
|
||||||
}
|
}
|
||||||
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user