Compare commits

...

2 Commits

Author SHA1 Message Date
93f574463b Day 20, part 2 2022-12-21 15:41:35 +01:00
63fecbd235 Day 20, part 1 2022-12-21 15:18:35 +01:00
4 changed files with 148 additions and 0 deletions

9
src/bin/d20p1.rs Normal file
View File

@ -0,0 +1,9 @@
use aoc22::{day20, util};
pub fn main() {
let nodes = day20::parse_file(&util::parse_input(), 1);
day20::mix(&nodes);
println!("Sum of coordinates: {}", day20::calc_coordinates(&nodes));
}

16
src/bin/d20p2.rs Normal file
View File

@ -0,0 +1,16 @@
use aoc22::{day20, util};
const KEY: isize = 811589153;
const ROUNDS: usize = 10;
pub fn main() {
let nodes = day20::parse_file(&util::parse_input(), KEY);
// day20::print_nodes(&nodes);
for _ in 0..ROUNDS {
day20::mix(&nodes);
// day20::print_nodes(&nodes);
}
println!("Sum of coordinates: {}", day20::calc_coordinates(&nodes));
}

122
src/day20.rs Normal file
View File

@ -0,0 +1,122 @@
use std::{cell::RefCell, fmt::Debug, ops::Deref, rc::Rc};
pub struct Node {
pub val: isize,
pub next: Option<Rc<RefCell<Node>>>,
pub prev: Option<Rc<RefCell<Node>>>,
}
// Default Debug implementation will loop indefinitely, since we have a ring buffer
impl Debug for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Node")
.field("val", &self.val)
.field("next", &self.next.as_ref().map(|n| n.borrow().val))
.field("prev", &self.prev.as_ref().map(|n| n.borrow().val))
.finish()
}
}
pub fn get_next(node: &Rc<RefCell<Node>>, n: usize) -> Rc<RefCell<Node>> {
let mut curr = node.clone();
for _ in 0..n {
let next = curr.borrow().next.as_ref().unwrap().clone();
curr = next;
}
curr
}
pub fn get_prev(node: &Rc<RefCell<Node>>, n: usize) -> Rc<RefCell<Node>> {
let mut curr = node.clone();
for _ in 0..n {
let prev = curr.borrow().prev.as_ref().unwrap().clone();
curr = prev;
}
curr
}
pub fn parse_file(input: &String, key: isize) -> Vec<Rc<RefCell<Node>>> {
let mut result = Vec::new();
let mut last = None;
for line in input.lines() {
let val: isize = line.parse().unwrap();
let node = Rc::new(RefCell::new(Node {
val: val * key,
next: None,
prev: last.clone(),
}));
if let Some(l) = last {
l.as_ref().borrow_mut().next = Some(node.clone());
}
result.push(node.clone());
last = Some(node);
}
assert!(result.len() > 0);
let last_refcell = last.as_ref().unwrap().deref();
last_refcell.borrow_mut().next = Some(result[0].clone());
let first_refcell = &*result[0];
first_refcell.borrow_mut().prev = Some(last.as_ref().unwrap().clone());
result
}
pub fn mix(nodes: &Vec<Rc<RefCell<Node>>>) {
let div = nodes.len() - 1;
for node in nodes {
let n = node.borrow().val;
if n == 0 || (n > 0 && (n as usize) % div == 0) || (n < 0 && (-n as usize) % div == 0) {
continue;
}
// Remove from current position
let prev = get_prev(node, 1);
let next = get_next(node, 1);
prev.borrow_mut().next = Some(next.clone());
next.borrow_mut().prev = Some(prev.clone());
let prev = if n > 0 {
let n = (n as usize) % div;
assert!(n < div);
get_next(node, n)
} else {
let n = ((-n as usize) % div) + 1;
assert!(n < div);
get_prev(node, n)
};
let next = get_next(&prev, 1);
prev.deref().borrow_mut().next = Some(node.clone());
next.deref().borrow_mut().prev = Some(node.clone());
let mut n_mut = node.deref().borrow_mut();
n_mut.prev = Some(prev.clone());
n_mut.next = Some(next.clone());
drop(n_mut);
}
}
pub fn print_nodes(nodes: &Vec<Rc<RefCell<Node>>>) {
let mut curr = nodes.iter().find(|n| n.borrow().val == 0).unwrap().clone();
loop {
print!("{}, ", curr.borrow().val);
let next = curr.borrow().next.as_ref().unwrap().clone();
curr = next;
if curr.borrow().val == 0 {
break;
}
}
print!("\n");
}
pub fn calc_coordinates(nodes: &Vec<Rc<RefCell<Node>>>) -> isize {
let zero = nodes.iter().find(|n| n.borrow().val == 0).unwrap();
let first = get_next(zero, 1000).borrow().val;
let second = get_next(zero, 2000).borrow().val;
let third = get_next(zero, 3000).borrow().val;
first + second + third
}

View File

@ -10,6 +10,7 @@ pub mod day17;
pub mod day18;
pub mod day19;
pub mod day2;
pub mod day20;
pub mod day3;
pub mod day4;
pub mod day5;