2022-12-08 11:36:21 +01:00
#![ feature(test) ]
extern crate test ;
2022-12-08 12:16:39 +01:00
use itertools ::Itertools ;
2022-12-08 11:36:21 +01:00
use std ::iter ::repeat ;
use aoc2022 ::{ boilerplate , common ::* } ;
const DAY : usize = 08 ;
type Parsed = Vec < Vec < u8 > > ;
fn parse_input ( raw : & str ) -> Parsed {
raw . lines ( ) . map ( | l | l . as_bytes ( ) . to_vec ( ) ) . collect ( )
}
fn is_visible_1d < ' a > ( iter : impl IntoIterator < Item = & ' a u8 > ) -> Vec < bool > {
iter . into_iter ( )
. scan ( 0 , | max , tree | {
let visible = tree > max ;
* max = * tree . max ( max ) ;
Some ( visible )
} )
. collect ( )
}
fn part1 ( parsed : & Parsed ) -> usize {
2022-12-08 12:16:39 +01:00
let size = parsed . len ( ) ; // input is always square
2022-12-08 11:36:21 +01:00
let a : Vec < _ > = parsed . iter ( ) . map ( is_visible_1d ) . collect ( ) ;
let b : Vec < _ > = parsed
. iter ( )
. map ( | l | {
let mut v = is_visible_1d ( l . iter ( ) . rev ( ) ) ;
v . reverse ( ) ;
v
} )
. collect ( ) ;
2022-12-08 12:16:39 +01:00
let c : Vec < _ > = ( 0 .. size ) . map ( | i | is_visible_1d ( parsed . iter ( ) . map ( | row | & row [ i ] ) ) ) . collect ( ) ;
let d : Vec < _ > = ( 0 .. size )
2022-12-08 11:36:21 +01:00
. map ( | i | {
let mut v = is_visible_1d ( parsed . iter ( ) . rev ( ) . map ( | row | & row [ i ] ) ) ;
v . reverse ( ) ;
v
} )
. collect ( ) ;
2022-12-08 12:16:39 +01:00
( 0 .. size ) . flat_map ( | i | repeat ( i ) . zip ( 0 .. size ) ) . filter ( | & ( i , j ) | a [ i ] [ j ] | | b [ i ] [ j ] | | c [ j ] [ i ] | | d [ j ] [ i ] ) . count ( )
2022-12-08 11:36:21 +01:00
}
fn part2 ( parsed : & Parsed ) -> usize {
2022-12-08 12:16:39 +01:00
let size = parsed . len ( ) ; // input is always square
( 1 .. size - 1 )
. flat_map ( | i | repeat ( i ) . zip ( 1 .. size - 1 ) )
. map ( | ( i , j ) | {
let tree = parsed [ i ] [ j ] ;
let mut heights = ( ( i + 1 ) .. size ) . map ( | i | parsed [ i ] [ j ] ) . peekable ( ) ;
let a = heights . peeking_take_while ( | & t | t < tree ) . count ( ) + heights . peek ( ) . map ( | _ | 1 ) . unwrap_or ( 0 ) ;
let mut heights = ( 0 .. i ) . rev ( ) . map ( | i | parsed [ i ] [ j ] ) . peekable ( ) ;
let b = heights . peeking_take_while ( | & t | t < tree ) . count ( ) + heights . peek ( ) . map ( | _ | 1 ) . unwrap_or ( 0 ) ;
let mut heights = ( ( j + 1 ) .. size ) . map ( | j | parsed [ i ] [ j ] ) . peekable ( ) ;
let c = heights . peeking_take_while ( | & t | t < tree ) . count ( ) + heights . peek ( ) . map ( | _ | 1 ) . unwrap_or ( 0 ) ;
let mut heights = ( 0 .. j ) . rev ( ) . map ( | j | parsed [ i ] [ j ] ) . peekable ( ) ;
let d = heights . peeking_take_while ( | & t | t < tree ) . count ( ) + heights . peek ( ) . map ( | _ | 1 ) . unwrap_or ( 0 ) ;
a * b * c * d
} )
. max ( )
. unwrap ( )
2022-12-08 11:36:21 +01:00
}
#[ cfg(test) ]
const TEST_OUTPUT : & [ bool ] = & [ true , true , false , true , false ] ;
boilerplate! {
TEST_INPUT = = " 30373
25512
65332
33549
35390 " ,
tests : {
part1 : { TEST_INPUT = > 21 } ,
2022-12-08 12:16:39 +01:00
part2 : { TEST_INPUT = > 8 } ,
2022-12-08 11:36:21 +01:00
} ,
unittests : {
is_visible_1d : { [ 1 , 3 , 2 , 4 , 2 ] = > TEST_OUTPUT , } ,
} ,
bench1 = = 1543 ,
2022-12-08 12:16:39 +01:00
bench2 = = 595080 ,
2022-12-08 11:36:21 +01:00
bench_parse : Vec ::len = > 99 ,
}