This commit is contained in:
Daniel Flanagan 2023-12-01 04:06:53 -06:00
parent ad791df964
commit 969d6d3977
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4

View file

@ -1,115 +1,102 @@
use crate::prelude::*; use crate::prelude::*;
use std::cell::OnceCell;
mod prelude; mod prelude;
const DIGITS = OnceCell::new();
fn main() { fn main() {
Day1::show(day_input(1), day_input(1)) Day1::show(day_input(1), day_input(1))
} }
const ASCII_ZERO: u8 = 0x30;
const ASCII_NINE: u8 = 0x39;
let value: &String = digits.get_or_init(|| {
[
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
]
.map(str::as_bytes)});
assert_eq!(value, "Hello, World!");
assert!(cell.get().is_some());
const DIGITS: [&[u8]; 10] = ;
const DIGITS_REV: [&[u8]; 10] = [
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
]
.map(|s| s.chars().rev().collect::<String>().as_bytes());
type Solution = i64;
struct Day1 {} struct Day1 {}
impl Day1 { impl Day1 {
fn calibration_value(line: &str) -> i128 { fn is_digit(b: &u8) -> bool {
println!("{line}"); (ASCII_ZERO..=ASCII_NINE).contains(b)
let bytes = line.as_bytes();
let mut first_digit: Option<u8> = None;
let mut last_digit: Option<u8> = None;
for i in 0..bytes.len() {
let n = bytes.len() - 1 - i;
println!("{n} {i}");
if first_digit.is_none() && (0x30..=0x39).contains(&bytes[i]) {
first_digit = Some(bytes[i] - 0x30);
println!("found first {first_digit:?}");
}
if last_digit.is_none() && (0x30..=0x39).contains(&bytes[n]) {
last_digit = Some(bytes[n] - 0x30);
println!("found last {last_digit:?}");
}
if first_digit.is_some() && last_digit.is_some() {
break;
}
}
println!("{:?} {:?}", first_digit, last_digit);
Into::<i128>::into(first_digit.or(last_digit).unwrap() * 10)
+ Into::<i128>::into(last_digit.or(first_digit).unwrap())
} }
fn num_name(s: &[u8]) -> Option<u8> { fn to_digit(b: &u8) -> Solution {
for (i, w) in [ i64::from(b - ASCII_ZERO)
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
]
.map(|s| s.as_bytes())
.iter()
.enumerate()
{
if s.starts_with(w) {
return Some(i as u8);
}
}
return None;
} }
fn num_name_end(s: &[u8]) -> Option<u8> { fn calibration_value(line_bytes: &[u8]) -> i64 {
for (i, w) in [ let i1 = line_bytes.iter().position(Self::is_digit).unwrap();
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", let i2 = line_bytes[i1..]
] .iter()
.map(|s| s.as_bytes()) .rev()
.iter() .position(Self::is_digit)
.enumerate() .unwrap_or(i1);
{
if s.ends_with(w) { Self::to_digit(&line_bytes[i1]) * 10 + Self::to_digit(&line_bytes[i2])
return Some(i as u8);
}
}
return None;
} }
fn calibration_value_words(line: &str) -> i128 { // part 2
println!("{line}");
let bytes = line.as_bytes(); fn num_name(s: &[u8], digits: &[&[u8]]) -> Option<i64> {
let mut first_digit: Option<u8> = None; digits
let mut last_digit: Option<u8> = None; .iter()
for i in 0..bytes.len() { .position(|d| s.starts_with(d))
let n = bytes.len() - 1 - i; .map(|n| n as i64)
println!("NI: {n} {i}"); }
if first_digit.is_none() {
if (0x30..=0x39).contains(&bytes[i]) { fn num_or_digit(s: &[u8], digits: &[&[u8]]) -> Option<Solution> {
first_digit = Some(bytes[i] - 0x30); if Self::is_digit(&s[0]) {
println!("found first {first_digit:?}"); Some(Self::to_digit(&s[0]))
} else if let Some(n) = Self::num_name(&bytes[i..]) { } else {
first_digit = Some(n); Self::num_name(s, digits)
println!("found first text {first_digit:?}"); }
}
fn calibration_value_words(line_bytes: &[u8]) -> i64 {
for i in 0..line_bytes.len() {
if let Some(first_digit) = Self::num_or_digit(&line_bytes[i..], &DIGITS) {
for j in (i..line_bytes.len()).rev() {
if let Some(last_digit) = Self::num_or_digit(&line_bytes[i..j], &DIGITS_REV) {
return first_digit * 10 + last_digit;
}
} }
} return first_digit * 10 + first_digit;
if last_digit.is_none() {
println!("{:?}", &bytes[..=n]);
if (0x30..=0x39).contains(&bytes[n]) {
last_digit = Some(bytes[n] - 0x30);
println!("found last {last_digit:?}");
} else if let Some(n) = Self::num_name_end(&bytes[..=n]) {
last_digit = Some(n);
println!("found last text {last_digit:?}");
}
}
if first_digit.is_some() && last_digit.is_some() {
break;
} }
} }
println!("{:?} {:?}", first_digit, last_digit); return 0;
Into::<i128>::into(first_digit.or(last_digit).unwrap() * 10)
+ Into::<i128>::into(last_digit.or(first_digit).unwrap())
} }
} }
impl AoCSolution for Day1 { impl AoCSolution for Day1 {
type Input = String; type Input = String;
type Solution = i128; type Solution = i64;
fn part1(input: Self::Input) -> Self::Solution { fn part1(input: Self::Input) -> Self::Solution {
input.lines().map(Self::calibration_value).sum() input
.lines()
.map(|l| Self::calibration_value(l.as_bytes()))
.sum()
} }
fn part2(input: Self::Input) -> Self::Solution { fn part2(input: Self::Input) -> Self::Solution {
input.lines().map(Self::calibration_value_words).sum() input
.lines()
.map(|l| Self::calibration_value_words(l.as_bytes()))
.sum()
} }
} }