added day 17/18
This commit is contained in:
parent
527b156882
commit
1e2bf54958
|
@ -4,6 +4,9 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "main"
|
default-run = "main"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fxhash = "0.2.1"
|
fxhash = "0.2.1"
|
||||||
rayon = "1.10.0"
|
rayon = "1.10.0"
|
||||||
|
|
|
@ -267,7 +267,6 @@ impl Bitmap {
|
||||||
self.inner[index] &= !(1 << bit_offset);
|
self.inner[index] &= !(1 << bit_offset);
|
||||||
self.left_bracket[index] &= !(1 << bit_offset);
|
self.left_bracket[index] &= !(1 << bit_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
125
src/day17/1.rs
Normal file
125
src/day17/1.rs
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
|
||||||
|
#![feature(test)]
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
const INPUTS: [&str; 7] = [
|
||||||
|
"Register A: 0
|
||||||
|
Register B: 0
|
||||||
|
Register C: 9
|
||||||
|
|
||||||
|
Program: 2,6",
|
||||||
|
"Register A: 10
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 5,0,5,1,5,4",
|
||||||
|
|
||||||
|
"Register A: 729
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 0,1,5,4,3,0",
|
||||||
|
|
||||||
|
|
||||||
|
"Register A: 2024
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 0,1,5,4,3,0",
|
||||||
|
|
||||||
|
"Register A: 0
|
||||||
|
Register B: 29
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 1,7",
|
||||||
|
|
||||||
|
|
||||||
|
"Register A: 0
|
||||||
|
Register B: 2024
|
||||||
|
Register C: 43690
|
||||||
|
|
||||||
|
Program: 4,0",
|
||||||
|
|
||||||
|
include_str!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn run(input: &str) -> String {
|
||||||
|
let (p, q) = input.split_once("\n\n").unwrap();
|
||||||
|
let (_, q) = q.split_once(' ').unwrap();
|
||||||
|
let program = q.trim().split(',').map(|x| x.parse::<u32>().unwrap()).collect::<Vec<u32>>();
|
||||||
|
|
||||||
|
let mut p = p.lines();
|
||||||
|
let mut a = p.next().unwrap().chars().filter(|x| x.is_digit(10)).collect::<String>().parse::<u32>().unwrap();
|
||||||
|
let mut b = p.next().unwrap().chars().filter(|x| x.is_digit(10)).collect::<String>().parse::<u32>().unwrap();
|
||||||
|
let mut c = p.next().unwrap().chars().filter(|x| x.is_digit(10)).collect::<String>().parse::<u32>().unwrap();
|
||||||
|
|
||||||
|
let mut out = vec![];
|
||||||
|
let mut ip = 0;
|
||||||
|
|
||||||
|
while ip < program.len() {
|
||||||
|
let opcode = program[ip];
|
||||||
|
let operand = program[ip+1];
|
||||||
|
ip += 2;
|
||||||
|
|
||||||
|
let combo = |op: u32| {
|
||||||
|
match op {
|
||||||
|
0..=3 => op,
|
||||||
|
4 => a,
|
||||||
|
5 => b,
|
||||||
|
6 => c,
|
||||||
|
7 => unreachable!(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match opcode {
|
||||||
|
0 => {
|
||||||
|
let denom = 2u32.pow(combo(operand));
|
||||||
|
a /= denom;
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
b ^= operand;
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
b = combo(operand) % 8;
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
if a != 0 {
|
||||||
|
ip = operand as usize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 => {
|
||||||
|
b = b ^ c;
|
||||||
|
}
|
||||||
|
5 => {
|
||||||
|
out.push(combo(operand)%8);
|
||||||
|
}
|
||||||
|
6 => {
|
||||||
|
let denom = 2u32.pow(combo(operand));
|
||||||
|
b = a / denom;
|
||||||
|
}
|
||||||
|
7 => {
|
||||||
|
let denom = 2u32.pow(combo(operand));
|
||||||
|
c = a / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.into_iter().map(|x| x.to_string()).collect::<Vec<String>>().join(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
println!("answer = {}", run(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn part1(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let v = run(INPUTS[6]);
|
||||||
|
test::black_box(v);
|
||||||
|
});
|
||||||
|
}
|
131
src/day17/2.rs
Normal file
131
src/day17/2.rs
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
|
||||||
|
#![feature(test)]
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
const INPUTS: [&str; 1] = [
|
||||||
|
include_str!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn run(input: &str) -> u64 {
|
||||||
|
let (_, q) = input.split_once("\n\n").unwrap();
|
||||||
|
let (_, q) = q.split_once(' ').unwrap();
|
||||||
|
let program = q.trim().split(',').map(|x| x.parse::<u64>().unwrap()).collect::<Vec<u64>>();
|
||||||
|
|
||||||
|
let mut a;
|
||||||
|
let b = 0;
|
||||||
|
let c = 0;
|
||||||
|
let mut out = Vec::new();
|
||||||
|
// Digits in program change in multiples of 8 so [1, 8, 64, 512, ...].
|
||||||
|
// instead of checking every value of a, check the values where all digits will change
|
||||||
|
let mut factors = vec![0; program.len()];
|
||||||
|
loop {
|
||||||
|
a = 0;
|
||||||
|
for (i, f) in factors.iter().enumerate() {
|
||||||
|
a += 8u64.pow(i as u32) * f;
|
||||||
|
}
|
||||||
|
|
||||||
|
test(a, b, c, &mut out);
|
||||||
|
// general_eval(a, b, c, &program, &mut out);
|
||||||
|
if out == program {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in (0..program.len()).rev() {
|
||||||
|
if out.len() < i {
|
||||||
|
factors[i] += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if out[i] != program[i] {
|
||||||
|
factors[i] += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2,4,1,4,7,5,4,1,1,4,5,5,0,3,3,0
|
||||||
|
fn test(mut a: u64, mut b: u64, mut c: u64, out: &mut Vec<u64>) {
|
||||||
|
while a != 0 {
|
||||||
|
b = a % 8;
|
||||||
|
b ^= 4;
|
||||||
|
c = a / (1 << b);
|
||||||
|
b ^= c;
|
||||||
|
b ^= 4;
|
||||||
|
out.push(b%8);
|
||||||
|
a = a / (1 << 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
fn general_eval(mut a: u64, mut b: u64, mut c: u64, input: &[u64], out: &mut Vec<u64>) {
|
||||||
|
let mut ip = 0;
|
||||||
|
|
||||||
|
while ip < input.len() {
|
||||||
|
let opcode = input[ip];
|
||||||
|
let operand = input[ip+1];
|
||||||
|
ip += 2;
|
||||||
|
|
||||||
|
|
||||||
|
let combo = |op: u64| {
|
||||||
|
match op {
|
||||||
|
0..=3 => op,
|
||||||
|
4 => a,
|
||||||
|
5 => b,
|
||||||
|
6 => c,
|
||||||
|
7 => unreachable!(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match opcode {
|
||||||
|
0 => {
|
||||||
|
let denom = 2u64.pow(combo(operand) as u32);
|
||||||
|
a /= denom;
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
b ^= operand;
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
b = combo(operand) % 8;
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
if a != 0 {
|
||||||
|
ip = operand as usize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 => {
|
||||||
|
b = b ^ c;
|
||||||
|
}
|
||||||
|
5 => {
|
||||||
|
out.push(combo(operand)%8);
|
||||||
|
}
|
||||||
|
6 => {
|
||||||
|
let denom = 2u64.pow(combo(operand) as u32);
|
||||||
|
b = a / denom;
|
||||||
|
}
|
||||||
|
7 => {
|
||||||
|
let denom = 2u64.pow(combo(operand) as u32);
|
||||||
|
c = a / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
println!("answer = {}", run(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn part1(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let v = run(INPUTS[0]);
|
||||||
|
test::black_box(v);
|
||||||
|
});
|
||||||
|
}
|
114
src/day18/1.rs
Normal file
114
src/day18/1.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
#![feature(slice_split_once)]
|
||||||
|
#![feature(test)]
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
const INPUTS: [&str; 1] = [
|
||||||
|
include_str!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn run(input: &str) -> i64 {
|
||||||
|
let input = input.as_bytes();
|
||||||
|
let parse = |x: &[u8]| {
|
||||||
|
(match x.len() {
|
||||||
|
1 => x[0] - b'0',
|
||||||
|
2 => (x[0] - b'0') * 10 + x[1] - b'0',
|
||||||
|
_ => 0
|
||||||
|
}) as i64
|
||||||
|
};
|
||||||
|
let mut visited = Bitmap::new();
|
||||||
|
let mut obstacles = Bitmap::new();
|
||||||
|
|
||||||
|
input.split(|&x| x == b'\n').take(1024).for_each(|x| {
|
||||||
|
let (a,b) = x.split_once(|&x| x == b',').unwrap();
|
||||||
|
let a = parse(a);
|
||||||
|
let b = parse(b);
|
||||||
|
|
||||||
|
obstacles.set(a,b);
|
||||||
|
});
|
||||||
|
|
||||||
|
let best = bfs(&obstacles, &mut visited, (0,0), (70,70));
|
||||||
|
|
||||||
|
best
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bfs(obstacles: &Bitmap, visited: &mut Bitmap, (x,y): (i64, i64), (ex, ey): (i64, i64)) -> i64 {
|
||||||
|
let mut q = VecDeque::new();
|
||||||
|
|
||||||
|
q.push_back((x,y,0));
|
||||||
|
|
||||||
|
while let Some((x,y,steps)) = q.pop_front() {
|
||||||
|
if x == ex && y == ey {
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
if visited.get(x,y) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visited.set(x,y);
|
||||||
|
|
||||||
|
for (i,j) in [(0,1), (1,0), (0,-1), (-1,0)].iter() {
|
||||||
|
let x = i + x;
|
||||||
|
let y = j + y;
|
||||||
|
|
||||||
|
if x < 0 || y < 0 || x > ex || y > ey {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if obstacles.get(x,y) || visited.get(x,y) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
q.push_back((x,y,steps+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
|
const WORD_SIZE: usize = 64;
|
||||||
|
|
||||||
|
struct Bitmap {
|
||||||
|
inner: [u64; (71 * 71) / WORD_SIZE + 1],
|
||||||
|
size: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bitmap {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self { inner: [0; (71 * 71) / WORD_SIZE + 1], size: 71 }
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn get(&self, x: i64, y: i64) -> bool {
|
||||||
|
let offset = (x * self.size + y) as usize;
|
||||||
|
let index = offset / WORD_SIZE;
|
||||||
|
let bit_offset = offset % WORD_SIZE;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(*self.inner.as_ptr().add(index) >> bit_offset & 1) == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&mut self, x: i64, y: i64) {
|
||||||
|
let offset = (x * self.size + y) as usize;
|
||||||
|
let index = offset / WORD_SIZE;
|
||||||
|
let bit_offset = offset % WORD_SIZE;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*self.inner.get_unchecked_mut(index) |= 1 << bit_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
println!("answer = {:?}", run(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn part1(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let v = run(INPUTS[0]);
|
||||||
|
test::black_box(v);
|
||||||
|
});
|
||||||
|
}
|
135
src/day18/2.rs
Normal file
135
src/day18/2.rs
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
#![feature(slice_split_once)]
|
||||||
|
#![feature(test)]
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
const INPUTS: [&str; 1] = [
|
||||||
|
include_str!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn run(input: &str) -> (i64, i64) {
|
||||||
|
let input = input.as_bytes();
|
||||||
|
let parse = |x: &[u8]| {
|
||||||
|
(match x.len() {
|
||||||
|
1 => x[0] - b'0',
|
||||||
|
2 => (x[0] - b'0') * 10 + x[1] - b'0',
|
||||||
|
_ => 0
|
||||||
|
}) as i64
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes = input.split(|&x| x == b'\n').filter(|x| !x.is_empty()).map(|x| {
|
||||||
|
let (a,b) = x.split_once(|&x| x == b',').unwrap();
|
||||||
|
let a = parse(a);
|
||||||
|
let b = parse(b);
|
||||||
|
|
||||||
|
(a,b)
|
||||||
|
}).collect::<Vec<(i64, i64)>>();
|
||||||
|
|
||||||
|
let mut visited = Bitmap::new();
|
||||||
|
let mut obstacles = Bitmap::new();
|
||||||
|
|
||||||
|
let mut l = 0;
|
||||||
|
let mut r = bytes.len()-1;
|
||||||
|
|
||||||
|
while l <= r {
|
||||||
|
let mid = (l + r) / 2;
|
||||||
|
|
||||||
|
for b in bytes[0..mid].iter() {
|
||||||
|
obstacles.set(b.0, b.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if dfs(&obstacles, &mut visited, (0,0), (70,70)) {
|
||||||
|
l = mid + 1;
|
||||||
|
} else {
|
||||||
|
r = mid - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
obstacles.clear();
|
||||||
|
visited.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes[r]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dfs(obstacles: &Bitmap, visited: &mut Bitmap, (x,y): (i64, i64), (ex, ey): (i64, i64)) -> bool {
|
||||||
|
let mut stack = vec![];
|
||||||
|
|
||||||
|
stack.push((x,y));
|
||||||
|
|
||||||
|
while let Some((x,y)) = stack.pop() {
|
||||||
|
if x == ex && y == ey {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if visited.get(x,y) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visited.set(x,y);
|
||||||
|
|
||||||
|
for (i,j) in [(0,1), (1,0), (0,-1), (-1,0)].iter() {
|
||||||
|
let x = i + x;
|
||||||
|
let y = j + y;
|
||||||
|
|
||||||
|
if x < 0 || y < 0 || x > ex || y > ex {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if obstacles.get(x,y) || visited.get(x,y) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.push((x,y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
const WORD_SIZE: usize = 64;
|
||||||
|
|
||||||
|
struct Bitmap {
|
||||||
|
inner: [u64; (71 * 71) / WORD_SIZE + 1],
|
||||||
|
size: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bitmap {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self { inner: [0; (71 * 71) / WORD_SIZE + 1], size: 71 }
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn get(&self, x: i64, y: i64) -> bool {
|
||||||
|
let offset = (x * self.size + y) as usize;
|
||||||
|
let index = offset / WORD_SIZE;
|
||||||
|
let bit_offset = offset % WORD_SIZE;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(*self.inner.as_ptr().add(index) >> bit_offset & 1) == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&mut self, x: i64, y: i64) {
|
||||||
|
let offset = (x * self.size + y) as usize;
|
||||||
|
let index = offset / WORD_SIZE;
|
||||||
|
let bit_offset = offset % WORD_SIZE;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*self.inner.get_unchecked_mut(index) |= 1 << bit_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self) {
|
||||||
|
self.inner.fill(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
println!("answer = {:?}", run(input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn part2(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let v = run(INPUTS[0]);
|
||||||
|
test::black_box(v);
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user