Skip to content

Commit 9366572

Browse files
committed
2018 day 19
1 parent 23b69d3 commit 9366572

File tree

5 files changed

+321
-8
lines changed

5 files changed

+321
-8
lines changed

crates/utils/src/enum.rs

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@
77
/// - `ALL`: All variants (reference to a static array).
88
/// - `iter()`: [`Iterator`] over all variants.
99
///
10-
/// Helpers for converting to and from the discriminant:
10+
/// Helpers for converting to and from the discriminant (requires the enum to have an explicit
11+
/// `#[repr(...)]` attribute before all other attributes):
1112
/// - `checked_from_discriminant()` & `from_discriminant()`: Safe and panicking conversions from
1213
/// the discriminant.
1314
/// - [`From`] implementation from the enum to the discriminant.
1415
/// - [`TryFrom`] implementation from the discriminant to the enum.
1516
///
16-
/// The discriminant utilities are only generated if the enum has an explicit `#[repr(...)]`
17-
/// attribute before all other attributes.
17+
/// Helpers for using variants as array indices (requires all variants to use implicit
18+
/// discriminants):
19+
/// - [`Index`](std::ops::Index) and [`IndexMut`](std::ops::IndexMut) implementations for
20+
/// `[T; COUNT]` arrays.
1821
///
1922
/// See also [`parser::parsable_enum!`](crate::parser::parsable_enum), which combined this macro
2023
/// with building a parser.
@@ -94,6 +97,26 @@
9497
///
9598
/// Operation::from_discriminant(64);
9699
/// ```
100+
///
101+
/// Index helpers:
102+
/// ```
103+
/// utils::enumerable_enum! {
104+
/// enum Register {
105+
/// A,
106+
/// B,
107+
/// C,
108+
/// D,
109+
/// }
110+
/// }
111+
///
112+
/// let mut registers = [0, 1, 2, 3];
113+
/// assert_eq!(registers[Register::A], 0);
114+
/// assert_eq!(registers[Register::B], 1);
115+
/// assert_eq!(registers[Register::C], 2);
116+
/// assert_eq!(registers[Register::D], 3);
117+
/// registers[Register::C] = 123;
118+
/// assert_eq!(registers[Register::C], 123);
119+
/// ```
97120
#[macro_export]
98121
macro_rules! enumerable_enum {
99122
(
@@ -158,9 +181,11 @@ macro_rules! enumerable_enum {
158181
$($(#[$variant_meta:meta])* $variant:ident $(= $discriminant:expr)?),+ $(,)?
159182
}
160183
) => {
161-
$(#[$meta])*
162-
$vis enum $name {
163-
$($(#[$variant_meta])* $variant $(= $discriminant)?,)+
184+
$crate::enumerable_enum! {@enum
185+
$(#[$meta])*
186+
$vis enum $name {
187+
$($(#[$variant_meta])* $variant $(= $discriminant)?,)+
188+
}
164189
}
165190

166191
impl $name {
@@ -176,5 +201,42 @@ macro_rules! enumerable_enum {
176201
[$(Self::$variant),+].into_iter()
177202
}
178203
}
179-
}
204+
};
205+
(@enum
206+
$(#[$meta:meta])*
207+
$vis:vis enum $name:ident {
208+
$($(#[$variant_meta:meta])* $variant:ident),+ $(,)?
209+
}
210+
) => {
211+
$(#[$meta])*
212+
$vis enum $name {
213+
$($(#[$variant_meta])* $variant,)+
214+
}
215+
216+
impl<T> ::std::ops::Index<$name> for [T; $name::COUNT] {
217+
type Output = T;
218+
219+
#[inline]
220+
fn index(&self, index: $name) -> &Self::Output {
221+
&self[index as usize]
222+
}
223+
}
224+
impl<T> ::std::ops::IndexMut<$name> for [T; $name::COUNT] {
225+
#[inline]
226+
fn index_mut(&mut self, index: $name) -> &mut Self::Output {
227+
&mut self[index as usize]
228+
}
229+
}
230+
};
231+
(@enum
232+
$(#[$meta:meta])*
233+
$vis:vis enum $name:ident {
234+
$($(#[$variant_meta:meta])* $variant:ident $(= $discriminant:expr)?),+ $(,)?
235+
}
236+
) => {
237+
$(#[$meta])*
238+
$vis enum $name {
239+
$($(#[$variant_meta])* $variant $(= $discriminant)?,)+
240+
}
241+
};
180242
}

crates/utils/src/number.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ number_impl! {float => f32, f64}
248248
/// assert_eq!(is_prime(123u32), false);
249249
/// ```
250250
#[inline]
251+
#[must_use]
251252
pub fn is_prime<T: UnsignedInteger>(n: T) -> bool {
252253
if n <= T::ONE {
253254
return false;
@@ -277,6 +278,54 @@ pub fn is_prime<T: UnsignedInteger>(n: T) -> bool {
277278
true
278279
}
279280

281+
/// Computes the sum of the divisors for unsigned integer `n`.
282+
///
283+
/// Returns `None` if the sum overflows.
284+
///
285+
/// # Examples
286+
/// ```
287+
/// # use utils::number::sum_of_divisors;
288+
/// assert_eq!(sum_of_divisors(5u32), Some(6));
289+
/// assert_eq!(sum_of_divisors(32u32), Some(63));
290+
/// assert_eq!(sum_of_divisors(50u32), Some(93));
291+
/// assert_eq!(sum_of_divisors(857_656_800u32), None);
292+
/// assert_eq!(sum_of_divisors(857_656_800u64), Some(4_376_251_152));
293+
/// ```
294+
#[inline]
295+
#[must_use]
296+
pub fn sum_of_divisors<T: UnsignedInteger>(n: T) -> Option<T> {
297+
if n <= T::ONE {
298+
return Some(n);
299+
}
300+
301+
let mut sum = T::ZERO;
302+
let mut d = T::ONE;
303+
while let Some(square) = d.checked_mul(d)
304+
&& square <= n
305+
{
306+
if n % d == T::ZERO {
307+
if let Some(s) = sum.checked_add(d) {
308+
sum = s;
309+
} else {
310+
return None;
311+
}
312+
313+
let q = n / d;
314+
if q != d {
315+
if let Some(s) = sum.checked_add(q) {
316+
sum = s;
317+
} else {
318+
return None;
319+
}
320+
}
321+
}
322+
323+
d += T::ONE;
324+
}
325+
326+
Some(sum)
327+
}
328+
280329
/// Computes the greatest common divisor (GCD) using the extended Euclidean algorithm.
281330
///
282331
/// Returns a tuple `(gcd, x, y)` where `x`, `y` are the coefficients of Bézout's identity:
@@ -291,6 +340,7 @@ pub fn is_prime<T: UnsignedInteger>(n: T) -> bool {
291340
/// assert_eq!((252 * -2) + (105 * 5), 21);
292341
/// ```
293342
#[inline]
343+
#[must_use]
294344
pub fn egcd<T: SignedInteger>(mut a: T, mut b: T) -> (T, T, T) {
295345
let (mut x0, mut x1, mut y0, mut y1) = (T::ONE, T::ZERO, T::ZERO, T::ONE);
296346

@@ -312,6 +362,8 @@ pub fn egcd<T: SignedInteger>(mut a: T, mut b: T) -> (T, T, T) {
312362
/// assert_eq!(lcm(6, 4), 12);
313363
/// assert_eq!(lcm(21, 6), 42);
314364
/// ```
365+
#[inline]
366+
#[must_use]
315367
pub fn lcm<T: SignedInteger>(a: T, b: T) -> T {
316368
if a == T::ZERO || b == T::ZERO {
317369
return T::ZERO;
@@ -335,6 +387,7 @@ pub fn lcm<T: SignedInteger>(a: T, b: T) -> T {
335387
/// assert_eq!(mod_inverse(2, 8), None);
336388
/// ```
337389
#[inline]
390+
#[must_use]
338391
pub fn mod_inverse<T: SignedInteger>(a: T, b: T) -> Option<T> {
339392
let (gcd, x, _) = egcd(a, b);
340393
if gcd == T::ONE {
@@ -358,6 +411,7 @@ pub fn mod_inverse<T: SignedInteger>(a: T, b: T) -> Option<T> {
358411
/// assert_eq!(366 % 11, 3);
359412
/// ```
360413
#[inline]
414+
#[must_use]
361415
pub fn chinese_remainder<T: SignedInteger>(
362416
residues: impl IntoIterator<Item = T>,
363417
moduli: impl IntoIterator<Item = T, IntoIter: Clone>,
@@ -383,6 +437,7 @@ pub fn chinese_remainder<T: SignedInteger>(
383437
/// assert_eq!(mod_pow::<u64>(65, 100000, 2147483647), 1085966926);
384438
/// ```
385439
#[inline]
440+
#[must_use]
386441
pub fn mod_pow<T: UnsignedInteger>(base: T, exponent: T, modulus: T) -> T {
387442
let mut result = T::ONE;
388443
let mut base = base % modulus;

crates/year2017/src/day23.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ impl Day23 {
131131
] if b == b2 && b == b3 && reg[b as usize] >= 0
132132
&& d == d2 && d == d3 && d == d4
133133
&& e == e2 && e == e3 && e == e4
134-
&& g == g2 && g == g3 && g == g4 && g == g5&& g == g6 && g == g7 && g == g8 && g == g9 && g == g10
134+
&& g == g2 && g == g3 && g == g4 && g == g5 && g == g6 && g == g7 && g == g8 && g == g9 && g == g10
135135
=> {
136136
reg[d as usize] = reg[b as usize];
137137
reg[e as usize] = reg[b as usize];

0 commit comments

Comments
 (0)