Compare commits
1 commit
master
...
2023-day1-
Author | SHA1 | Date | |
---|---|---|---|
969d6d3977 |
1 changed files with 70 additions and 83 deletions
|
@ -1,115 +1,102 @@
|
|||
use crate::prelude::*;
|
||||
use std::cell::OnceCell;
|
||||
|
||||
mod prelude;
|
||||
|
||||
const DIGITS = OnceCell::new();
|
||||
|
||||
fn main() {
|
||||
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 {}
|
||||
impl Day1 {
|
||||
fn calibration_value(line: &str) -> i128 {
|
||||
println!("{line}");
|
||||
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 is_digit(b: &u8) -> bool {
|
||||
(ASCII_ZERO..=ASCII_NINE).contains(b)
|
||||
}
|
||||
|
||||
fn num_name(s: &[u8]) -> Option<u8> {
|
||||
for (i, w) in [
|
||||
"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 to_digit(b: &u8) -> Solution {
|
||||
i64::from(b - ASCII_ZERO)
|
||||
}
|
||||
|
||||
fn num_name_end(s: &[u8]) -> Option<u8> {
|
||||
for (i, w) in [
|
||||
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||
]
|
||||
.map(|s| s.as_bytes())
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
if s.ends_with(w) {
|
||||
return Some(i as u8);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
fn calibration_value(line_bytes: &[u8]) -> i64 {
|
||||
let i1 = line_bytes.iter().position(Self::is_digit).unwrap();
|
||||
let i2 = line_bytes[i1..]
|
||||
.iter()
|
||||
.rev()
|
||||
.position(Self::is_digit)
|
||||
.unwrap_or(i1);
|
||||
|
||||
Self::to_digit(&line_bytes[i1]) * 10 + Self::to_digit(&line_bytes[i2])
|
||||
}
|
||||
|
||||
fn calibration_value_words(line: &str) -> i128 {
|
||||
println!("{line}");
|
||||
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!("NI: {n} {i}");
|
||||
if first_digit.is_none() {
|
||||
if (0x30..=0x39).contains(&bytes[i]) {
|
||||
first_digit = Some(bytes[i] - 0x30);
|
||||
println!("found first {first_digit:?}");
|
||||
} else if let Some(n) = Self::num_name(&bytes[i..]) {
|
||||
first_digit = Some(n);
|
||||
println!("found first text {first_digit:?}");
|
||||
// part 2
|
||||
|
||||
fn num_name(s: &[u8], digits: &[&[u8]]) -> Option<i64> {
|
||||
digits
|
||||
.iter()
|
||||
.position(|d| s.starts_with(d))
|
||||
.map(|n| n as i64)
|
||||
}
|
||||
|
||||
fn num_or_digit(s: &[u8], digits: &[&[u8]]) -> Option<Solution> {
|
||||
if Self::is_digit(&s[0]) {
|
||||
Some(Self::to_digit(&s[0]))
|
||||
} else {
|
||||
Self::num_name(s, digits)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
return first_digit * 10 + first_digit;
|
||||
}
|
||||
}
|
||||
println!("{:?} {:?}", first_digit, last_digit);
|
||||
Into::<i128>::into(first_digit.or(last_digit).unwrap() * 10)
|
||||
+ Into::<i128>::into(last_digit.or(first_digit).unwrap())
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
impl AoCSolution for Day1 {
|
||||
type Input = String;
|
||||
type Solution = i128;
|
||||
type Solution = i64;
|
||||
|
||||
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 {
|
||||
input.lines().map(Self::calibration_value_words).sum()
|
||||
input
|
||||
.lines()
|
||||
.map(|l| Self::calibration_value_words(l.as_bytes()))
|
||||
.sum()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue