Compare commits
2 commits
6ce747054d
...
e1d9bd89ef
Author | SHA1 | Date | |
---|---|---|---|
|
e1d9bd89ef | ||
|
9fe31c237a |
1 changed files with 46 additions and 69 deletions
|
@ -1,4 +1,4 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let input = std::fs::read_to_string("input").unwrap();
|
let input = std::fs::read_to_string("input").unwrap();
|
||||||
|
@ -7,85 +7,68 @@ fn main() {
|
||||||
println!("{}", pt2(&stones));
|
println!("{}", pt2(&stones));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pt1(stones: &[u128]) -> usize {
|
fn pt1(stones: &[u64]) -> usize {
|
||||||
blink3(stones.to_vec(), 25)
|
b4(stones, 25)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pt2(stones: &[u128]) -> usize {
|
fn pt2(stones: &[u64]) -> usize {
|
||||||
let mut total = 0;
|
b4(stones, 75)
|
||||||
for stone in stones {
|
|
||||||
total += blink3(vec![*stone], 75);
|
|
||||||
}
|
|
||||||
total
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blink2(stones: &[u128], blinks: usize) -> usize {
|
fn b4(stones: &[u64], blinks: usize) -> usize {
|
||||||
let mut stones = VecDeque::from_iter(stones.iter().copied());
|
let mut cache = HashMap::new();
|
||||||
|
for &stone in stones {
|
||||||
|
cache
|
||||||
|
.entry(stone)
|
||||||
|
.and_modify(|n| *n += 1usize)
|
||||||
|
.or_insert(1usize);
|
||||||
|
}
|
||||||
|
|
||||||
for _blink in 0..blinks {
|
for _blink in 0..blinks {
|
||||||
let mut rots = 0;
|
let mut new_cache = HashMap::new();
|
||||||
while rots < stones.len() {
|
for (stone, count) in cache.into_iter() {
|
||||||
let stone = stones[0];
|
|
||||||
let digits = stone.to_string();
|
|
||||||
|
|
||||||
match stone {
|
match stone {
|
||||||
0 => {
|
0 => {
|
||||||
stones[0] = 1;
|
new_cache
|
||||||
stones.rotate_left(1);
|
.entry(1)
|
||||||
rots += 1;
|
.and_modify(|n| *n += count)
|
||||||
|
.or_insert(count);
|
||||||
}
|
}
|
||||||
_ if digits.len() % 2 == 0 => {
|
_ if (stone.checked_ilog10().unwrap_or(0) + 1) % 2 == 0 => {
|
||||||
let mid = digits.len() / 2;
|
let (left, right) = split(stone);
|
||||||
let left = digits[0..mid].parse().unwrap();
|
new_cache
|
||||||
let right = digits[mid..].parse().unwrap();
|
.entry(left)
|
||||||
stones[0] = left;
|
.and_modify(|n| *n += count)
|
||||||
stones.rotate_left(1);
|
.or_insert(count);
|
||||||
stones.push_front(right);
|
new_cache
|
||||||
stones.rotate_left(1);
|
.entry(right)
|
||||||
rots += 2;
|
.and_modify(|n| *n += count)
|
||||||
|
.or_insert(count);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
stones[0] = stone * 2024;
|
let new = stone * 2024;
|
||||||
stones.rotate_left(1);
|
new_cache
|
||||||
rots += 1;
|
.entry(new)
|
||||||
|
.and_modify(|n| *n += count)
|
||||||
|
.or_insert(count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stones.rotate_right(rots);
|
cache = new_cache;
|
||||||
}
|
|
||||||
stones.len()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blink3(mut stones: Vec<u128>, blinks: usize) -> usize {
|
cache.values().sum()
|
||||||
let mut total = stones.len();
|
|
||||||
for blink in 0..blinks {
|
|
||||||
let mut rights = Vec::new();
|
|
||||||
for stone in stones.iter_mut() {
|
|
||||||
let digits = stone.to_string();
|
|
||||||
match stone {
|
|
||||||
0 => {
|
|
||||||
*stone = 1;
|
|
||||||
}
|
|
||||||
_ if digits.len() % 2 == 0 => {
|
|
||||||
let mid = digits.len() / 2;
|
|
||||||
let left = digits[0..mid].parse().unwrap();
|
|
||||||
let right = digits[mid..].parse().unwrap();
|
|
||||||
*stone = left;
|
|
||||||
rights.push(right);
|
|
||||||
total += 1;
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
*stone *= 2024;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
total += blink3(rights, blinks - blink);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
total
|
fn split(num: u64) -> (u64, u64) {
|
||||||
|
let num_digits = num.ilog10() + 1;
|
||||||
|
let div = num_digits / 2;
|
||||||
|
let left = num.div_euclid(10u64.pow(div));
|
||||||
|
let right = num.rem_euclid(10u64.pow(div));
|
||||||
|
(left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(input: &str) -> Vec<u128> {
|
fn parse(input: &str) -> Vec<u64> {
|
||||||
input
|
input
|
||||||
.trim()
|
.trim()
|
||||||
.split(' ')
|
.split(' ')
|
||||||
|
@ -102,10 +85,4 @@ mod test {
|
||||||
let stones = parse("125 17");
|
let stones = parse("125 17");
|
||||||
assert_eq!(55312, pt1(&stones));
|
assert_eq!(55312, pt1(&stones));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn p2() {
|
|
||||||
let stones = parse("125 17");
|
|
||||||
assert_eq!(55312, blink3(stones, 25));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue