2020-12-03 10:24:03 +01:00
#![ feature(iter_map_while) ]
2020-12-03 08:54:04 +01:00
#![ feature(test) ]
extern crate test ;
use itertools ::Itertools ;
2020-12-03 10:24:03 +01:00
use std ::iter ;
2020-12-03 08:54:04 +01:00
2020-12-03 10:24:03 +01:00
#[ derive(Debug, PartialEq, Copy, Clone) ]
2020-12-03 08:54:04 +01:00
enum Tile {
Free ,
Tree ,
}
type Forest = Vec < Vec < Tile > > ;
const STEP_RIGHT : [ usize ; 5 ] = [ 1 , 3 , 5 , 7 , 1 ] ;
const STEP_DOWN : [ usize ; 5 ] = [ 1 , 1 , 1 , 1 , 2 ] ;
impl From < char > for Tile {
fn from ( c : char ) -> Self {
match c {
'.' = > Tile ::Free ,
'#' = > Tile ::Tree ,
_ = > unreachable! ( ) ,
}
}
}
fn read_input ( ) -> String {
std ::fs ::read_to_string ( " input " ) . unwrap ( )
}
fn parse_input ( raw : & str ) -> Forest {
raw . lines ( ) . map ( | l | l . chars ( ) . map_into ( ) . collect ( ) ) . collect ( )
}
fn count_all_paths ( forest : & Forest ) -> usize {
2020-12-03 10:24:03 +01:00
STEP_RIGHT
. iter ( )
. zip ( STEP_DOWN . iter ( ) )
2020-12-03 08:54:04 +01:00
. map ( | ( & r , & d ) | count_trees ( forest , r , d ) )
. product ( )
}
fn count_trees ( forest : & Forest , step_right : usize , step_down : usize ) -> usize {
2020-12-03 10:27:03 +01:00
iter ::successors ( Some ( ( 0 , 0 ) ) , | ( y , x ) | Some ( ( y + step_down , ( x + step_right ) % forest [ 0 ] . len ( ) ) ) )
. map_while ( | ( y , x ) | forest . get ( y ) . map ( | r | r [ x ] ) )
. filter ( | & t | t = = Tile ::Tree )
. count ( )
2020-12-03 08:54:04 +01:00
}
fn main ( ) {
let forest = parse_input ( & read_input ( ) ) ;
let p1 = count_trees ( & forest , STEP_RIGHT [ 1 ] , STEP_DOWN [ 1 ] ) ;
println! ( " Part 1: {} " , p1 ) ;
let p2 = count_all_paths ( & forest ) ;
println! ( " Part 2: {} " , p2 ) ;
}
mod tests {
use super ::* ;
use test ;
const INPUT : & str = " ..##.......
#.. . #.. . #..
. #.. .. #.. #.
.. #. #.. . #. #
. #.. . ##.. #.
.. #. ##.. .. .
. #. #. #.. .. #
. #.. .. .. .. #
#. ##.. . #.. .
#.. . ##.. .. #
. #.. #.. . #. #" ;
#[ test ]
fn part1_test ( ) {
let forest = parse_input ( INPUT ) ;
2020-12-03 10:24:03 +01:00
assert_eq! ( count_trees ( & forest , STEP_RIGHT [ 1 ] , STEP_DOWN [ 1 ] ) , 7 ) ;
2020-12-03 08:54:04 +01:00
}
#[ test ]
fn part2_test ( ) {
let forest = parse_input ( INPUT ) ;
2020-12-03 10:24:03 +01:00
assert_eq! ( count_all_paths ( & forest ) , 336 ) ;
2020-12-03 08:54:04 +01:00
}
}