day10, part1
This commit is contained in:
parent
d1b628fff1
commit
81f7933cc0
1 changed files with 161 additions and 2 deletions
|
@ -1,13 +1,172 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
let input = std::fs::read_to_string("input").unwrap();
|
||||
let grid = Grid::new(&input);
|
||||
println!("{}", pt1(&grid));
|
||||
}
|
||||
|
||||
fn pt1(grid: &Grid) -> usize {
|
||||
dfs(grid)
|
||||
}
|
||||
|
||||
fn dfs(grid: &Grid) -> usize {
|
||||
let mut total = 0;
|
||||
|
||||
for head in grid.heads.iter() {
|
||||
let mut processed = HashSet::new();
|
||||
let mut q = Vec::new();
|
||||
|
||||
q.push(*head);
|
||||
while let Some(current) = q.pop() {
|
||||
if !processed.contains(¤t) {
|
||||
q.push(current);
|
||||
}
|
||||
|
||||
let mut do_top = true;
|
||||
let nexts = grid.next_step(¤t);
|
||||
for next in nexts.iter() {
|
||||
if !processed.contains(next) {
|
||||
q.push(*next);
|
||||
do_top = false;
|
||||
}
|
||||
}
|
||||
|
||||
if do_top {
|
||||
let _ = q.pop();
|
||||
processed.insert(current);
|
||||
if grid.get(¤t).unwrap() == 9 {
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
total
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Grid {
|
||||
rows: Vec<Vec<usize>>,
|
||||
heads: Vec<Loc>,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
fn new(input: &str) -> Self {
|
||||
todo!()
|
||||
let mut rows = Vec::new();
|
||||
let mut heads = Vec::new();
|
||||
for (row, line) in input.lines().enumerate() {
|
||||
let row = line
|
||||
.chars()
|
||||
.enumerate()
|
||||
.map(|(col, c)| {
|
||||
let n = c.to_digit(10).unwrap() as usize;
|
||||
if n == 0 {
|
||||
heads.push(Loc { row, col });
|
||||
}
|
||||
n
|
||||
})
|
||||
.collect();
|
||||
rows.push(row);
|
||||
}
|
||||
Self { rows, heads }
|
||||
}
|
||||
|
||||
fn get(&self, loc: &Loc) -> Option<usize> {
|
||||
self.rows
|
||||
.get(loc.row)
|
||||
.and_then(|row| row.get(loc.col).copied())
|
||||
}
|
||||
|
||||
fn next(&self, loc: &Loc) -> Vec<Tile> {
|
||||
let Loc { row, col } = *loc;
|
||||
let mut out = Vec::new();
|
||||
|
||||
// north
|
||||
{
|
||||
let row = row.wrapping_sub(1);
|
||||
if let Some(&alt) = self.rows.get(row).and_then(|r| r.get(col)) {
|
||||
out.push(Tile {
|
||||
alt,
|
||||
loc: Loc { row, col },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// south
|
||||
{
|
||||
let row = row + 1;
|
||||
if let Some(&alt) = self.rows.get(row).and_then(|r| r.get(col)) {
|
||||
out.push(Tile {
|
||||
alt,
|
||||
loc: Loc { row, col },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// east
|
||||
{
|
||||
let col = col + 1;
|
||||
if let Some(&alt) = self.rows.get(row).and_then(|r| r.get(col)) {
|
||||
out.push(Tile {
|
||||
alt,
|
||||
loc: Loc { row, col },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// west
|
||||
{
|
||||
let col = col.wrapping_sub(1);
|
||||
if let Some(&alt) = self.rows.get(row).and_then(|r| r.get(col)) {
|
||||
out.push(Tile {
|
||||
alt,
|
||||
loc: Loc { row, col },
|
||||
});
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn next_step(&self, loc: &Loc) -> Vec<Loc> {
|
||||
let alt = self.rows[loc.row][loc.col];
|
||||
let target = alt + 1;
|
||||
self.next(loc)
|
||||
.iter()
|
||||
.filter_map(|t| if t.alt == target { Some(t.loc) } else { None })
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
struct Loc {
|
||||
row: usize,
|
||||
col: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
struct Tile {
|
||||
loc: Loc,
|
||||
alt: usize,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::*;
|
||||
|
||||
static INPUT: &str = "89010123
|
||||
78121874
|
||||
87430965
|
||||
96549874
|
||||
45678903
|
||||
32019012
|
||||
01329801
|
||||
10456732";
|
||||
|
||||
#[test]
|
||||
fn p1() {
|
||||
let g = Grid::new(INPUT);
|
||||
assert_eq!(36, pt1(&g));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue