advent-of-code 2025.5.0

Solutions to Advent of Code
Documentation
use crate::input::Input;

pub fn solve(input: &Input) -> Result<u32, String> {
    Ok(input
        .text
        .lines()
        .map(|line| calibration_value(line, input.is_part_two()))
        .sum())
}

fn calibration_value(line: &str, part2: bool) -> u32 {
    let (mut first_digit, mut last_digit) = (0, 0);

    let mut bits = 0_u64;
    for byte in line.bytes() {
        bits = (bits << 8) | u64::from(byte);

        let (m1, m2, m3) = if part2 {
            (0x00ff_ffff, 0xffff_ffff, 0xff_ffff_ffff)
        } else {
            (0, 0, 0)
        };

        #[allow(clippy::unreadable_literal)]
        let digit = match (bits & 0xff, bits & m1, bits & m2, bits & m3) {
            (49, ..) | (_, 0b11011110110111001100101, ..) => 1,
            (50, ..) | (_, 0b11101000111011101101111, ..) => 2,
            (51, ..) | (.., 0b111010001101000011100100110010101100101) => 3,
            (52, ..) | (.., 0b1100110011011110111010101110010, _) => 4,
            (53, ..) | (.., 0b1100110011010010111011001100101, _) => 5,
            (54, ..) | (_, 0b11100110110100101111000, ..) => 6,
            (55, ..) | (.., 0b111001101100101011101100110010101101110) => 7,
            (56, ..) | (.., 0b110010101101001011001110110100001110100) => 8,
            (57, ..) | (.., 0b1101110011010010110111001100101, _) => 9,
            _ => {
                continue;
            }
        };
        if first_digit == 0 {
            first_digit = digit;
        }
        last_digit = digit;
    }

    first_digit * 10 + last_digit
}

#[test]
pub fn tests() {
    let test_input = "1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet";
    test_part_one_no_allocations!(test_input => 142);

    let test_input = "two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen
five3threeqgtwone
twone
oneight
nine
ninine
eightwo";
    test_part_two_no_allocations!(test_input => 281 + 51 + 21 + 18 + 99 + 99 + 82);

    let test_input = "cneightwotdkfxxxjfdpz3zkkthree";
    test_part_two_no_allocations!(test_input => 83);

    let real_input = include_str!("day01_input.txt");
    test_part_one_no_allocations!(real_input => 55386);
    test_part_two_no_allocations!(real_input => 54824);
}