Day 24 part 1 solution.

Broken day 23 part 2.
Moved debug_println into lib.rs.
This commit is contained in:
Bill Thiede 2020-12-25 14:18:12 -08:00
parent 25855b47a6
commit 5e92b3a7e0
7 changed files with 870 additions and 34 deletions

View File

@ -13,3 +13,6 @@ aoc-runner-derive = "0.3.0"
regex = "1.4.2"
[dev-dependencies]
pretty_assertions = "0.6"
[profile.release]
debug = true

349
2020/input/2020/day24.txt Normal file
View File

@ -0,0 +1,349 @@
sewnwwwswnwnwwneneeenwwseswseww
nwwseneswnwsenwwweseneenesenwwwnw
seswewnwnesewneneneseseswwsesesesesenew
sesewnwwwswesenwswswneswswswwwnew
nwswenenwswenwnwwnwnwnw
wwswwwswwnwwe
wewnwsenwswnenwneneesenwwswsene
nenwnwnwnenwnesewnwnwnenwnene
nwewwwnwnwnwswwnw
nwnwseesewswsenesenesesewswseseseeswe
swnweseseenwseeswewneeneswewesesenw
enwneneeswneesewneneneenwnwneeese
senwswseesesesenwswseswsenwneseseseswsese
seswswnewneswswseneswsweswsw
swnwnwnwnwnenwwnwnwenwnwswnenwsenwnwnw
nenesesenenenenewenwneneneneswnewnwne
seweeeseewseseewseewwneeee
nwwwswwewwwswnwswswewswwsw
nwnwnwsesenwnenenwnwsesenwnwnwnwenwswnww
wesewsewswneneesenenenwnenwwnenwnwnw
nwnenwnenenenenenwnwsenw
wesweeswenwenweeenweswsenweew
senwswswnenwwsweneswweswwswenesew
nwwnwenesenwnwnwnenesenwsenwnenwwnwesw
newnwenenenwnenwsenwnenwnenesenenesese
seswnewnewnwswewnwswwwnenwsweeeww
nenwnenenwnwnwnenwnwnwneseswne
enwswswswenenwwswswneswse
wwsenwsewnewnwswnwsweswewwwwsw
eseeneewnwwnwneswneweeeeesee
swwneswswesenwnenwnwsenewwseseeswseene
wwswneswswswswneswswswswsewswswenesesw
nenenenenenenenenenenenwnesene
nwwnweswnwwwswenwswswwwswswwneeese
swneswnwseseseswswswweseswswswnweswewsw
weseseeswesenwseeeeseesenwesene
wswswseewnewswwneneswseneswwseswsese
wswnwneeenenenenenesenenenenenenwsenene
neneneneneswnewneeswnenwneeeenenene
swseswsewseswwsenwswneseswswseeseswsw
wswswswnesweswswswswwewnewswneseswswsw
nwsenesesesewweseseswnesewswne
sewswwnenwneneseeneesw
nwwnwnwnwswnwwnwnwwwnwne
enwsewneweeeseeeseseseeseeee
seswneewneenenewneneneneneswnweswne
seswseenesesewswswswsenwseesenwsesesw
swnwwnwnwnwnwnwwswswnwnenwenwnwenwnww
nenwnwnwwenenwswswnwnwnwnwenwnenwnwne
nwsewsenwneswsenwsenenwwnwnewswsenwe
wneenewwnwseneeseseewwseswsesese
swswneeeseesenwneesweneseesesenwsww
wnwsweswswwnwswwswswswnesewseswswnwew
swsewsesesewswneseswswswsenwneewnwe
nenenwnenwnenwsewnwnwnene
neseswswwwnwseenwswswwswwwese
enwnewwswwesenwnwnwswnwnwwwnwwnww
nesewnenwwswnweenenenwnenenene
wnwseeneseswnwnwsese
wewswsewwnenwwsenwwwnwwwwnw
wsesewsenesesewesenweseswseseseneneswse
eeswswsenwnesenewne
wseseswswswswswswswwenewnwswnwswswne
wswswswswewwwwswenwewwswnwswsw
enwnwneseswneeneswneeeeneneeswenenw
nenwewnwnenwnwnwnenwswsenwenwnwwnw
swnewseswseseseseesesesenwnwswenwsew
seewwwwwnewswwwnwwwnwnewnenwnwse
neswenweneneseeeneewneswneewneenesw
nesenwsewnwsenenenwwswnw
sesweeeneseneeneenwweenenewwsene
neneneeswnewneseswnewenenwewnenene
swneneswwwsenwnesenwnwwwnewnwnwww
nwenenwnwnwswwnwwnwnwsesenwsenwnwsenenw
seseseseseswsenwseseseseseneswnwsesewsw
nwswweswswnenewneswswswewswswswese
seeneseswseeeeesewseseenwneeswesw
seseeswswsesesewsesenwseesesesenwsese
nwsenwnenweswswenenwswesenwnesenenene
nwnwnwnwnwwsenwswnenwwnwnwnenwnwsenwsene
nenwnwwseneenwnwsw
eeeneeeeeseswe
neneesweneneseswnenwneneseneenewnwwe
wswneneneswswswseswnenewswswswswswswsw
neswswseswewswnewswswewswnwwswswenw
wwwseneweswnesesweseseswneswseese
wneeswenesenweneweneeeswnwswseene
wseneseneswnwneeneenwnenenenewnewne
nwsenewenenesewwnese
sewwnenwewwwsewswewsewwnewwww
seeeenweneswnwswseswnwnwwswswenwne
senwwwnwenwewnwnwewnwwwesenwenw
neswnewseenenewsweeesewnwenenwe
seneneswseweewnwnenwseweneneewnew
swwswnewnweseseswwwneweeneneseswwne
sesenewswswseseseseseneswwse
swsenwnenwwnenenenwnenee
sweeweenweeeswenwee
swsenwneseswewsesesewesenwsenweesw
swwsewswwswwswwwswswnwsw
eswnwneseswneneenenesw
newswsenwesewwwwwnenwswnwnwenwnwnw
seeseseenwseneenwneeesweeswewesw
seeeseswesesewsesenweeenwseeeesw
nenesenewnenewnenewwswneseseseenwnene
swwswneswswswwswwsewsw
sewesweeseeseneeeeee
seseswswswnewnwewsweseneswswsesewwsw
wnesenesweeenenenenenenwewnenenesw
nesenewwnwwneswnwnwsenwsewnw
enwwswnwwwwnwnwwnww
sewneeeseseenwnwnwseswseseseeseneese
eseseseseswneseseenenweseswseswe
swsesesenwneswswwneseeseeswwnwswswse
swnwneseseseswseseswseseseseseswnesewsw
nwswwwseesweswwswwne
sewnwnwwsewsewsenenwnwnwwnenwwnwwesw
wwwnwwnwnwswwswwnwwnewwe
seswnwenweswewnwswseneseswneewnww
seseseseseneseesesesesesenwsewsewsese
swwsesenwswnwswnwewnwnwnwnenwnwnwnwwne
senwseeeeeeseeseewsese
swswenewswswneseseswseswnwswneseswww
neneneneseneneeneneneneswneswnwenwesene
swseswseseseneesenenewewwseeswnenew
swnwnewwwwwwsewwweswwwneww
wswswnwswwwswneseswswswswwswseweswsenw
enwswnwnesenwnwenwenwswneneswnwnwnww
eneesweneneneeswnwne
wnwwewwnwwnwwwnese
nwwewneseeeswenwseswswswswsenwwswnwsw
wnwnwnwwnwnwwwwwnesew
wnwswseeswenewww
nwnwnwnwnwwnwseswneenwnenw
enesweeneseeeweenwseneswwswee
sewwwswneswnwsewswsw
neseseswneswwswswseseswneseseswseswswse
eseswswswswnwswseswswswse
eeseswnwswswseenwwseswnwseneseswsene
wwswneneswsewwneswswseswseswwwwnw
newswwsewneeneseeseseewsewnwweswse
nwnenwnwnwnenwnwnwwnwswnwnwnwnwsweenw
neneenesewnenewsenenenenwswwneenenese
neneseneneneneneneseeneneneswwnenewnene
nweswnwseswsweeeeenenenwsweseweese
swneswseswswswnwseseswswswswnwseeswwsw
wnwsenwwnwsenwwswnenwnwwnwenenewsenesw
nweseseeswsweesenweswnenweseseee
wswnenwnwnwsenwwenwnwseenwswnwnwsenwnene
nwnwnewnwnwnwnwwnwswnwnesweswsenwnwnww
neweewenenwneeeeneeseseswseenew
weweesweseneeswwseenwnwnewneee
wnesweneeeneseenwwwseenesweww
wnewseneneswswseswswwnesenwneswnewsenw
seswnwewsewswswswwnenwswsene
swswwnewswsewswweswswneseswswsw
nwewsweeneneneneswnww
newneweneneneswneneneneneneeneeseswne
nenwewnewseswnewneeswswseesenenww
seswswswneswswwswswswseneswneseneswsesww
nenenenenenwneeneseeesweneswsenwnenwww
eeneeeeeneeenesweesw
swwseneswsweswseswwseswseswneseswsenewse
seenweneeswwwwswnenenewneseneene
swswneswswswsewseseneseswweeenwwnwswsw
newnwswnewwnewwsesenwswnw
weneswswnewnwsenwswnenesenwnenenwnene
sesesesweseweswsewsewenwseesenwse
nenweenwwnwwsewnwwswnwnesenwwswsw
swnwswnwseneneseseswswseswwswsewneswswsese
nenwnenwenenesenwnenwnwswnwne
nwswswweseswswneswseew
eeswseenweeeseweseeeesee
sewwswswswseneswsweseneswswswneseswwsw
ewewnwsweeenesweeneseeswneenwe
neneswesenwnwsweeseswnwswwswnwewesw
neeneneeswenweeeeneneee
nenesesenenwnwnwnesewnwneneneswnenwnenwne
seseseneweneswwseseswsenwseseseswsese
sewsewneewewnwswwwneww
seseseseeseseswsenwsesesenwsenwseseee
sewwwwneswwesenwwwswswswww
eneeswneseweeweeewenweeene
swswnwswsweswswseseseswse
seseseswsenwswseseseeseswsesesesenwe
nenenewnenwnenwneeenenwnenwneneneswse
eseeeeeenweeeeee
wwwwnwwnewnwsewswwswneweesesew
seenewwneneneseeeneneenenenewnene
seswswneneeenwswwnwenenewnenenenesene
eeewneseeeswseenweewseewee
eeeewsweeenwnwweeseeneenenew
nwneswswnenwnenwnesenwnwwnwneswnwseswsew
nwsweeneeneseeenewnwnwneneswneswne
swsesewseseesenenew
nenesweseeeeewesweeesenwseee
nwnwenwwswsewswwneenwwnwsewseene
enwneneneswneeneneneswnenweeneswsene
swswwswswneswseswswwwswswsw
swswswswseswseneeswnewswwsesese
wseeswesenenwenenenwneeneweeswnee
eseenwseeseenwnwsweseseesesenw
sewswseseeseseseneseswsenesesewsesesw
swswnesenenwnewseewsweswneswwswswswse
sewwswseswnenwwewwswwwsewwnwswnwnw
nwnwnwenwwnwnwnwsenenwnwnw
swwnwsweswseeewnewwwnese
swwenwnwnwwswseeewnwnwwewswnenwne
seseneesenenwswnewwseesewseeswsese
swsesweeswnesewweeneswwswwswseswne
wswsewwwswnwwwnwwnenewwwseewnw
eewswnesenwswnwnewseeswnwnwnw
nwwwnewwewnwnwwnwnewwnwewswsw
sesewneswneenwseswseesese
neswweneeenesweneenesenewne
nwwnwseswswnwnwnenwnweswnwswnwwweenw
enwnenwnewenwnenenwnwwnene
neswnwnenenwnwswenenwnewse
nwweneenenewswneswnwenenesenwnewnw
neeswsewswnwnewswswswsesewnwneseswswsw
senwneswwnwnenenwnenenesenewenenenenene
sesewneswswsweenwsesweswnw
ewneesewneeeenesenweswnesesweee
swsewwwwnwwwewnenwsewwwsewwnene
swswnwseswesesweswneseswswseswswnwswnwswse
swseswswneseeseswneswenwneeswwnwswnww
weeswswnwswswswnwnwswswsweeswswswsww
nesewnwswseswwenweweseeeswnesene
sweseswnesenwseesesweneeswsesenwnesw
nwseeswseseeneswseswnwsweswseswsewse
sesewsesesweseeneenwesee
seneesewswewswnwsesw
seseseeseseseesesewseenenwnwsesesee
wneeeseseewswswseewnesenenwesenw
eneneeeneewneeenee
eneneneenenenewnenenesenwwnesw
eeeeeseeeenwe
nwnwnwnwnwenwnwnwnwwnw
seenwnenwswsenenwnenenewnenwnenenwnwnw
swenewweeeneseneneneeenweewnesw
nwnwnwnenwnenwnwnwnwse
seswswseesewswwseswneswswseenw
senewsewswnwewneswsewneenewwswsw
nenenwenwnenwswnenwnwne
nenenenenenwnenenewneneneswenene
eseneseseseswseseseseeee
wseseeneeseswseseseseenwwsewseswse
enwneeneneeneeseweeeeeewnesw
swswswswswswenwneswswwswswswneseswswe
eeeeeweneeee
wswswswnwewswswnwnweswwwswweswwse
nenenewnewseneneesweenweeneneeene
nenwneseswnwnenenewsesenenenwnesenewsenene
wswsenwswswseseswsenewneneseseseswswsese
nenwnwneenwswnwenwnwnenwnenwnwnwnewsw
nwnwwwnwwwwwneswnwwww
senweneswseeseweeseeewenewseee
eseseeeweesesesesesee
senenwnenwnewneeswneseenenwswseneneswne
nenwnenenewseneenenesesenenenewnenene
wnwnenenenewnenwwsenewseeseeswnenw
nwnwswwnesewnweewswnenwenenwnwwene
senwnenwnwnwnenwwnwnwnwwnenwesenwnwnw
seeeeeenwswswesenwnwsewesew
newwswnewsenwwwswwwenwnewwww
neneswnenwseewneneneneneneneneesenewnw
eneeesenewseneweswneeneneeenewe
seesewseeesesenwnwnwsweseseswsesesesee
enweseeeeenweseeswnwseewseeese
eswneeeeeeeenweneeeeesw
senwseseswseseeneseeseseseesewswnewe
nwnwnwenwsenwesenewnwswnwswnwnwnwnwnwnenw
neeneeenwsweeeenwsesweneneeewe
sweenenenewwneneneneenenenene
enweeeeeeneneeneneese
eneeseswsewsenwneswsweseswneeesenesw
enwwnwswnwnwwwwnwewnwwsewnwnwnw
wnwwwnwwewswnww
nenwneeswweswnesweneneeeswswewse
eswweseeseneenweneeewenwe
eswswswnweswswsweswswwswswnwsenewswnwne
swwseweneeeeweseeseesenenw
eeeeeenesweseeeeswnesweenwe
swwswneswwswwwswnewswwwewwswnw
nwneswnwswnenenwneenwnwenwnwnwnenwew
newwnwsewsewnwwweneswswnwwnwnew
neesweswswnwseswwwwwswneneswsenwwww
wswnewwwwwswneseswnwneneswwswwsew
eneswwwswnewwswswweswwwwswnwnenw
eswseneseswswsewseseswseseswseswswnwne
eeeeeeeeeeewswenenwee
sewnenenenewnwnwseeenwseswswweee
nenenenenenwseseneneneenenewneswswwnwnenw
wswswnwswnwseswseneswswswnewsweswsesw
eeewnenwneswwseseneeswseesewww
wsesweswswswswswswswswswswswnwwnwswenw
nwseswswswwswswsene
sewwwswwnwswswwnewswwnesewsesww
swwswswswswswswwswsenwne
nwnenwnwsewwnwwnwnwnwnwseww
swewseewnwenweseseneswnwenwsweesee
eeweswswneneenwesweneeeeseee
wseseseesesenewnwnesewswseseseesee
wswwnesewwnwwwnwseneswwwwew
nwwnenwwswnwweseeeswseseneenwwnwne
sewwwnwwsewwnwesesewswnwnwwnewe
newsesenwwsenesesewwneseseseseseneseesw
sweweseneseswnwswweswseswnwswnwnwsww
swsenenwnwneswnwnenwnenwnenenwnwewnw
swswwewwswsewewwwsenwwwnewwww
nenwsenwnwswnenwnenenwsenenwwnwnesenwne
seseseeeesewswnesesenweseseneewse
esesenweswseseneweeseseesesesee
wwswsewwwnewenewwwwwwnwnww
nwneseneeseeeseswnewseeswse
nwneneneeneenenese
eswseeeseesenweesesenwweewsesesese
wneweseswswnwswneneeeeene
nenewnwnenenwswsenenenesenwswneswswnenenw
sewnenwseswsesenwswnenenwnwnwnwnwwenw
nwnwnwenenwnwnwnwswnenenwnwsewnwsenwse
sesenewwnenwwnwwneswwswnwewenenwsw
neneewnwnesenwnwnenewneswnenwnenenwenw
neseenweneswnwnwneswwnwnwnwnenenenwnenw
nenenweswwneswnwnenenenweneenwswnene
swnenesenenenenenenenenwnenenwene
wneswnenwswwswseenwwwwwsew
sewwwnenewwwwwnesewwwswsewwne
nesenwneenesweeenwenene
seseeseeeswsenwseseeseseesesewsenw
nwnenwnwneneeenwswnenwswnwswneenwnwnwnenw
seneneeesweewesewwsewwnewee
nwwnenwsewnwwnwnwnwenenwnwwsewsenwnw
wswwwwwwswswsewneneewseenenwnw
nwseeswesesesesenwseenweeeeeeesw
seenewnenwswsenwnenesewnwswsenwnewnenw
wnwnewseswneeneeweenwnenweenese
swswsweenwnesenwswwneswseswwseneswse
nwesenenwnewneenwnwnwnwneswsesenwnwnenene
enenewneneneneneswewswneeneweneese
nwwwnwsenwnwwwnwwnwnenww
nwnwwnwnwnwnenwnwnwnwseswnwnwnwnew
swnewnenwneswenesenenwneewneneswnenesw
nwsewnwnwwnwswnewnenwwnwnwse
seneneswneneewnenwnenenewneswenenwsene
sweseneeeenewenenenweneenewene
enwwwwwwwnwwwsewwwswnewsene
sewewseswwsenwnwwesewewwwwnenew
nenwnwnwnwewnwsww

