Day 1: Secret Entrance

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

you are viewing a single comment's thread
view the rest of the comments
[โ€“] 1 point 9 months ago* (last edited 9 months ago)

Rust

use std::{cmp::Ordering, fs, str::FromStr};

use color_eyre::eyre::{Result, bail};

const DIAL_NUMBERS: isize = 100;

#[derive(Clone, Copy)]
struct Dial(usize);

impl Dial {
    fn new() -> Self {
        Self(50)
    }

    fn rotate(&mut self, rot: isize) -> usize {
        let pass_0s;

        let total = rot.wrapping_add_unsigned(self.0);
        match total.cmp(&0) {
            Ordering::Equal => {
                pass_0s = 1;
                self.0 = 0;
            }
            Ordering::Less => {
                // Starting on 0 means we don't cross it
                let started_0 = if self.0 == 0 { 1 } else { 0 };
                pass_0s = 1 + (-total / DIAL_NUMBERS) as usize - started_0;
                self.0 = (self.0 as isize + rot).rem_euclid(DIAL_NUMBERS) as usize;
            }
            Ordering::Greater => {
                let full_turns = total / DIAL_NUMBERS;
                pass_0s = full_turns as usize;
                self.0 = (total - DIAL_NUMBERS * full_turns) as usize;
            }
        };

        pass_0s
    }

    fn sequence(&mut self, s: &str) -> Result<(usize, usize)> {
        let mut end_0s = 0;
        let mut pass_0s = 0;

        for l in s.lines() {
            let num = isize::from_str(&l[1..]).unwrap();
            let dir = l.bytes().next().unwrap();
            pass_0s += match dir {
                b'L' => self.rotate(-num),
                b'R' => self.rotate(num),
                _ => bail!("b{dir} is an invalid rotation direction"),
            };
            if self.0 == 0 {
                end_0s += 1;
            }
        }

        Ok((end_0s, pass_0s))
    }
}

fn parts(filepath: &str) -> Result<(usize, usize)> {
    let input = fs::read_to_string(filepath)?;
    let mut dial = Dial::new();
    let res = dial.sequence(&input)?;
    Ok(res)
}

fn main() -> Result<()> {
    color_eyre::install()?;

    let (p1, p2) = parts("d01/input.txt")?;
    println!("Part 1: {p1}");
    println!("Part 2: {p2}");
    Ok(())
}

I lost a lot of time struggling with edge cases in part two since I thought it was wasteful to run rem_euclid() (i.e. modulus) when I'd already got the information to do it more efficiently. While I got there in the end my final code was a bit ugly. This prettier, "unoptimised" version runs in 1.6ms, so I was being an idiot.

  • source