day12/day13: codspeed compat (&str input)

This commit is contained in:
Keenan Tims 2024-12-13 17:42:35 -08:00
parent a1774d1f73
commit ed184fc92c
Signed by: ktims
GPG Key ID: 11230674D69038D4
2 changed files with 34 additions and 36 deletions

View File

@ -1,3 +1,5 @@
use std::str::FromStr;
use aoc_runner_derive::{aoc, aoc_generator}; use aoc_runner_derive::{aoc, aoc_generator};
use grid::{Coord2d, Grid}; use grid::{Coord2d, Grid};
@ -5,11 +7,10 @@ pub struct Farm {
map: Grid<u8>, map: Grid<u8>,
} }
impl From<&[u8]> for Farm { impl FromStr for Farm {
fn from(input: &[u8]) -> Self { type Err = <Grid<u8> as FromStr>::Err;
Self { fn from_str(input: &str) -> Result<Self, Self::Err> {
map: Grid::from(input), Ok(Self { map: input.parse()? })
}
} }
} }
@ -100,10 +101,12 @@ impl Farm {
if visited.get(adj) == Some(&false) { if visited.get(adj) == Some(&false) {
// add the perimeter of the growth from there if not visited yet // add the perimeter of the growth from there if not visited yet
let (n_area, n_corners) = self.region_corners(adj, visited); let (n_area, n_corners) = self.region_corners(adj, visited);
(area+n_area, corners+n_corners) (area + n_area, corners + n_corners)
} else { (area, corners) } } else {
(area, corners)
}
} }
Some(_) | None => { (area, corners) } Some(_) | None => (area, corners),
} }
}) })
} }
@ -131,25 +134,26 @@ impl Farm {
} }
} }
#[aoc_generator(day12)] fn parse(input: &str) -> Farm {
fn parse(input: &[u8]) -> Farm { input.parse().unwrap()
input.into()
} }
#[aoc(day12, part1)] #[aoc(day12, part1)]
pub fn part1(farm: &Farm) -> u64 { pub fn part1(input: &str) -> u64 {
let farm = parse(input);
farm.regions_cost() farm.regions_cost()
} }
#[aoc(day12, part2)] #[aoc(day12, part2)]
pub fn part2(farm: &Farm) -> u64 { pub fn part2(input: &str) -> u64 {
let farm = parse(input);
farm.regions_discount_cost() farm.regions_discount_cost()
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
const EXAMPLE: &[u8] = b"RRRRIICCFF const EXAMPLE: &str = "RRRRIICCFF
RRRRIICCCF RRRRIICCCF
VVRRRCCFFF VVRRRCCFFF
VVRCCCJFFF VVRCCCJFFF
@ -162,11 +166,11 @@ MMMISSJEEE";
#[test] #[test]
fn part1_example() { fn part1_example() {
assert_eq!(part1(&parse(EXAMPLE)), 1930); assert_eq!(part1(EXAMPLE), 1930);
} }
#[test] #[test]
fn part2_example() { fn part2_example() {
assert_eq!(part2(&parse(EXAMPLE)), 1206); assert_eq!(part2(EXAMPLE), 1206);
} }
} }

View File

@ -1,8 +1,7 @@
use std::io::{BufRead, Lines}; use aoc_runner_derive::aoc;
use aoc_runner_derive::{aoc, aoc_generator};
use itertools::Itertools; use itertools::Itertools;
use regex::Regex; use regex::Regex;
use std::str::Lines;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MachineAction(i64, i64); pub struct MachineAction(i64, i64);
@ -15,17 +14,12 @@ struct ClawMachine {
} }
impl ClawMachine { impl ClawMachine {
fn consume_from_input<T: BufRead>(input: &mut Lines<T>) -> Option<Self> { fn consume_from_input(input: &mut Lines) -> Option<Self> {
// consume any empty lines at the front // consume any empty lines at the front
let ofs_re = Regex::new(r"X([+-]\d+), Y([+-]\d+)").unwrap(); let ofs_re = Regex::new(r"X([+-]\d+), Y([+-]\d+)").unwrap();
let prize_re = Regex::new(r"X=(\d+), Y=(\d+)").unwrap(); let prize_re = Regex::new(r"X=(\d+), Y=(\d+)").unwrap();
// consume 3 lines - a, b, prize // consume 3 lines - a, b, prize
if let Some((a_line, b_line, prize_line)) = input if let Some((a_line, b_line, prize_line)) = input.filter(|l| !l.is_empty()).take(3).collect_tuple() {
.filter(|l| l.as_ref().is_ok_and(|l| !l.is_empty()))
.take(3)
.map(|l| l.unwrap())
.collect_tuple()
{
let a_caps = ofs_re.captures(&a_line).unwrap(); let a_caps = ofs_re.captures(&a_line).unwrap();
let b_caps = ofs_re.captures(&b_line).unwrap(); let b_caps = ofs_re.captures(&b_line).unwrap();
let prize_caps = prize_re.captures(&prize_line).unwrap(); let prize_caps = prize_re.captures(&prize_line).unwrap();
@ -76,8 +70,8 @@ struct ClawMachines {
machines: Vec<ClawMachine>, machines: Vec<ClawMachine>,
} }
impl From<&[u8]> for ClawMachines { impl From<&str> for ClawMachines {
fn from(input: &[u8]) -> Self { fn from(input: &str) -> Self {
let mut machines = Vec::new(); let mut machines = Vec::new();
let mut lines = input.lines(); let mut lines = input.lines();
while let Some(machine) = ClawMachine::consume_from_input(&mut lines) { while let Some(machine) = ClawMachine::consume_from_input(&mut lines) {
@ -87,19 +81,19 @@ impl From<&[u8]> for ClawMachines {
} }
} }
#[aoc_generator(day13)] fn parse(input: &str) -> ClawMachines {
fn parse(input: &[u8]) -> ClawMachines {
ClawMachines::from(input) ClawMachines::from(input)
} }
#[aoc(day13, part1)] #[aoc(day13, part1)]
fn part1(machines: &ClawMachines) -> i64 { fn part1(input: &str) -> i64 {
let machines = parse(input);
machines.machines.iter().filter_map(|m| m.cheapest_prize()).sum() machines.machines.iter().filter_map(|m| m.cheapest_prize()).sum()
} }
#[aoc(day13, part2)] #[aoc(day13, part2)]
fn part2(machines: &ClawMachines) -> i64 { fn part2(input: &str) -> i64 {
let mut machines = machines.clone(); let mut machines = parse(input);
machines machines
.machines .machines
.iter_mut() .iter_mut()
@ -113,7 +107,7 @@ fn part2(machines: &ClawMachines) -> i64 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
const EXAMPLE: &[u8] = b"Button A: X+94, Y+34 const EXAMPLE: &str = "Button A: X+94, Y+34
Button B: X+22, Y+67 Button B: X+22, Y+67
Prize: X=8400, Y=5400 Prize: X=8400, Y=5400
@ -131,11 +125,11 @@ Prize: X=18641, Y=10279";
#[test] #[test]
fn part1_example() { fn part1_example() {
assert_eq!(part1(&parse(EXAMPLE)), 480); assert_eq!(part1(EXAMPLE), 480);
} }
#[test] #[test]
fn part2_example() { fn part2_example() {
assert_eq!(part2(&parse(EXAMPLE)), 875318608908); assert_eq!(part2(EXAMPLE), 875318608908);
} }
} }