2023-12-03 16:25:25 +01:00
use std ::iter ::Step ;
2023-11-30 23:56:01 +01:00
pub fn read_file ( day : usize ) -> String {
std ::fs ::read_to_string ( std ::env ::var ( " AOC_INPUT " ) . unwrap_or_else ( | _ | format! ( " inputs/day {day:0>2} " ) ) ) . unwrap ( )
}
pub fn parse_nums ( l : & str ) -> Vec < usize > {
l . lines ( ) . map ( parse_num ) . collect ( )
}
pub fn parse_nums_comma ( l : & str ) -> Vec < usize > {
l . trim ( ) . split ( ',' ) . map ( parse_num ) . collect ( )
}
2023-12-02 10:14:10 +01:00
pub trait Splitting {
fn before < ' a > ( & ' a self , sep : & str ) -> & ' a str ;
fn after < ' a > ( & ' a self , sep : & str ) -> & ' a str ;
}
impl Splitting for & str {
fn after < ' a > ( & ' a self , sep : & str ) -> & ' a str {
self . split_once ( sep ) . unwrap ( ) . 1
}
fn before < ' a > ( & ' a self , sep : & str ) -> & ' a str {
self . split_once ( sep ) . unwrap ( ) . 0
}
}
2023-12-03 16:25:25 +01:00
pub trait Inc : Default + Copy + Step {
fn inc ( self ) -> Self ;
fn dec ( self ) -> Self ;
}
impl < T : Step + Default + Copy > Inc for T {
fn inc ( self ) -> Self {
T ::forward ( self , 1 )
}
fn dec ( self ) -> Self {
T ::backward ( self , 1 )
}
}
2023-11-30 23:56:01 +01:00
#[ cfg(debug_assertions) ]
pub fn parse_num < T : std ::str ::FromStr + std ::fmt ::Display > ( s : & str ) -> T {
s . parse ( ) . unwrap_or_else ( | _ | panic! ( " Invalid number {s} " ) )
}
// For benchmarks.
// This function assumes that the input will always be valid numbers and is UB otherwise
#[ cfg(not(debug_assertions)) ]
pub fn parse_num < T : From < u8 > + std ::ops ::Add < T , Output = T > + std ::ops ::Mul < T , Output = T > > ( s : & str ) -> T {
let mut digits = s . bytes ( ) . map ( | b | T ::from ( b - b '0' ) ) ;
let start = unsafe { digits . next ( ) . unwrap_unchecked ( ) } ;
digits . fold ( start , | acc , n | acc * T ::from ( 10 ) + n )
}