-rw-r--r--src/lib.rs199
1 files changed, 98 insertions, 101 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 787be2b..598246f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -29,122 +29,119 @@
hint_assert_unchecked
)]
mod util;
-pub mod day12 {
+pub mod day13 {
+ use super::util;
use super::util::prelude::*;
-
const SIZE: usize = 140;
+
+ fn two([a, b]: [u8; 2]) -> i64 {
+ (a - b'0') as i64 * 10 + (b - b'0') as i64
+ }
+
#[no_mangle]
pub fn part2(i: &str) -> impl Display {
- fn explore(
- (x, y): (usize, usize),
- handled: &mut [[bool; 140]; 140],
- char: u8,
- get: &mut impl FnMut(usize, usize) -> Option<u8>,
- tot: &mut u32,
- count: &mut u32,
- ) {
- if get(x, y) == Some(char) && handled[y][x] == false {
- handled[y][x] = true;
- // αbβ
- // a.c
- // γdδ
- let α = get(x.wrapping_sub(1), y.wrapping_sub(1)) != Some(char);
- let β = get(x.wrapping_add(1), y.wrapping_sub(1)) != Some(char);
- let γ = get(x.wrapping_sub(1), y.wrapping_add(1)) != Some(char);
- let δ = get(x.wrapping_add(1), y.wrapping_add(1)) != Some(char);
-
- let a = get(x.wrapping_sub(1), y) != Some(char);
- let b = get(x, y.wrapping_sub(1)) != Some(char);
- let c = get(x.wrapping_add(1), y) != Some(char);
- let d = get(x, y.wrapping_add(1)) != Some(char);
- fn u(a: bool) -> u32 {
- a as u32
+ let mut i = i.as_bytes();
+ // let i = i.as_chunks_unchecked::<{ SIZE + 1 }>();
+ // let get = |x, y| (x < SIZE && y < SIZE).then(|| i[y][x]);
+ let mut sum = 0;
+ for _ in 0..340 {
+ let a_x = two(util::nail(C! { &i["button a: x+".len()..]}));
+ let a_y = two(util::nail(C! { &i["button a: x+55, y+".len()..]}));
+ let b_x = two(util::nail(
+ C! { &i["button a: x+55, y+jj\nbutton b: x+".len()..]},
+ ));
+ let b_y = two(util::nail(
+ C! { &i["button a: x+55, y+jj\nbutton b: x+44, y+".len()..]},
+ ));
+ i.skip("button a: x+55, y+jj\nbutton b: x+44, y+jj\nprize: x=".len());
+ let p_x: i64 = reading::until::<i64>(&mut i, b',') + 10000000000000;
+ i.skip(" y=".len());
+ let p_y: i64 = reading::until::<i64>(&mut i, b'\n') + 10000000000000;
+ #[inline]
+ fn dmod(a: i64, b: i64) -> (i64, i64) {
+ unsafe {
+ (
+ core::intrinsics::unchecked_div(a, b),
+ core::intrinsics::unchecked_rem(a, b),
+ )
}
- // *tot += u(a) + u(b) + u(c) + u(d);
-
- *tot += u(a & b) + u(b & c) + u(c & d) + u(a & d);
- *tot += u(!a & !b & α) + u(!b & !c & β) + u(!c & !d & δ) + u(!a & !d & γ);
- *count += 1;
+ }
+ // a_x * α + b_x * β = p_x
+ // a_y * α + b_y * β = p_y
+ let (β, ok) = dmod(
+ a_y * p_x - a_x * p_y, //
+ a_y * b_x - a_x * b_y,
+ );
+ if ok == 0 {
+ let (α, ok) = {
+ dmod(
+ b_y * p_x - b_x * p_y, //
+ a_x * b_y - a_y * b_x,
+ )
+ };
+ if ok == 0 {
+ sum += 3 * α + β;
+ }
+ }
- explore((x.wrapping_sub(1), y), handled, char, get, tot, count);
- explore((x + 1, y), handled, char, get, tot, count);
- explore((x, y + 1), handled, char, get, tot, count);
- explore((x, y.wrapping_sub(1)), handled, char, get, tot, count);
+ if i.is_empty() {
+ break;
}
+ i.skip(1);
}
-
- let grid = unsafe { i.as_bytes().as_chunks_unchecked::<{ SIZE + 1 }>() };
- let handled = &mut [[false; SIZE]; SIZE];
- let mut get = |x: usize, y: usize| {
- unsafe { core::hint::assert_unchecked(grid.len() == SIZE) };
- (x < SIZE && y < SIZE).then(|| grid[y][x])
- };
- (0..SIZE)
- .flat_map(move |y| (0..SIZE).map(move |x| (x, y)))
- .filter_map(|(x, y)| {
- let mut sides = 0;
- let mut area = 0;
- (!handled[y][x]).then(|| {
- let char = C! { grid[y][x]};
- explore((x, y), handled, char, &mut get, &mut sides, &mut area);
- area * sides
- })
- })
- .sum::<u32>()
+ sum
}
+
#[no_mangle]
pub fn part1(i: &str) -> impl Display {
- fn explore(
- (x, y): (usize, usize),
- handled: &mut [[bool; 140]; 140],
- char: u8,
- get: &mut impl FnMut(usize, usize) -> Option<u8>,
- tot: &mut u32,
- count: &mut u32,
- ) {
- if get(x, y) == Some(char) && handled[y][x] == false {
- handled[y][x] = true;
- // αbβ
- // a.c
- // γdδ
- let a = get(x.wrapping_sub(1), y) != Some(char);
- let b = get(x, y.wrapping_sub(1)) != Some(char);
- let c = get(x.wrapping_add(1), y) != Some(char);
- let d = get(x, y.wrapping_add(1)) != Some(char);
- fn u(a: bool) -> u32 {
- a as u32
+ let mut i = i.as_bytes();
+ // let i = i.as_chunks_unchecked::<{ SIZE + 1 }>();
+ // let get = |x, y| (x < SIZE && y < SIZE).then(|| i[y][x]);
+ let mut sum = 0;
+ for _ in 0..340 {
+ let a_x = two(util::nail(C! { &i["button a: x+".len()..]}));
+ let a_y = two(util::nail(C! { &i["button a: x+55, y+".len()..]}));
+ let b_x = two(util::nail(
+ C! { &i["button a: x+55, y+jj\nbutton b: x+".len()..]},
+ ));
+ let b_y = two(util::nail(
+ C! { &i["button a: x+55, y+jj\nbutton b: x+44, y+".len()..]},
+ ));
+ i.skip("button a: x+55, y+jj\nbutton b: x+44, y+jj\nprize: x=".len());
+ let p_x: i64 = reading::until(&mut i, b',');
+ i.skip(" y=".len());
+ let p_y: i64 = reading::until(&mut i, b'\n');
+ #[inline]
+ fn dmod(a: i64, b: i64) -> (i64, i64) {
+ unsafe {
+ (
+ core::intrinsics::unchecked_div(a, b),
+ core::intrinsics::unchecked_rem(a, b),
+ )
}
- *tot += u(a) + u(b) + u(c) + u(d);
-
- // *tot += u(a & b) + u(b & c) + u(c & d) + u(a & d);
- // *tot += u(!a & !b & α) + u(!b & !c & β) + u(!c & !d & δ) + u(!a & !d & γ);
- *count += 1;
+ }
+ // a_x * α + b_x * β = p_x
+ // a_y * α + b_y * β = p_y
+ let (β, ok) = dmod(
+ a_y * p_x - a_x * p_y, //
+ a_y * b_x - a_x * b_y,
+ );
+ if ok == 0 {
+ let α = unsafe {
+ core::intrinsics::unchecked_div(
+ b_y * p_x - b_x * p_y, //
+ a_x * b_y - a_y * b_x,
+ )
+ };
+ sum += 3 * α + β;
+ }
- explore((x.wrapping_sub(1), y), handled, char, get, tot, count);
- explore((x + 1, y), handled, char, get, tot, count);
- explore((x, y + 1), handled, char, get, tot, count);
- explore((x, y.wrapping_sub(1)), handled, char, get, tot, count);
+ if i.is_empty() {
+ break;
}
+ i.skip(1);
}
-
- let grid = unsafe { i.as_bytes().as_chunks_unchecked::<{ SIZE + 1 }>() };
- let handled = &mut [[false; SIZE]; SIZE];
- let mut get = |x: usize, y: usize| {
- unsafe { core::hint::assert_unchecked(grid.len() == SIZE) };
- (x < SIZE && y < SIZE).then(|| grid[y][x])
- };
- (0..SIZE)
- .flat_map(move |y| (0..SIZE).map(move |x| (x, y)))
- .filter_map(|(x, y)| {
- let mut sides = 0;
- let mut area = 0;
- (!handled[y][x]).then(|| {
- let char = C! { grid[y][x]};
- explore((x, y), handled, char, &mut get, &mut sides, &mut area);
- area * sides
- })
- })
- .sum::<u32>()
+ sum
}
}