add 2023/06
This commit is contained in:
parent
9a9545425a
commit
1063818bf3
|
@ -0,0 +1,2 @@
|
||||||
|
Time: 51 69 98 78
|
||||||
|
Distance: 377 1171 1224 1505
|
|
@ -0,0 +1,40 @@
|
||||||
|
#![feature(test)]
|
||||||
|
extern crate test;
|
||||||
|
use aoc2023::{boilerplate, common::*};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use tuple_map::TupleMap2;
|
||||||
|
|
||||||
|
const DAY: usize = 6;
|
||||||
|
type I = usize;
|
||||||
|
type Parsed = (Vec<(I, I)>, (f64, f64));
|
||||||
|
|
||||||
|
fn parse_input(raw: &str) -> Parsed {
|
||||||
|
let lines = raw.lines().collect_tuple::<(_, _)>().unwrap();
|
||||||
|
let (time, distance) = lines.map(|l| l.split_ascii_whitespace().skip(1).map(parse_num).collect_vec());
|
||||||
|
let part1 = time.into_iter().zip(distance).collect();
|
||||||
|
let part2 = lines.map(|l| l.after(":").replace(' ', "").parse().unwrap());
|
||||||
|
(part1, part2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1((races, _): &Parsed) -> usize {
|
||||||
|
races.iter().cloned().map(|(time, distance)| (1..time).filter(|i| i * (time - i) > distance).count()).product()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2((_, (time, distance)): &Parsed) -> usize {
|
||||||
|
let x1 = time / 2.0 + (time * time / 4.0 - distance).sqrt();
|
||||||
|
let x2 = time / 2.0 - (time * time / 4.0 - distance).sqrt();
|
||||||
|
(x1 - x2).round() as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
boilerplate! {
|
||||||
|
TEST_INPUT == "\
|
||||||
|
Time: 7 15 30
|
||||||
|
Distance: 9 40 200",
|
||||||
|
tests: {
|
||||||
|
part1: { TEST_INPUT => 288 },
|
||||||
|
part2: { TEST_INPUT => 71504 }, // this is 1 off the real solution. I blame floats
|
||||||
|
},
|
||||||
|
bench1 == 131376,
|
||||||
|
bench2 == 34123437,
|
||||||
|
bench_parse: |(v, _): &Parsed| v.len() => 4,
|
||||||
|
}
|
|
@ -1,15 +1,28 @@
|
||||||
use std::iter::Step;
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
iter::Step,
|
||||||
|
ops::{Add, Mul},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn read_file(day: usize) -> String {
|
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()
|
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> {
|
pub trait ParseableNumber<I>: FromStr + Display + From<u8> + Add<I, Output = I> + Mul<I, Output = I> {}
|
||||||
l.lines().map(parse_num).collect()
|
macro_rules! parseable {
|
||||||
|
($($t: ty),*) => {
|
||||||
|
$(impl ParseableNumber<$t> for $t {})*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
parseable! {usize, u32, u64, isize, i32, i64}
|
||||||
|
|
||||||
|
pub fn parse_nums<I: ParseableNumber<I>>(l: &str) -> Vec<I> {
|
||||||
|
l.lines().map(parse_num::<I>).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_nums_comma(l: &str) -> Vec<usize> {
|
pub fn parse_nums_comma<I: ParseableNumber<I>>(l: &str) -> Vec<I> {
|
||||||
l.trim().split(',').map(parse_num).collect()
|
l.trim().split(',').map(parse_num::<I>).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Splitting {
|
pub trait Splitting {
|
||||||
|
@ -43,15 +56,15 @@ impl<T: Step + Default + Copy> Inc for T {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub fn parse_num<T: std::str::FromStr + std::fmt::Display>(s: &str) -> T {
|
pub fn parse_num<I: ParseableNumber<I>>(s: &str) -> I {
|
||||||
s.parse().unwrap_or_else(|_| panic!("Invalid number {s}"))
|
s.parse().unwrap_or_else(|_| panic!("Invalid number {s}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// For benchmarks.
|
// For benchmarks.
|
||||||
// This function assumes that the input will always be valid numbers and is UB otherwise
|
// This function assumes that the input will always be valid numbers and is UB otherwise
|
||||||
#[cfg(not(debug_assertions))]
|
#[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 {
|
pub fn parse_num<I: ParseableNumber<I>>(s: &str) -> I {
|
||||||
let mut digits = s.bytes().map(|b| T::from(b - b'0'));
|
let mut digits = s.bytes().map(|b| I::from(b - b'0'));
|
||||||
let start = unsafe { digits.next().unwrap_unchecked() };
|
let start = unsafe { digits.next().unwrap_unchecked() };
|
||||||
digits.fold(start, |acc, n| acc * T::from(10) + n)
|
digits.fold(start, |acc, n| acc * I::from(10) + n)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user