heh
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 195 |
1 files changed, 137 insertions, 58 deletions
diff --git a/src/main.rs b/src/main.rs index 778a54d..39f14a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,79 +33,158 @@ )] extern crate test; pub mod util; +use atools::CollectArray; use std::cmp::Reverse; pub use util::prelude::*; const SIZE: usize = 141; +fn exec(program: &[u8], [mut a, mut b, mut c]: [u128; 3]) -> Vec<u8> { + let mut pointer = 0; + let mut out = vec![]; + while let Some(opcode) = program.get(pointer) { + let operand = program[pointer + 1]; + let combo = || match operand { + 0..=3 => operand as u128, + 4 => a, + 5 => b, + 6 => c, + _ => panic!(), + }; + match opcode { + 0 => { + a = a / (2u128.pow(combo() as u32)); + pointer += 2; + } + 1 => { + b ^= operand as u128; + pointer += 2; + } + 2 => { + b = combo() & 7; + pointer += 2; + } + 3 => { + if a == 0 { + pointer += 2; + } else { + pointer = operand.into(); + } + } + 4 => { + b ^= c; + pointer += 2; + } + 5 => { + out.push((combo() & 7) as u8); + pointer += 2; + } + 6 => { + b = a / (1 << combo() as u32); + pointer += 2; + } + 7 => { + c = a / (1 << combo() as u32); + pointer += 2; + } + _ => unreachable!(), + } + // println!("{a} {b} {c}"); + } + out +} + #[no_mangle] pub unsafe fn run(i: &str) -> impl Display { let i = i.as_bytes(); - let j = memchr::memchr(b'S', i).ψ(); - let (x, y) = (j % (SIZE + 1), j / (SIZE + 1)); - let grid = i.to_vec().leak().as_chunks_unchecked_mut::<{ SIZE + 1 }>(); - grid[y][x] = b'.'; - // let mut q = std::collections::BinaryHeap::with_capacity(1 << 10); - // let mut s = HashSet::with_capacity_and_hasher(1 << 16, rustc_hash::FxBuildHasher::default()); - // q.push(Reverse((0u64, ((x, y), Dir::E)))); - // while let Some(Reverse((c, n @ ((x, y), dir)))) = q.pop() { - // if grid[y][x] == b'E' { - // return c; - // } - // if !s.insert(n) { - // continue; - // } - // for (n, d) in [ - // ((dir + n.0, dir), 1), - // ((n.0, dir.turn_90()), 1000), - // ((n.0, dir.turn_90ccw()), 1000), - // ] - // .into_iter() - // .filter(|(((x, y), ..), _)| grid[*y][*x] != b'#') - // { - // if s.contains(&n) { - // continue; - // } - // q.push(Reverse((c + d, n))); - // } - // } - - let (path, _) = pathfinding::directed::astar::astar_bag( - &((x, y), Dir::E), - |&(p, dir)| { - let dir: Dir = dir; - [ - ((dir + p, dir), 1), - ((p, dir.turn_90()), 1000u64), - ((p, dir.turn_90ccw()), 1000u64), - ] - .into_iter() - .filter(|(((x, y), ..), _)| grid[*y][*x] != b'#') - }, - |_| 0, - |((x, y), ..)| grid[*y][*x] == b'E', - ) - .unwrap(); - path.into_iter() - .flat_map(|x| x.into_iter().map(|((x, y), _)| (x, y))) - .collect::<HashSet<_>>() - .len() + let mut i = i.行(); + let regi = i + .by_ref() + .take_while(|x| !x.is_empty()) + .map(|x| x.μ1(':').trim_ascii_start().λ::<u128>()) + .carr(); + let program = i + .nth(1) + .ψ() + .μ1(':') + .trim_ascii_start() + .split(|x| *x == b',') + .map(|x| x.λ::<u8>()) + .collect_vec(); + exec(&program, regi).into_iter().join(",") } fn main() { - // (1..u32::MAX as u64).for_each(|a| assert_eq!(a.ilog10() + 1, digs(a))); - // let mut s = String::new(); - // for i in 0..1280 { let i = include_str!("inp.txt"); - // s.push_str(i);i - // }w - // std::fs::write("src/inp.txt", s); - #[allow(unused_unsafe)] - println!("{}", unsafe { run(i) }); + let mut i = i.行(); + let regi: [u128; 3] = i + .by_ref() + .take_while(|x| !x.is_empty()) + .map(|x| x.μ1(':').trim_ascii_start().λ::<u128>()) + .carr(); + let program = i + .nth(1) + .ψ() + .μ1(':') + .trim_ascii_start() + .split(|x| *x == b',') + .map(|x| x.λ::<u8>()) + .collect_vec(); + println!( + r#" +from z3 import * +solver = Optimize() +s = BitVec("s", 64) +a = s +b, c = (0, 0)"# + ); + println!("for x in {program:?}:"); + for &[opcode, operand] in program.array_chunks::<2>() { + let combo = || match operand { + 0..=3 => format!("{operand}"), + 4 => "a".to_string(), + 5 => "b".to_string(), + 6 => "c".to_string(), + _ => panic!(), + }; + match opcode { + 0 => println!(" a >>= {}", combo()), + 1 => println!(" b ^= {operand}"), + 2 => println!(" b = {} & 7", combo()), + 3 => {} // println!(" a == 0 ? {operand}"), + 4 => println!(" b ^= c"), + 5 => println!(" solver.add({} % 8 == x)", combo()), + 6 => println!(" b = a >> {}", combo()), + 7 => println!(" c = a >> {}", combo()), + _ => unreachable!(), + } + } + println!( + r#" +solver.add(a == 0) +solver.minimize(s) +assert str(solver.check()) == "sat" +print(solver.model().eval(s))"# + ); + assert_eq!( + exec(&[0, 1, 5, 4, 3, 0], [729, 0, 0]), + [4, 6, 3, 5, 6, 3, 5, 2, 1, 0] + ); + assert_eq!(exec(&[5, 0, 5, 1, 5, 4], [10, 0, 0]), [0, 1, 2]); + assert_eq!( + exec(&[0, 1, 5, 4, 3, 0], [2024, 0, 0],), + [4, 2, 5, 6, 7, 7, 7, 7, 3, 1, 0] + ); + // dbg!(exec(&program, regi)); } #[bench] fn bench(b: &mut test::Bencher) { let i = boxd(include_str!("inp.txt")); - b.iter(|| unsafe { p2(i) }); + b.iter(|| unsafe { + exec( + boxd(&[2, 4, 1, 7, 7, 5, 0, 3, 1, 7, 4, 1, 5, 5, 3, 0]), + [64012472, 0, 0], + ) + }); } |