Work on day20
This commit is contained in:
parent
7353989dd2
commit
db7cfc6b49
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -357,6 +357,9 @@ version = "0.1.0"
|
|||
[[package]]
|
||||
name = "day20"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day21"
|
||||
|
|
|
@ -8,3 +8,4 @@ build = true
|
|||
app = true
|
||||
|
||||
[dependencies]
|
||||
bitvec = "1.0.1"
|
||||
|
|
5000
day20/input
Normal file
5000
day20/input
Normal file
File diff suppressed because it is too large
Load diff
7
day20/input.test
Normal file
7
day20/input.test
Normal file
|
@ -0,0 +1,7 @@
|
|||
1
|
||||
2
|
||||
-3
|
||||
3
|
||||
-2
|
||||
0
|
||||
4
|
|
@ -1,3 +1,193 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader},
|
||||
ops::{Range, RangeInclusive},
|
||||
};
|
||||
|
||||
use bitvec::{prelude::Msb0, vec::BitVec};
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
enum SolvePuzzle {
|
||||
First,
|
||||
#[default]
|
||||
Second,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct List {
|
||||
numbers: Vec<i64>,
|
||||
number_positions: Vec<usize>,
|
||||
}
|
||||
|
||||
impl List {
|
||||
fn parse_input<const DECRYPTION_KEY: i64, R: BufRead>(reader: R) -> Self {
|
||||
reader
|
||||
.lines()
|
||||
.map(Result::unwrap)
|
||||
.map(|line| line.parse())
|
||||
.map(Result::unwrap)
|
||||
.map(|number: i64| number * DECRYPTION_KEY)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn apply_rotation(&mut self) {
|
||||
let mut moved: BitVec<usize, Msb0> = BitVec::repeat(false, self.numbers.len());
|
||||
println!("NUM: {:>3?}", self.numbers);
|
||||
println!("POS: {:>3?}", self.number_positions);
|
||||
println!(
|
||||
"MOV: {:>3?}",
|
||||
moved.iter().by_vals().map(u8::from).collect::<Vec<_>>()
|
||||
);
|
||||
println!(
|
||||
"***: {:>3?}",
|
||||
self.number_positions
|
||||
.iter()
|
||||
.map(|&idx| self.numbers[idx])
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
for position_index in 0..self.number_positions.len() {
|
||||
let number_index = self.number_positions[position_index];
|
||||
println!("\n=== {number_index} ===");
|
||||
let elem = self.numbers[position_index];
|
||||
let op = Operation::new(elem, number_index, self.numbers.len());
|
||||
println!("OP: {op:?}");
|
||||
let idx_saved = self.number_positions[op.from];
|
||||
let rotate_right = op.should_rotate_right();
|
||||
let range = op.get_rotation_range();
|
||||
if rotate_right {
|
||||
self.number_positions[range.clone()].rotate_right(1);
|
||||
moved[range.clone()].rotate_left(1);
|
||||
} else {
|
||||
self.number_positions[range.clone()].rotate_left(1);
|
||||
moved[range.clone()].rotate_right(1);
|
||||
}
|
||||
self.number_positions[op.to] = idx_saved;
|
||||
moved.set(op.to, true);
|
||||
println!("NUM: {:>3?}", self.numbers);
|
||||
println!("POS: {:>3?}", self.number_positions);
|
||||
println!(
|
||||
"MOV: {:>3?}",
|
||||
moved.iter().by_vals().map(u8::from).collect::<Vec<_>>()
|
||||
);
|
||||
println!(
|
||||
"***: {:>3?}",
|
||||
self.number_positions
|
||||
.iter()
|
||||
.map(|&idx| self.numbers[idx])
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn sum_of_magic_positions(&self) -> i64 {
|
||||
let pos_of_zero = self
|
||||
.numbers
|
||||
.iter()
|
||||
.position(|&num| num == 0)
|
||||
.expect("Zero must be present in data");
|
||||
let first = (pos_of_zero + 1000) % self.numbers.len();
|
||||
let second = (pos_of_zero + 2000) % self.numbers.len();
|
||||
let third = (pos_of_zero + 3000) % self.numbers.len();
|
||||
self.numbers[first] + self.numbers[second] + self.numbers[third]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Operation {
|
||||
from: usize,
|
||||
to: usize,
|
||||
insert: i64,
|
||||
}
|
||||
|
||||
impl Operation {
|
||||
fn new(insert: i64, from: usize, list_len: usize) -> Self {
|
||||
let to_unbounded = from as i64 + insert;
|
||||
let mut to = to_unbounded.rem_euclid(list_len as i64 - 1);
|
||||
if to == 0 {
|
||||
to = list_len as i64 - 1;
|
||||
}
|
||||
Self {
|
||||
from,
|
||||
to: to as usize,
|
||||
insert,
|
||||
}
|
||||
}
|
||||
|
||||
fn should_rotate_right(&self) -> bool {
|
||||
self.to < self.from
|
||||
}
|
||||
|
||||
fn get_rotation_range(&self) -> RangeInclusive<usize> {
|
||||
self.from.min(self.to)..=self.from.max(self.to)
|
||||
}
|
||||
|
||||
fn index_change(&self) -> usize {
|
||||
if self.to < self.from {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn solve_first_puzzle<R: BufRead>(reader: R) -> i64 {
|
||||
let mut list = List::parse_input::<1, _>(reader);
|
||||
list.apply_rotation();
|
||||
list.sum_of_magic_positions()
|
||||
}
|
||||
|
||||
pub fn solve_second_puzzle<R: BufRead>(reader: R) -> i64 {
|
||||
let mut list = List::parse_input::<811589153, _>(reader);
|
||||
for _ in 0..10 {
|
||||
list.apply_rotation();
|
||||
}
|
||||
list.sum_of_magic_positions()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = ::std::env::args().skip(1);
|
||||
let file = args.next().unwrap_or_else(|| String::from("./input"));
|
||||
let solve = args
|
||||
.next()
|
||||
.map(|arg| match arg.as_str() {
|
||||
"first" => SolvePuzzle::First,
|
||||
"second" => SolvePuzzle::Second,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let file = BufReader::new(File::open(file).expect("Opening file"));
|
||||
match solve {
|
||||
SolvePuzzle::First => println!("{}", solve_first_puzzle(file)),
|
||||
SolvePuzzle::Second => println!("{}", solve_second_puzzle(file)),
|
||||
};
|
||||
}
|
||||
|
||||
impl FromIterator<i64> for List {
|
||||
fn from_iter<T: IntoIterator<Item = i64>>(iter: T) -> Self {
|
||||
let numbers: Vec<i64> = iter.into_iter().collect();
|
||||
let number_positions = (0..numbers.len()).collect();
|
||||
Self {
|
||||
numbers,
|
||||
number_positions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn example_on_first() {
|
||||
let reader = Cursor::new(include_str!("../input.test"));
|
||||
assert_eq!(solve_first_puzzle(reader), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_on_second() {
|
||||
let reader = Cursor::new(include_str!("../input.test"));
|
||||
assert_eq!(solve_second_puzzle(reader), 1623178306);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue