heh
-rw-r--r--src/main.rs126
-rw-r--r--src/util.rs96
2 files changed, 85 insertions, 137 deletions
diff --git a/src/main.rs b/src/main.rs
index bfa424a..2ba9db6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -69,122 +69,22 @@ pub use util::prelude::*;
#[allow(warnings)]
type u32x3 = Simd<u32, 3>;
-
-impl Debug for Item {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{} {:?}", self.name.get(), self.kind)
- }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
-
-struct Item {
- name: identifier,
- kind: ItemK,
-}
-#[derive(Clone, Copy, Debug)]
-#[repr(u8)]
-enum identifier {
- u1,
- u2,
- u3,
- u4,
- u5,
- u6,
- u7,
- u8,
- u9,
-}
-impl identifier {
- fn get(self) -> u8 {
- self as u8
- }
-}
-impl PartialEq for identifier {
- fn eq(&self, other: &Self) -> bool {
- self.get() == other.get()
- }
-}
-impl Eq for identifier {}
-impl PartialOrd for identifier {
- fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
- self.get().partial_cmp(&other.get())
- }
-}
-impl Ord for identifier {
- fn cmp(&self, other: &Self) -> std::cmp::Ordering {
- self.get().cmp(&other.get())
- }
-}
-impl Hash for identifier {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- self.get().hash(state)
- }
-}
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-enum ItemK {
- Chip,
- Gen,
-}
-use ItemK::*;
#[unsafe(no_mangle)]
#[implicit_fn::implicit_fn]
pub unsafe fn p1(x: &'static [u8; ISIZE]) -> impl Debug {
- let re = Regex::new(r"([0-9a-z]+) generator").unwrap();
- let rechip = Regex::new(r"([0-9a-z]+)-compatible microchip").unwrap();
- let mut floors = vec![vec![]; 4];
- x.行().zip(&mut floors).for_each(|(x, to)| {
- to.extend(re.captures_iter(x).map(|x| Item {
- name: transmute(x.get(1).unwrap().as_bytes()[0] - b'0'),
- kind: Gen,
- }));
- to.extend(rechip.captures_iter(x).map(|x| Item {
- name: transmute(x.get(1).unwrap().as_bytes()[0] - b'0'),
- kind: Chip,
- }));
- });
- // if a chip is ever left in the same area as another RTG, and it's not connected to its own RTG, the chip will be fried.
- fn not_fried(floor: impl Iterator<Item = Item> + Clone) -> bool {
- floor.clone().all(_.kind == Chip)
- || floor
- .clone()
- .filter(_.kind == Chip) // every chip
- .all(|x| floor.clone().filter(_.kind == Gen).any(_.name == x.name)) // is connected
- };
-
- util::steps_astar(
- (0, floors),
- |(e, floor)| {
- [(e < 3).then(|| e + 1), (e > 0).then(|| e - 1)]
- .into_iter()
- .flatten()
- .flat_map(move |v| {
- floor[e]
- .clone()
- .into_iter()
- .ι()
- .tuple_combinations()
- .map(|(a, b)| vec![a, b])
- .chain(floor[e].clone().into_iter().ι().map(|a| vec![a]))
- .map({
- let floor = floor.clone();
- move |mut x| {
- let mut floor = floor.clone();
- floor[v].extend(x.iter().map(|x| x.0));
- x.sort_by_key(|x| x.1);
- x.iter().rev().map(|(_, i)| floor[e].swap_remove(*i)).θ();
- floor[v].sort();
- floor[e].sort();
- (v, floor)
- }
- })
- })
- .filter(|(e, floor)| not_fried(floor[*e].iter().copied()))
- .map(|n| (n, 1))
- },
- |x| -(x.1[3].len() as i16),
- |(_, f)| f[0..3].iter().all(_.is_empty()),
- )
+ let mut store = Vec::with_capacity(1024);
+ store.push(1);
+ (1..)
+ .map(|x| {
+ util::nb(spiral::coordinate_of(x))
+ .map(spiral::index_at)
+ .iter()
+ .flat_map(|x| store.get(*x as usize))
+ .sum::<u32>()
+ .and(|&x| store.push(x))
+ })
+ .find(|x| *x > 325489)
+ // util::manhattan((-285, -267), (0, 0))
}
const ISIZE: usize = include_bytes!("inp.txt").len();
fn main() {
diff --git a/src/util.rs b/src/util.rs
index 0afefa4..3795648 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -21,12 +21,12 @@ use std::{
pub mod prelude {
pub use super::{
- BoolTools, DigiCount, Dir, FilterBy, FilterBy3, GreekTools, GridFind, IntoCombinations,
- IntoLines, IterͶ, MapWith, NumTupleIterTools, ParseIter, PartitionByKey, Printable, Skip,
- SplitU8, Str, TakeLine, TupleIterTools2, TupleIterTools2R, TupleIterTools3, TupleUtils,
- TwoWayMapCollect, UnifiedTupleUtils, UnsoundUtilities, Widen, countmap, even, gcd, gt,
- infinite_successors, l, lcm, lt, nail, pa, r, rand, reading, reading::Ext, sort, twice, Ͷ,
- Α, Ι, Κ, Λ, Μ,
+ AndF, BoolTools, DigiCount, Dir, FilterBy, FilterBy3, GreekTools, GridFind,
+ IntoCombinations, IntoLines, IterͶ, MapWith, NumTupleIterTools, ParseIter, PartitionByKey,
+ Printable, Skip, SplitU8, Str, TakeLine, TupleIterTools2, TupleIterTools2R,
+ TupleIterTools3, TupleUtils, TwoWayMapCollect, UnifiedTupleUtils, UnsoundUtilities, Widen,
+ countmap, even, gcd, gt, infinite_successors, l, lcm, lt, nail, pa, r, rand, reading,
+ reading::Ext, sort, spiral, twice, Ͷ, Α, Ι, Κ, Λ, Μ,
};
#[allow(unused_imports)]
pub(crate) use super::{C, bits, dang, leek, mat, shucks};
@@ -1383,7 +1383,7 @@ pub mod reading {
s = T::default();
}
b => {
- s = s * T::ten() + T::from(b - b'0');
+ s = s * T::TEN + T::from(b - b'0');
}
}
}
@@ -1391,14 +1391,14 @@ pub mod reading {
n + 1
}
pub trait Ten {
- fn ten() -> Self;
+ const TEN: Self;
+ const ONE: Self;
}
macro_rules! tenz {
($for:ty) => {
impl Ten for $for {
- fn ten() -> $for {
- 10
- }
+ const TEN: Self = 10;
+ const ONE: Self = 1;
}
};
}
@@ -1464,7 +1464,7 @@ pub mod reading {
if x == until {
return n;
}
- n = n * T::ten() + T::from(x - b'0')
+ n = n * T::TEN + T::from(x - b'0')
}
}
@@ -1492,7 +1492,7 @@ pub mod reading {
if byte == until {
return n;
}
- n = n * T::ten() + T::from(byte - b'0');
+ n = n * T::TEN + T::from(byte - b'0');
}
}
@@ -1504,7 +1504,7 @@ pub mod reading {
) -> T {
let mut n = T::default();
for &byte in x {
- n = n * T::ten() + T::from(byte - b'0');
+ n = n * T::TEN + T::from(byte - b'0');
}
n
}
@@ -1913,18 +1913,22 @@ pub fn ints(x: &'static [u8]) -> impl Iterator<Item = i64> {
static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new("-?[0-9]+").unwrap());
RE.find_iter(x.str()).map(|x| x.as_str().λ())
}
-#[lower::apply(wrapping)]
-pub fn nb(x: usize, y: usize) -> [(usize, usize); 8] {
+
+pub fn nb<
+ T: Default + std::ops::Sub<T, Output = T> + std::ops::Add<T, Output = T> + Copy + reading::Ten,
+>(
+ (x, y): (T, T),
+) -> [(T, T); 8] {
[
- (x - 1, y - 1),
- (x, y - 1),
- (x + 1, y - 1),
- (x - 1, y),
+ (x - T::ONE, y - T::ONE),
+ (x, y - T::ONE),
+ (x + T::ONE, y - T::ONE),
+ (x - T::ONE, y),
// this
- (x + 1, y),
- (x - 1, y + 1),
- (x, y + 1),
- (x + 1, y + 1),
+ (x + T::ONE, y),
+ (x - T::ONE, y + T::ONE),
+ (x, y + T::ONE),
+ (x + T::ONE, y + T::ONE),
]
}
pub fn twice<T: Copy>(x: T) -> impl Iterator<Item = T> + Clone + ExactSizeIterator {
@@ -2030,3 +2034,47 @@ impl<K: Eq + Hash + Clone, V: Clone, I: Iterator<Item = ((K, K), V)>> TwoWayMapC
m
}
}
+
+/// for spiral such as
+/// 9 10 11 12
+/// 8 1 2 13
+/// 7 0 3 14
+/// 6 5 4 15
+pub mod spiral {
+ // https://www.desmos.com/calculator/qpn25p39v9
+ pub fn coordinate_of(n: u64) -> (i64, i64) {
+ let m = n.isqrt() as i64;
+
+ (
+ (-1i64).pow(m as u32 + 1)
+ * (((n as i64 - m * (m + 1)) // _
+ * (((2.0 * (n as f64).sqrt()).floor() as i64 + 1) % 2))
+ + (m + 1) / 2),
+ (-1i64).pow(m as u32)
+ * ((n as i64 - m * (m + 1)) // _
+ * ((2.0 * (n as f64).sqrt()).floor() as i64 % 2)
+ - (m + 1) / 2),
+ )
+ }
+
+ //https://math.stackexchange.com/a/1860731
+ pub fn index_at((x, y): (i64, i64)) -> i64 {
+ let s = if x.abs() >= y.abs() { x } else { -y };
+
+ if s >= 0 {
+ 4 * s * s - x + -y
+ } else {
+ 4 * s * s + (-1_i64).pow((s == x) as u32) * (2 * s + x + -y)
+ }
+ }
+}
+
+pub trait AndF {
+ fn and<T>(self, f: impl FnMut(&Self) -> T) -> Self;
+}
+impl<T> AndF for T {
+ fn and<U>(self, mut f: impl FnMut(&Self) -> U) -> Self {
+ f(&self);
+ self
+ }
+}