day(20): add solution
Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
parent
08246225fb
commit
4fe0d4d891
2 changed files with 117 additions and 0 deletions
7
samples/day20.txt
Normal file
7
samples/day20.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
1
|
||||||
|
2
|
||||||
|
-3
|
||||||
|
3
|
||||||
|
-2
|
||||||
|
0
|
||||||
|
4
|
110
src/bin/day20.rs
Normal file
110
src/bin/day20.rs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
use aoc_2022::*;
|
||||||
|
|
||||||
|
type Input = Vec<Coordinate>;
|
||||||
|
type Output = i64;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
struct Coordinate {
|
||||||
|
key: i64,
|
||||||
|
index: usize,
|
||||||
|
swapped: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Coordinate {
|
||||||
|
fn new(key: i64, index: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
key,
|
||||||
|
index,
|
||||||
|
swapped: key == 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
swapped: self.key == 0,
|
||||||
|
..*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index_of<T: PartialEq>(vector: &[T], key: &T) -> Option<usize> {
|
||||||
|
vector
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|&(_, val)| key == val)
|
||||||
|
.map(|found| found.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mix(order: &[Coordinate], mut coordinates: Input) -> Input {
|
||||||
|
let length: i64 = coordinates.len().try_into().unwrap();
|
||||||
|
|
||||||
|
for coordinate in order {
|
||||||
|
if coordinate.swapped {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let old_idx = index_of(&coordinates, coordinate).unwrap();
|
||||||
|
|
||||||
|
let mut new_idx = (old_idx as i64 + coordinate.key) % (length - 1);
|
||||||
|
if new_idx < 0 {
|
||||||
|
new_idx += length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut c = coordinates.remove(old_idx);
|
||||||
|
c.swapped = true;
|
||||||
|
coordinates.insert(new_idx as usize, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
coordinates.iter().map(Coordinate::reset).collect_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_sum(mixed: &[Coordinate]) -> Output {
|
||||||
|
let mixed = mixed.iter().map(|c| c.key).collect_vec();
|
||||||
|
let base_index = index_of(&mixed, &0).unwrap();
|
||||||
|
|
||||||
|
vec![1000, 2000, 3000]
|
||||||
|
.iter()
|
||||||
|
.map(|off| mixed[(base_index + off) % mixed.len()])
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Day20;
|
||||||
|
impl Solution<Input, Output> for Day20 {
|
||||||
|
fn parse_input<P: AsRef<Path>>(pathname: P) -> Input {
|
||||||
|
let coordinates: Vec<i64> = file_to_structs(pathname);
|
||||||
|
|
||||||
|
coordinates
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, key)| Coordinate::new(*key, i))
|
||||||
|
.collect_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_1(input: &Input) -> Output {
|
||||||
|
let order = input.clone();
|
||||||
|
let mixed = mix(&order, input.clone());
|
||||||
|
|
||||||
|
find_sum(&mixed)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_2(input: &Input) -> Output {
|
||||||
|
let decryption_key = 811589153;
|
||||||
|
let with_decryption = input
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|c| Coordinate::new(c.key * decryption_key, c.index))
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
let order = with_decryption.clone();
|
||||||
|
let mixed = (0..10).fold(with_decryption, |acc, _| mix(&order, acc));
|
||||||
|
|
||||||
|
find_sum(&mixed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
// Day20::run("sample")
|
||||||
|
Day20::main()
|
||||||
|
}
|
||||||
|
|
||||||
|
test_sample!(day_20, Day20, 3, 1623178306);
|
Loading…
Reference in a new issue