View File

@ -0,0 +1,2 @@
12092626
4707356

View File

@ -372,6 +372,8 @@ use std::collections::{HashSet, VecDeque};
use aoc_runner_derive::aoc;
use crate::debug_println;
#[derive(Clone, Debug, PartialEq)]
struct Players {
p1: VecDeque<usize>,
@ -402,10 +404,6 @@ fn deck_to_str(deck: &VecDeque<usize>) -> String {
s
}
macro_rules! debug_println {
($($arg:tt)*) => (#[cfg(debug_assertions)] println!($($arg)*));
}
use std::sync::atomic::{AtomicUsize, Ordering};
static GAME_NUM: AtomicUsize = AtomicUsize::new(1);
impl Players {

View File

@ -71,17 +71,250 @@
//!
//! Using your labeling, simulate 100 moves. What are the labels on the cups after cup 1?
//! --- Part Two ---
//! Due to what you can only assume is a mistranslation (you're not exactly fluent in Crab), you are quite surprised when the crab starts arranging many cups in a circle on your raft - one million (1000000) in total.
//!
//! Your labeling is still correct for the first few cups; after that, the remaining cups are just numbered in an increasing fashion starting from the number after the highest number in your list and proceeding one by one until one million is reached. (For example, if your labeling were 54321, the cups would be numbered 5, 4, 3, 2, 1, and then start counting up from 6 until one million is reached.) In this way, every number from one through one million is used exactly once.
//!
//! After discovering where you made the mistake in translating Crab Numbers, you realize the small crab isn't going to do merely 100 moves; the crab is going to do ten million (10000000) moves!
//!
//! The crab is going to hide your stars - one each - under the two cups that will end up immediately clockwise of cup 1. You can have them if you predict what the labels on those cups will be when the crab is finished.
//!
//! In the above example (389125467), this would be 934001 and then 159792; multiplying these together produces 149245887792.
//!
//! Determine which two cups will end up immediately clockwise of cup 1. What do you get if you multiply their labels together?
use std::fmt;
use std::ops::{Index, IndexMut, Range, RangeFrom};
use aoc_runner_derive::aoc;
struct Hand {
use crate::debug_println;
trait Hand {
fn play(&mut self, rounds: usize) {
use std::time::{Duration, Instant};
let start = Instant::now();
let mut last_report = Instant::now();
(0..rounds).for_each(|i| {
debug_println!("-- move {} --", i + 1);
if last_report.elapsed() > Duration::new(1, 0) {
let elapsed = start.elapsed();
let runtime = elapsed * rounds as u32 / i as u32;
let eta = runtime - elapsed;
println!(
"{} steps ({}%) in {}s, Estimated runtime {}s, ETA {}s",
i,
100 * i / rounds,
elapsed.as_secs_f32(),
runtime.as_secs_f32(),
eta.as_secs_f32(),
);
last_report = Instant::now();
}
self.step();
});
}
fn part1_answer(&self) -> String;
fn part2_answer(&self) -> usize;
fn step(&mut self);
fn test_cur_to_end(&self) -> Vec<usize>;
}
#[derive(Debug)]
struct TargetCup {
val: usize,
idx: usize,
}
#[derive(Debug)]
struct FastHand {
idx_to_val: Vec<usize>,
val_to_idx: Vec<usize>,
cur: usize,
min: usize,
max: usize,
}
impl FastHand {
fn new(s: &str) -> FastHand {
let data: Vec<_> = s.bytes().map(|s| (s - b'0') as usize).collect();
let min = *data.iter().min().unwrap();
let max = *data.iter().max().unwrap();
let mut idx_to_val = vec![0; data.len()];
let mut val_to_idx = vec![0; data.len()];
data.into_iter().enumerate().for_each(|(idx, val)| {
val_to_idx[val - 1] = idx;
idx_to_val[idx] = val;
});
FastHand {
idx_to_val,
val_to_idx,
cur: 0,
min,
max,
}
}
fn new_part2(s: &str) -> FastHand {
let mut data: Vec<_> = s.bytes().map(|s| (s - b'0') as usize).collect();
let min = *data.iter().min().unwrap();
let mut max = *data.iter().max().unwrap();
data.extend(max + 1..=1000000);
max = 1000000;
let mut idx_to_val = vec![0; data.len()];
let mut val_to_idx = vec![0; data.len()];
data.into_iter().enumerate().for_each(|(idx, val)| {
val_to_idx[val - 1] = idx;
idx_to_val[idx] = val;
});
FastHand {
idx_to_val,
val_to_idx,
cur: 0,
min,
max,
}
}
fn destination_cup_idx(&self, skip_vals: &[usize]) -> usize {
let mut search_val = self.idx_to_val[self.cur] - 1;
while skip_vals.contains(&search_val) {
search_val -= 1;
}
if search_val < self.min {
search_val = self.max;
}
while skip_vals.contains(&search_val) {
search_val -= 1;
}
self.val_to_idx[search_val - 1]
}
}
impl fmt::Display for FastHand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (idx, val) in self.idx_to_val.iter().enumerate() {
if idx == self.cur {
write!(f, "({}) ", val)?;
} else {
write!(f, "{} ", val)?;
};
}
Ok(())
}
}
#[derive(Debug)]
struct CircleVec<T> {
data: Vec<T>,
}
impl<T> CircleVec<T> {
fn len(&self) -> usize {
self.data.len()
}
fn iter(&self) -> impl Iterator<Item = &T> {
self.data.iter()
}
}
// TODO(wathiede): Index<Range> and Index<RangeFrom>?
impl<T> Index<usize> for CircleVec<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.data[index % self.data.len()]
}
}
impl<T> IndexMut<usize> for CircleVec<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
let len = self.data.len();
&mut self.data[index % len]
}
}
impl Hand for FastHand {
fn step(&mut self) {
let n_cups = self.idx_to_val.len();
let right_idx = self.cur + 1;
let mut three = vec![0; 3];
(0..3).for_each(|dst| three[dst] = self.idx_to_val[(right_idx + dst) % n_cups]);
let dst_idx = self.destination_cup_idx(&three);
// TODO
debug_println!(
"before {} three {:?} target {}",
self,
three,
self.idx_to_val[dst_idx]
);
//dbg!(right, &dst);
let end_idx = if dst_idx < right_idx {
n_cups + dst_idx - 3 + 1
} else {
dst_idx + 1 - 3
};
debug_println!("moving window {}.. to {}..{}", dst_idx, right_idx, end_idx);
(right_idx..end_idx)
// Allow wrap around.
.zip((right_idx + 3..).chain(0..))
.for_each(|(dst_idx, src_idx)| {
let src_idx = src_idx % n_cups;
let dst_idx = dst_idx % n_cups;
let v = self.idx_to_val[src_idx];
debug_println!(
"moving {}({}) -> {}({})",
v,
src_idx,
self.idx_to_val[dst_idx],
dst_idx
);
self.idx_to_val[dst_idx] = v;
self.val_to_idx[v - 1] = dst_idx;
});
(0..3).for_each(|i| {
let dst_idx = (end_idx + i) % n_cups;
self.idx_to_val[dst_idx] = three[i];
self.val_to_idx[three[i] - 1] = dst_idx;
});
self.cur = (self.cur + 1) % n_cups;
debug_println!(" after {}", self);
}
fn test_cur_to_end(&self) -> Vec<usize> {
self.idx_to_val[self.cur..]
.iter()
.chain(self.idx_to_val[..self.cur].iter())
.cloned()
.collect()
}
fn part1_answer(&self) -> String {
let one_idx = self.val_to_idx[1 - 1];
let s = self.idx_to_val[one_idx + 1..]
.iter()
.fold("".to_string(), |acc, c| format!("{}{}", acc, c));
self.idx_to_val[..one_idx]
.iter()
.fold(s, |acc, c| format!("{}{}", acc, c))
}
fn part2_answer(&self) -> usize {
let one_idx = self.val_to_idx[1 - 1];
self.idx_to_val[one_idx + 1] * self.idx_to_val[one_idx + 2]
}
}
struct SlowHand {
cups: Vec<usize>,
cur: usize,
min: usize,
max: usize,
}
impl fmt::Display for Hand {
impl fmt::Display for SlowHand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, cup) in self.cups.iter().enumerate() {
if i == self.cur {
@ -94,12 +327,12 @@ impl fmt::Display for Hand {
}
}
impl Hand {
fn new(s: &str) -> Hand {
impl SlowHand {
fn new(s: &str) -> SlowHand {
let cups: Vec<_> = s.bytes().map(|s| (s - b'0') as usize).collect();
let min = *cups.iter().min().unwrap();
let max = *cups.iter().max().unwrap();
Hand {
SlowHand {
cups,
cur: 0,
min,
@ -107,15 +340,33 @@ impl Hand {
}
}
fn play(&mut self, rounds: usize) -> String {
(0..rounds).for_each(|i| {
println!("-- move {} --", i + 1);
self.step();
});
self.answer()
fn new_part2(s: &str) -> SlowHand {
let mut cups: Vec<_> = s.bytes().map(|s| (s - b'0') as usize).collect();
let min = *cups.iter().min().unwrap();
let mut max = *cups.iter().max().unwrap();
cups.extend(max + 1..1000000);
max = 1000000;
SlowHand {
cups,
cur: 0,
min,
max,
}
}
}
impl Hand for SlowHand {
fn part1_answer(&self) -> String {
let idx = self.cups.iter().position(|i| i == &1).unwrap();
let s = self.cups[idx + 1..]
.iter()
.fold("".to_string(), |acc, c| format!("{}{}", acc, c));
self.cups[..idx]
.iter()
.fold(s, |acc, c| format!("{}{}", acc, c))
}
fn step(&mut self) {
println!("{}", self);
debug_println!("{}", self);
let cur = self.cups[self.cur];
let mut pickups = Vec::new();
let mut destination = self.cups[self.cur] - 1;
@ -140,9 +391,9 @@ impl Hand {
}
//dbg!(&pickups, &self.cups, destination);
let idx = self.cups.iter().position(|i| i == &destination).unwrap();
println!("pick up: {:?}", pickups);
println!("destination: {}({})", destination, idx);
println!("next destination: {}", next);
debug_println!("pick up: {:?}", pickups);
debug_println!("destination: {}({})", destination, idx);
debug_println!("next destination: {}", next);
pickups
.into_iter()
@ -151,21 +402,34 @@ impl Hand {
self.cur = self.cups.iter().position(|i| i == &next).unwrap();
}
fn answer(&self) -> String {
let idx = self.cups.iter().position(|i| i == &1).unwrap();
let s = self.cups[idx + 1..]
/// Return internal state in a way unit tests can use
fn test_cur_to_end(&self) -> Vec<usize> {
self.cups[self.cur..]
.iter()
.fold("".to_string(), |acc, c| format!("{}{}", acc, c));
self.cups[..idx]
.iter()
.fold(s, |acc, c| format!("{}{}", acc, c))
.chain(self.cups[..self.cur].iter())
.cloned()
.collect()
}
fn part2_answer(&self) -> usize {
let one = self.cups.iter().position(|n| n == &1).unwrap();
self.cups[one + 1] * self.cups[one + 2]
}
}
#[aoc(day23, part1)]
fn solution1(input: &str) -> String {
let mut hand = Hand::new(input);
hand.play(100)
let mut hand = SlowHand::new(input);
hand.play(100);
hand.part1_answer()
}
#[aoc(day23, part2)]
fn solution2(input: &str) -> usize {
let mut hand = FastHand::new_part2(input);
//hand.play(1_000);
hand.play(10_000_000);
hand.part2_answer()
}
#[cfg(test)]
@ -173,13 +437,56 @@ mod tests {
use super::*;
const INPUT: &'static str = "389125467";
#[test]
fn part1_10step() {
let mut hand = Hand::new(INPUT);
assert_eq!(hand.play(10), "92658374");
fn test_hand<H: Hand>(mut hand: H) {
let want = vec![
[3, 8, 9, 1, 2, 5, 4, 6, 7],
[2, 8, 9, 1, 5, 4, 6, 7, 3],
[5, 4, 6, 7, 8, 9, 1, 3, 2],
[8, 9, 1, 3, 4, 6, 7, 2, 5],
[4, 6, 7, 9, 1, 3, 2, 5, 8],
[1, 3, 6, 7, 9, 2, 5, 8, 4],
[9, 3, 6, 7, 2, 5, 8, 4, 1],
[2, 5, 8, 3, 6, 7, 4, 1, 9],
[6, 7, 4, 1, 5, 8, 3, 9, 2],
[5, 7, 4, 1, 8, 3, 9, 2, 6],
[8, 3, 7, 4, 1, 9, 2, 6, 5],
];
want.iter().enumerate().for_each(|(step, want)| {
assert_eq!(hand.test_cur_to_end(), want, "step0 {}", step);
hand.step();
});
}
//#[test]
#[test]
fn slow_step() {
let mut hand = SlowHand::new(INPUT);
test_hand(hand);
}
#[test]
fn fast_step() {
let mut hand = FastHand::new(INPUT);
test_hand(hand);
}
#[test]
fn part1_10step_slow() {
let mut hand = SlowHand::new(INPUT);
hand.play(10);
assert_eq!(hand.part1_answer(), "92658374");
}
#[test]
fn part1_10step_fast() {
let mut hand = FastHand::new(INPUT);
hand.play(10);
assert_eq!(hand.part1_answer(), "92658374");
}
#[test]
fn part1() {
assert_eq!(solution1(INPUT), "67384529");
}
#[test]
fn part2() {
assert_eq!(solution2("389125467"), 149245887792);
}
}

166
2020/src/day24.rs Normal file
View File

@ -0,0 +1,166 @@
//! --- Day 24: Lobby Layout ---
//! Your raft makes it to the tropical island; it turns out that the small crab was an excellent navigator. You make your way to the resort.
//!
//! As you enter the lobby, you discover a small problem: the floor is being renovated. You can't even reach the check-in desk until they've finished installing the new tile floor.
//!
//! The tiles are all hexagonal; they need to be arranged in a hex grid with a very specific color pattern. Not in the mood to wait, you offer to help figure out the pattern.
//!
//! The tiles are all white on one side and black on the other. They start with the white side facing up. The lobby is large enough to fit whatever pattern might need to appear there.
//!
//! A member of the renovation crew gives you a list of the tiles that need to be flipped over (your puzzle input). Each line in the list identifies a single tile that needs to be flipped by giving a series of steps starting from a reference tile in the very center of the room. (Every line starts from the same reference tile.)
//!
//! Because the tiles are hexagonal, every tile has six neighbors: east, southeast, southwest, west, northwest, and northeast. These directions are given in your list, respectively, as e, se, sw, w, nw, and ne. A tile is identified by a series of these directions with no delimiters; for example, esenee identifies the tile you land on if you start at the reference tile and then move one tile east, one tile southeast, one tile northeast, and one tile east.
//!
//! Each time a tile is identified, it flips from white to black or from black to white. Tiles might be flipped more than once. For example, a line like esew flips a tile immediately adjacent to the reference tile, and a line like nwwswee flips the reference tile itself.
//!
//! Here is a larger example:
//!
//! sesenwnenenewseeswwswswwnenewsewsw
//! neeenesenwnwwswnenewnwwsewnenwseswesw
//! seswneswswsenwwnwse
//! nwnwneseeswswnenewneswwnewseswneseene
//! swweswneswnenwsewnwneneseenw
//! eesenwseswswnenwswnwnwsewwnwsene
//! sewnenenenesenwsewnenwwwse
//! wenwwweseeeweswwwnwwe
//! wsweesenenewnwwnwsenewsenwwsesesenwne
//! neeswseenwwswnwswswnw
//! nenwswwsewswnenenewsenwsenwnesesenew
//! enewnwewneswsewnwswenweswnenwsenwsw
//! sweneswneswneneenwnewenewwneswswnese
//! swwesenesewenwneswnwwneseswwne
//! enesenwswwswneneswsenwnewswseenwsese
//! wnwnesenesenenwwnenwsewesewsesesew
//! nenewswnwewswnenesenwnesewesw
//! eneswnwswnwsenenwnwnwwseeswneewsenese
//! neswnwewnwnwseenwseesewsenwsweewe
//! wseweeenwnesenwwwswnew
//! In the above example, 10 tiles are flipped once (to black), and 5 more are flipped twice (to black, then back to white). After all of these instructions have been followed, a total of 10 tiles are black.
//!
//! Go through the renovation crew's list and determine which tiles they need to flip. After all of the instructions have been followed, how many tiles are left with the black side up?
use std::collections::HashMap;
use aoc_runner_derive::{aoc, aoc_generator};
#[derive(Debug, PartialEq)]
enum Direction {
East,
SouthEast,
SouthWest,
West,
NorthWest,
NorthEast,
}
#[derive(Debug, PartialEq, Eq, Hash)]
struct TileCoord((isize, isize, isize));
#[derive(Debug, PartialEq)]
struct Tile {
directions: Vec<Direction>,
}
impl std::str::FromStr for Tile {
type Err = ();
fn from_str(s: &str) -> Result<Tile, ()> {
let mut it = s.bytes();
let mut directions = Vec::new();
use Direction::*;
while let Some(b) = it.next() {
match b {
b'n' => match it.next().unwrap() {
b'e' => directions.push(NorthEast),
b'w' => directions.push(NorthWest),
c => panic!(format!("unexpected tile direction {}", c)),
},
b's' => match it.next().unwrap() {
b'e' => directions.push(SouthEast),
b'w' => directions.push(SouthWest),
c => panic!(format!("unexpected tile direction {}", c)),
},
b'e' => directions.push(East),
b'w' => directions.push(West),
c => panic!(format!("unexpected tile direction {}", c)),
}
}
Ok(Tile { directions })
}
}
impl Tile {
fn coord(&self) -> TileCoord {
// Based on 'cube coordinates' from https://www.redblobgames.com/grids/hexagons/
TileCoord(
self.directions
.iter()
.fold((0, 0, 0), |(x, y, z), dir| match dir {
Direction::East => (x + 1, y - 1, z),
Direction::SouthEast => (x, y - 1, z + 1),
Direction::SouthWest => (x - 1, y, z + 1),
Direction::West => (x - 1, y + 1, z),
Direction::NorthWest => (x, y + 1, z - 1),
Direction::NorthEast => (x + 1, y, z - 1),
}),
)
}
}
#[aoc_generator(day24)]
fn parse(input: &str) -> Vec<Tile> {
input
.split('\n')
.map(|l| l.parse().expect("Failed to parse tile"))
.collect()
}
#[aoc(day24, part1)]
fn solution1(tiles: &[Tile]) -> usize {
let mut colors: HashMap<TileCoord, bool> = HashMap::new();
tiles.iter().for_each(|t| {
let v = colors.entry(t.coord()).or_insert(false);
*v = !*v;
});
colors.values().filter(|v| **v).count()
}
#[cfg(test)]
mod tests {
use super::*;
const INPUT: &'static str = r#"
sesenwnenenewseeswwswswwnenewsewsw
neeenesenwnwwswnenewnwwsewnenwseswesw
seswneswswsenwwnwse
nwnwneseeswswnenewneswwnewseswneseene
swweswneswnenwsewnwneneseenw
eesenwseswswnenwswnwnwsewwnwsene
sewnenenenesenwsewnenwwwse
wenwwweseeeweswwwnwwe
wsweesenenewnwwnwsenewsenwwsesesenwne
neeswseenwwswnwswswnw
nenwswwsewswnenenewsenwsenwnesesenew
enewnwewneswsewnwswenweswnenwsenwsw
sweneswneswneneenwnewenewwneswswnese
swwesenesewenwneswnwwneseswwne
enesenwswwswneneswsenwnewswseenwsese
wnwnesenesenenwwnenwsewesewsesesew
nenewswnwewswnenesenwnesewesw
eneswnwswnwsenenwnwnwwseeswneewsenese
neswnwewnwnwseenwseesewsenwsweewe
wseweeenwnesenwwwswnew
"#;
#[test]
fn tile() {
use Direction::*;
assert_eq!(
"esenee".parse::<Tile>().expect("failed to parse tile"),
Tile {
directions: vec![East, SouthEast, NorthEast, East]
}
);
}
#[test]
fn part1() {
assert_eq!(solution1(&parse(INPUT)), 10);
}
}

View File

@ -13,7 +13,8 @@ pub mod day2;
//pub mod day20;
pub mod day21;
pub mod day22;
pub mod day23;
//pub mod day23;
pub mod day24;
pub mod day3;
pub mod day4;
pub mod day5;
@ -24,4 +25,14 @@ pub mod day9;
use aoc_runner_derive::aoc_lib;
#[macro_export]
macro_rules! debug_print{
($($arg:tt)*) => (#[cfg(debug_assertions)] print!($($arg)*));
}
#[macro_export]
macro_rules! debug_println {
($($arg:tt)*) => (#[cfg(debug_assertions)] println!($($arg)*));
}
aoc_lib! { year = 2020 }