[-] Deebster@programming.dev 2 points 2 years ago* (last edited 2 years ago)

Rust

I had a hunch about part two that didn't pay off, so I over-coded this instead of just using an array of arrays.

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

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

#[derive(Debug, Copy, Clone)]
enum Direction {
    N,
    NE,
    E,
    SE,
    S,
    SW,
    W,
    NW,
}

impl Direction {
    fn all() -> &'static [Direction] {
        &[
            Direction::N,
            Direction::NE,
            Direction::E,
            Direction::SE,
            Direction::S,
            Direction::SW,
            Direction::W,
            Direction::NW,
        ]
    }
}

#[derive(Debug, PartialEq, Eq)]
struct WordSearch {
    grid: Vec<char>,
    width: usize,
    height: usize,
}

impl FromStr for WordSearch {
    type Err = Report;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let grid: Vec<_> = s.chars().filter(|&ch| ch != '\n').collect();
        let width = s
            .chars()
            .position(|ch| ch == '\n')
            .ok_or_else(|| Report::msg("grid width cannot be zero, or one line"))?;
        let height = grid.len() / width;
        Ok(Self {
            grid,
            width,
            height,
        })
    }
}

impl WordSearch {
    fn neighbour(&self, i: usize, dir: Direction) -> Option<usize> {
        let width = self.width;
        let length = self.grid.len();
        use Direction::*;
        match dir {
            N if i >= width => Some(i - width),
            NE if i >= width && i % width != width - 1 => Some(i - width + 1),
            E if i % width != width - 1 => Some(i + 1),
            SE if i + width + 1 < length && i % width != width - 1 => Some(i + width + 1),
            S if i + width < length => Some(i + width),
            SW if i + width - 1 < length && i % width != 0 => Some(i + width - 1),
            W if i % width != 0 => Some(i - 1),
            NW if i >= width && i % width != 0 => Some(i - width - 1),
            _ => None,
        }
    }

    fn word_count(&self, word: &str) -> Result<usize> {
        let mut found = 0;
        for i in 0..self.grid.len() {
            for dir in Direction::all() {
                if self.word_present(word, i, *dir) {
                    found += 1;
                }
            }
        }
        Ok(found)
    }

    fn x_count(&self) -> Result<usize> {
        let mut found = 0;
        for i in 0..self.grid.len() {
            if self.x_present(i) {
                found += 1;
            }
        }
        Ok(found)
    }

    fn word_present(&self, word: &str, location: usize, dir: Direction) -> bool {
        let mut next = Some(location);
        for ch in word.chars() {
            let i = if let Some(i) = next {
                i
            } else {
                // Off the edge
                return false;
            };

            if self.grid[i] != ch {
                return false;
            }
            next = self.neighbour(i, dir);
        }
        true
    }

    fn x_present(&self, location: usize) -> bool {
        if self.grid.get(location) != Some(&'A') {
            return false;
        }
        let diags = [
            (Direction::NE, Direction::SW),
            (Direction::NW, Direction::SE),
        ];
        diags.iter().all(|(dir_a, dir_b)| {
            let Some(a_idx) = self.neighbour(location, *dir_a) else {
                return false;
            };
            let Some(b_idx) = self.neighbour(location, *dir_b) else {
                return false;
            };
            let a = self.grid[a_idx];
            let b = self.grid[b_idx];
            (a == 'M' && b == 'S') || (b == 'M' && a == 'S')
        })
    }
}

fn part1(filepath: &str) -> Result<usize> {
    let input = fs::read_to_string(filepath)?;
    let grid = WordSearch::from_str(&input)?;
    grid.word_count("XMAS")
}

fn part2(filepath: &str) -> Result<usize> {
    let input = fs::read_to_string(filepath)?;
    let grid = WordSearch::from_str(&input)?;
    grid.x_count()
}

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

    println!("Part 1: {}", part1("d04/input.txt")?);
    println!("Part 2: {}", part2("d04/input.txt")?);
    Ok(())
}
[-] Deebster@programming.dev 2 points 2 years ago

Not funny, but interesting!

[-] Deebster@programming.dev 2 points 2 years ago

Telescopes don't allow you to hear sound from space though...

I wondered if they meant that you couldn't help but imagine the sound when seeing it - I don't know if there's a word for that (or where to ask on Lemmy).

[-] Deebster@programming.dev 2 points 2 years ago

“The ledges are full of bird shite and are just minging,” says Johnston.

Haha, what a quote to get in the papers.

[-] Deebster@programming.dev 2 points 2 years ago

Sounds great. I tried bourbon in an amaretto sour (a godfather sour?) last night, although the recipe I used still asked for a decent amount of syrup so I think it brought it back to a usual sweetness.

[-] Deebster@programming.dev 2 points 2 years ago

sweet stop

I think you mean sweet spot. Now I'm wondering if it's a typo or an eggcorn.

[-] Deebster@programming.dev 2 points 2 years ago

Why is a judge allowed to compete?

[-] Deebster@programming.dev 2 points 2 years ago* (last edited 2 years ago)

I see! Great work, along with plenty of others in your post history.

Is this unedited, or did you bring out that contrast in post?

[-] Deebster@programming.dev 2 points 2 years ago* (last edited 2 years ago)

I miss The Register being a UK publication - I've never heard of any grandfather's axe, but I have heard of Trigger's broom.

[-] Deebster@programming.dev 2 points 2 years ago

I just replayed Little Inferno after something reminded me about it and I noticed there was a DLC released (in late 2022).

It's a sandbox puzzle game where you burn stuff in your fireplace and try to find combos. There's slightly more to it, but really just stuff that's there to stop you buying + burning everything at once and insta-completing the game.

The DLC adds a new catalogue and more combos; if you're replaying you don't need to replay the main game too as it just adds to that (with a few changes).

[-] Deebster@programming.dev 2 points 2 years ago

I don't see it as much of a plot hole; I'd assumed he'd previously had an interest and had some replica stuff lying around (as people do today) and so when he needed an escape he had them to hand for his fantasy/delusion.

[-] Deebster@programming.dev 2 points 3 years ago

That looks really interesting, I'm fairly happy with Joplin but SB looks like how I’d do things if I wrote something like this.

view more: ‹ prev next ›

Deebster

0 post score
0 comment score
joined 3 years ago