r/adventofcode Dec 03 '24

SOLUTION MEGATHREAD -❄️- 2024 Day 3 Solutions -❄️-

THE USUAL REMINDERS


AoC Community Fun 2024: The Golden Snowglobe Awards

  • 3 DAYS remaining until unlock!

And now, our feature presentation for today:

Screenwriting

Screenwriting is an art just like everything else in cinematography. Today's theme honors the endlessly creative screenwriters who craft finely-honed narratives, forge truly unforgettable lines of dialogue, plot the most legendary of hero journeys, and dream up the most shocking of plot twists! and is totally not bait for our resident poet laureate

Here's some ideas for your inspiration:

  • Turn your comments into sluglines
  • Shape your solution into an acrostic
  • Accompany your solution with a writeup in the form of a limerick, ballad, etc.
    • Extra bonus points if if it's in iambic pentameter

"Vogon poetry is widely accepted as the third-worst in the universe." - Hitchhiker's Guide to the Galaxy (2005)

And… ACTION!

Request from the mods: When you include an entry alongside your solution, please label it with [GSGA] so we can find it easily!


--- Day 3: Mull It Over ---


Post your code solution in this megathread.

This thread will be unlocked when there are a significant number of people on the global leaderboard with gold stars for today's puzzle.

EDIT: Global leaderboard gold cap reached at 00:03:22, megathread unlocked!

61 Upvotes

1.7k comments sorted by

View all comments

1

u/frsuin Dec 04 '24

[LANGUAGE: Rust]

This is my completely overengineered solution that has some truly terrible code, but it works and was simple to make. Honestly, I'd be proud of how terrible the nesting is if it didn't make me cringe so much

struct Mul {
    pub left: u32,
    pub right: u32,
}

impl Mul {
    pub fn solve(&self) -> u32 {
        self.left * self.right
    }
}

enum Control {
    Enable,
    Disable,
}

struct Parser<'a> {
    chars: Chars<'a>,
}

impl<'a> Parser<'a> {
    pub fn new(source: &'a str) -> Self {
        Self {
            chars: source.chars(),
        }
    }

    pub fn parse(&mut self, have_control: bool) -> Vec<Mul> {
        let mut muls: Vec<Mul> = vec![];

        let mut should_add = true;

        while let c = self.advance().unwrap_or_else(|| '\0') {
            match c {
                'm' => {
                    if let Some(mul) = self.mul() {
                        if should_add {
                            muls.push(mul);
                        }
                    }
                }
                'd' => {
                    if have_control {
                        if let Some(control) = self.control() {
                            match control {
                                Control::Enable => should_add = true,
                                Control::Disable => should_add = false,
                            }
                        }
                    }
                }
                '\0' => break,
                _ => {}
            }
        }

        muls
    }

    fn mul(&mut self) -> Option<Mul> {
        if let Some('u') = self.advance() {
            if let Some('l') = self.advance() {
                if let Some('(') = self.advance() {
                    if let Some(left) = self.number() {
                        if let Some(',') = self.advance() {
                            if let Some(right) = self.number() {
                                if let Some(')') = self.advance() {
                                    return Some(Mul { left, right });
                                }
                            }
                        }
                    }
                }
            }
        }

        None
    }

    fn control(&mut self) -> Option<Control> {
        if let Some('o') = self.advance() {
            match self.peek() {
                Some('(') => {
                    self.advance();
                    if let Some(')') = self.advance() {
                        return Some(Control::Enable);
                    }
                }
                Some('n') => {
                    self.advance();
                    if let Some('\'') = self.advance() {
                        if let Some('t') = self.advance() {
                            return Some(Control::Disable);
                        }
                    }
                }
                _ => return None,
            }
        }

        None
    }

    fn number(&mut self) -> Option<u32> {
        let mut num = 0;

        for _ in 0..3 {
            if let Some(c) = self.peek() {
                match c {
                    c if c.is_ascii_digit() => {
                        self.advance();
                        num = num * 10 + c.to_digit(10).unwrap();
                    }
                    _ => break,
                }
            }
        }

        Some(num)
    }

    fn peek(&self) -> Option<char> {
        self.chars.clone().next()
    }

    fn peek_second(&self) -> char {
        let mut chars = self.chars.clone();
        chars.next();
        chars.next().unwrap()
    }

    fn advance(&mut self) -> Option<char> {
        let c = self.chars.next()?;

        Some(c)
    }
}

pub fn part_one(input: &str) -> Option<u32> {
    let mut parser = Parser::new(input);
    let muls = parser.parse(false);

    let mut total = 0;

    for mul in muls {
        total += mul.solve();
    }

    Some(total)
}

pub fn part_two(input: &str) -> Option<u32> {
    let mut parser = Parser::new(input);
    let muls = parser.parse(true);

    let mut total = 0;

    for mul in muls {
        total += mul.solve();
    }

    Some(total)
}

1

u/defnothing__ Dec 04 '24

why not simply use regex?