mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Compare commits
3 Commits
8a0b72f111
...
9e37026f30
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e37026f30 | |||
| a926243f0d | |||
| a35ae82548 |
@@ -16,6 +16,10 @@ criterion = "0.3"
|
|||||||
# Keep debug information in release for better flamegraphs
|
# Keep debug information in release for better flamegraphs
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
|
[profile.bench]
|
||||||
|
# And same for benchmarking
|
||||||
|
debug = true
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "days"
|
name = "days"
|
||||||
harness = false
|
harness = false
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use criterion::criterion_main;
|
|||||||
use criterion::BenchmarkId;
|
use criterion::BenchmarkId;
|
||||||
use criterion::Criterion;
|
use criterion::Criterion;
|
||||||
|
|
||||||
const DAYS_IMPLEMENTED: usize = 13;
|
const DAYS_IMPLEMENTED: usize = 14;
|
||||||
|
|
||||||
fn read_input(day: usize) -> Vec<u8> {
|
fn read_input(day: usize) -> Vec<u8> {
|
||||||
let input_path = format!("inputs/{:02}.txt", day);
|
let input_path = format!("inputs/{:02}.txt", day);
|
||||||
|
|||||||
@@ -1,86 +1,91 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use crate::common::LineIter;
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::character::complete::multispace1;
|
||||||
|
use nom::multi::many1;
|
||||||
|
use nom::multi::separated_list1;
|
||||||
|
use nom::sequence::preceded;
|
||||||
|
use nom::sequence::tuple;
|
||||||
|
use nom::Finish;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct BingoCard {
|
struct BingoCard([(bool, u8); 25]);
|
||||||
ticks: [[bool; 5]; 5],
|
|
||||||
mapping: HashMap<u8, (u8, u8)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BingoCard {
|
impl BingoCard {
|
||||||
pub fn cross(&mut self, num: u8) -> bool {
|
pub fn cross(&mut self, num: u8) -> Option<usize> {
|
||||||
if let Some(&(x, y)) = self.mapping.get(&num) {
|
self.0
|
||||||
self.ticks[y as usize][x as usize] = true;
|
.iter_mut()
|
||||||
true
|
.enumerate()
|
||||||
} else {
|
.find_map(|(pos, (ticked, x))| {
|
||||||
false
|
if *x == num {
|
||||||
}
|
*ticked = true;
|
||||||
|
Some(pos)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_won(&self) -> bool {
|
pub fn has_won(&self, crossed: usize) -> bool {
|
||||||
// Check horizontal lines
|
// Check horizontal lines
|
||||||
if self.ticks.iter().any(|s| s.iter().all(|&b| b)) {
|
if self
|
||||||
|
.0
|
||||||
|
.chunks_exact(5)
|
||||||
|
.nth(crossed / 5)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.all(|&b| b.0)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check vertical lines
|
// Check vertical lines
|
||||||
(0..5).any(|x| self.ticks.iter().all(|row| row[x]))
|
self.0.iter().skip(crossed % 5).step_by(5).all(|b| b.0)
|
||||||
|
|
||||||
// Diagonals do not count
|
// Diagonals do not count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remaining(&self) -> u32 {
|
pub fn remaining(&self) -> u32 {
|
||||||
self.mapping
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(&num, &(x, y))| {
|
.filter_map(|&(ticked, num)| if !ticked { Some(num as u32) } else { None })
|
||||||
if self.ticks[y as usize][x as usize] {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(num as u32)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_input(input: &mut dyn Read) -> (Vec<u8>, Vec<BingoCard>) {
|
fn parse_numbers(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
|
||||||
let mut reader = LineIter::new(input);
|
use nom::character::complete::u8;
|
||||||
|
separated_list1(tag(","), u8)(input)
|
||||||
|
}
|
||||||
|
|
||||||
let numbers: Vec<u8> = reader
|
fn parse_bingo(mut input: &[u8]) -> IResult<&[u8], BingoCard> {
|
||||||
.next()
|
use nom::character::complete::u8;
|
||||||
.unwrap()
|
|
||||||
.split(',')
|
|
||||||
.map(|num| num.parse().unwrap())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut bingo_cards = Vec::new();
|
let mut card = [0; 25];
|
||||||
|
|
||||||
while reader.next().is_some() {
|
let mut parse_num = preceded(multispace1, u8);
|
||||||
let mut mapping = HashMap::with_capacity(25);
|
|
||||||
|
|
||||||
for y in 0..5 {
|
// fill doesn't work with preceded
|
||||||
reader
|
for num in &mut card {
|
||||||
.next()
|
let result = parse_num(input)?;
|
||||||
.unwrap()
|
*num = result.1;
|
||||||
.split(' ')
|
input = result.0;
|
||||||
.filter_map(|s| if s.is_empty() { None } else { s.parse().ok() })
|
|
||||||
.enumerate()
|
|
||||||
.for_each(|(x, num)| {
|
|
||||||
mapping.insert(num, (x as u8, y));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let card = BingoCard {
|
|
||||||
mapping,
|
|
||||||
ticks: Default::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
bingo_cards.push(card);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(numbers, bingo_cards)
|
Ok((input, BingoCard(card.map(|x| (false, x)))))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(input: &[u8]) -> IResult<&[u8], (Vec<u8>, Vec<BingoCard>)> {
|
||||||
|
tuple((parse_numbers, many1(parse_bingo)))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_input(input: &mut dyn Read) -> (Vec<u8>, Vec<BingoCard>) {
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
|
||||||
|
input.read_to_end(&mut buffer).unwrap();
|
||||||
|
|
||||||
|
parse_input(&buffer).finish().unwrap().1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn part1(input: &mut dyn Read) -> String {
|
pub fn part1(input: &mut dyn Read) -> String {
|
||||||
@@ -88,7 +93,7 @@ pub fn part1(input: &mut dyn Read) -> String {
|
|||||||
|
|
||||||
for number in numbers {
|
for number in numbers {
|
||||||
for card in &mut bingo_cards {
|
for card in &mut bingo_cards {
|
||||||
if card.cross(number) && card.has_won() {
|
if matches!(card.cross(number), Some(pos) if card.has_won(pos)) {
|
||||||
return (number as u32 * card.remaining()).to_string();
|
return (number as u32 * card.remaining()).to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +110,11 @@ pub fn part2(input: &mut dyn Read) -> String {
|
|||||||
|
|
||||||
for num in numbers {
|
for num in numbers {
|
||||||
for (won, card) in bingo_won.iter_mut().zip(bingo_cards.iter_mut()) {
|
for (won, card) in bingo_won.iter_mut().zip(bingo_cards.iter_mut()) {
|
||||||
if !*won && card.cross(num) && card.has_won() {
|
if *won {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(card.cross(num), Some(pos) if card.has_won(pos)) {
|
||||||
*won = true;
|
*won = true;
|
||||||
num_won += 1;
|
num_won += 1;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user