day(08): add initial solution
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
c975a73f7a
commit
e419087f1c
2 changed files with 149 additions and 0 deletions
5
samples/day08.txt
Normal file
5
samples/day08.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
30373
|
||||||
|
25512
|
||||||
|
65332
|
||||||
|
33549
|
||||||
|
35390
|
144
src/bin/day08.rs
Normal file
144
src/bin/day08.rs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
use std::{cmp::max, collections::BTreeSet};
|
||||||
|
|
||||||
|
use aoc_2022::*;
|
||||||
|
|
||||||
|
use color_eyre::eyre::Result;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use tracing::*;
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
|
type Input = Vec<Vec<i8>>;
|
||||||
|
type Output = usize;
|
||||||
|
|
||||||
|
fn count_in_rows(trees: &Input, counted: &mut BTreeSet<(usize, usize)>) {
|
||||||
|
trees.iter().enumerate().for_each(|(y, row)| {
|
||||||
|
row.iter().enumerate().fold(-1, |tallest, (x, tree)| {
|
||||||
|
if *tree > tallest {
|
||||||
|
counted.insert((x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
max(*tree, tallest)
|
||||||
|
});
|
||||||
|
|
||||||
|
row.iter().enumerate().rfold(-1, |tallest, (x, tree)| {
|
||||||
|
if *tree > tallest {
|
||||||
|
counted.insert((x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
max(*tree, tallest)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_in_columns(trees: &Input, counted: &mut BTreeSet<(usize, usize)>) {
|
||||||
|
(0..trees[0].len()).for_each(|x| {
|
||||||
|
(0..trees.len()).fold(-1, |tallest, y| {
|
||||||
|
if trees[y][x] > tallest {
|
||||||
|
counted.insert((x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
max(tallest, trees[y][x])
|
||||||
|
});
|
||||||
|
|
||||||
|
(0..trees.len()).rev().fold(-1, |tallest, y| {
|
||||||
|
if trees[y][x] > tallest {
|
||||||
|
counted.insert((x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
max(tallest, trees[y][x])
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_1(input: &Input) -> Output {
|
||||||
|
let mut counted: BTreeSet<(usize, usize)> = BTreeSet::new();
|
||||||
|
|
||||||
|
count_in_rows(input, &mut counted);
|
||||||
|
count_in_columns(input, &mut counted);
|
||||||
|
|
||||||
|
counted.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn in_range(trees: &Input, x: i32, y: i32) -> bool {
|
||||||
|
y >= 0 && y < trees.len() as i32 && x >= 0 && x < trees[y as usize].len() as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_scenic_score(trees: &Input, x: i32, y: i32) -> usize {
|
||||||
|
vec![(0, 1), (1, 0), (0, -1), (-1, 0)]
|
||||||
|
.iter()
|
||||||
|
.map(|&(dx, dy)| {
|
||||||
|
let max_height = trees[y as usize][x as usize];
|
||||||
|
let mut d = 1;
|
||||||
|
|
||||||
|
let mut visible = 0;
|
||||||
|
|
||||||
|
while in_range(trees, x + d * dx, y + d * dy) {
|
||||||
|
visible += 1;
|
||||||
|
|
||||||
|
if trees[(y + d * dy) as usize][(x + d * dx) as usize] >= max_height {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
d += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
visible as usize
|
||||||
|
})
|
||||||
|
.product()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_2(input: &Input) -> Output {
|
||||||
|
(0..input.len())
|
||||||
|
.flat_map(|y| {
|
||||||
|
(0..input[y].len()).map(move |x| compute_scenic_score(input, x as i32, y as i32))
|
||||||
|
})
|
||||||
|
.max()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(pathname: &str) -> Input {
|
||||||
|
file_to_string(pathname)
|
||||||
|
.lines()
|
||||||
|
.map(|line| {
|
||||||
|
line.chars()
|
||||||
|
.map(|c| c.to_digit(10).unwrap() as i8)
|
||||||
|
.collect_vec()
|
||||||
|
})
|
||||||
|
.collect_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
.with_env_filter(EnvFilter::from_default_env())
|
||||||
|
.with_target(false)
|
||||||
|
.with_file(true)
|
||||||
|
.with_line_number(true)
|
||||||
|
.without_time()
|
||||||
|
.compact()
|
||||||
|
.init();
|
||||||
|
color_eyre::install()?;
|
||||||
|
|
||||||
|
let input = parse_input("inputs/day08.txt");
|
||||||
|
|
||||||
|
info!("Part 1: {}", part_1(&input));
|
||||||
|
info!("Part 2: {}", part_2(&input));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod day_08 {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_part_1() {
|
||||||
|
let sample = parse_input("samples/day08.txt");
|
||||||
|
assert_eq!(part_1(&sample), 21);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_part_2() {
|
||||||
|
let sample = parse_input("samples/day08.txt");
|
||||||
|
assert_eq!(part_2(&sample), 8);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue