day 4 part 1 and two

This commit is contained in:
RingOfStorms (Joshua Bell) 2023-12-04 00:40:38 -06:00
parent 99d91ab254
commit 41604e606a
3 changed files with 337 additions and 23 deletions

View file

@ -30,21 +30,18 @@ impl Grid {
}
}
fn get_adjacent_items(&self, row: usize, start: usize, end: usize) -> Vec<(&Item, usize, usize)> {
fn get_adjacent_items(
&self,
row: usize,
start: usize,
end: usize,
) -> Vec<(&Item, usize, usize)> {
// println!("\tget adj: r{} s{} e{}", row, start, end);
let row_start = if row > 0 {
row - 1
} else {
0
};
let col_start = if start > 0 {
start - 1
} else {
0
};
let row_start = if row > 0 { row - 1 } else { 0 };
let col_start = if start > 0 { start - 1 } else { 0 };
let mut items: Vec<(&Item, usize, usize)> = vec![];
for row_i in row_start ..= row + 1 {
for col_i in col_start ..= end + 1 {
for row_i in row_start..=row + 1 {
for col_i in col_start..=end + 1 {
if row_i != row || col_i < start || col_i > end {
let item = self.get_item(row_i, col_i);
@ -63,14 +60,17 @@ impl Grid {
for item in self.get_adjacent_items(row, col, col) {
match item {
(Item::Digit(_), r, c) => {
if let Some(number_at) =
self.numbers.iter().find(|n| n.row_index == r && c >= n.char_start && c <= n.char_end) {
if let Some(number_at) = self
.numbers
.iter()
.find(|n| n.row_index == r && c >= n.char_start && c <= n.char_end)
{
if unique_numbers.iter().all(|n| n.value != number_at.value) {
unique_numbers.push(number_at);
}
}
},
_ => { },
}
_ => {}
}
}
unique_numbers
@ -136,8 +136,11 @@ fn part1(input: String) -> Result<usize> {
let grid: Grid = input.parse()?;
let mut sum = 0;
for number in grid.numbers.iter() {
let adjacent = grid.get_adjacent_items(number.row_index, number.char_start, number.char_end);
let is_part_no = adjacent.iter().any(|item| matches!(item, (Item::Symbol(_), _, _)));
let adjacent =
grid.get_adjacent_items(number.row_index, number.char_start, number.char_end);
let is_part_no = adjacent
.iter()
.any(|item| matches!(item, (Item::Symbol(_), _, _)));
// ```
// println!(
@ -160,11 +163,16 @@ fn part2(input: String) -> Result<usize> {
let mut sum = 0;
let mut used: Vec<(usize, usize)> = vec![];
for number in grid.numbers.iter() {
let is_used =
used.iter().any(|(row, char_start)| number.row_index == *row && number.char_start == *char_start);
let is_used = used
.iter()
.any(|(row, char_start)| number.row_index == *row && number.char_start == *char_start);
if !is_used {
let adjacent = grid.get_adjacent_items(number.row_index, number.char_start, number.char_end);
if let Some((_, row, col)) = adjacent.iter().find(|item| matches!(item.0, Item::Symbol(true))) {
let adjacent =
grid.get_adjacent_items(number.row_index, number.char_start, number.char_end);
if let Some((_, row, col)) = adjacent
.iter()
.find(|item| matches!(item.0, Item::Symbol(true)))
{
let gear_nums = grid.get_adjacent_numbers(*row, *col);
if gear_nums.len() >= 2 {
// this is lazy.. adds duplicates but w/e

104
src/bin/day4.rs Normal file
View file

@ -0,0 +1,104 @@
use aoc23::prelude::*;
use itertools::Itertools;
use std::{
collections::{HashMap, VecDeque},
str::FromStr,
};
#[derive(Debug)]
struct Card {
id: usize,
winning_numbers: Vec<usize>,
numbers: Vec<usize>,
matches: usize,
score: usize,
}
impl FromStr for Card {
type Err = BoxE;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let mut id: Option<usize> = None;
let mut winning_numbers: Vec<usize> = vec![];
let mut numbers: Vec<usize> = vec![];
let mut score = 0;
let mut matches = 0;
for part in s.split(':') {
if id.is_some() {
for (num_mode, wins_or_nums) in part.split('|').enumerate() {
wins_or_nums
.trim()
.split_whitespace()
.into_iter()
.map(|num| {
num.parse::<usize>()
.expect(&format!("could not parse number: {}", num))
})
.for_each(|num| {
if num_mode == 0 {
winning_numbers.push(num);
} else {
numbers.push(num);
if winning_numbers.iter().any(|winner| winner == &num) {
matches += 1;
score = if score == 0 { 1 } else { score * 2 };
}
}
});
}
} else {
id = Some(
part.split_whitespace()
.last()
.ok_or("Failed to get last item")?
.parse()?,
)
}
}
Ok(Card {
id: id.ok_or("no id found")?,
winning_numbers,
numbers,
score,
matches,
})
}
}
fn part1(input: String) -> Result<usize> {
Ok(input
.lines()
.map(|line| line.parse::<Card>())
.filter_map(|card| card.ok())
.fold(0, |sum, card| sum + card.score))
}
fn part2(input: String) -> Result<usize> {
let mut sum = 0;
let cards = input
.lines()
.map(|line| line.parse::<Card>())
.filter_map(|card| card.ok())
.collect_vec();
let mut queue: VecDeque<&Card> = cards.iter().collect();
let mut counts: HashMap<usize, usize> = HashMap::new();
while let Some(card) = queue.pop_front() {
let counter = counts.entry(card.id).or_insert(0);
*counter += 1;
sum += 1;
for card_index in card.id..card.id + card.matches {
cards.get(card_index).map(|c| queue.push_back(&c));
}
}
Ok(sum)
}
#[tokio::main]
async fn main() -> Result<()> {
println!("Day 4");
println!("=====");
let input = utils::aoc::get_puzzle_input(4).await?;
println!("part 1: {}", part1(input.clone())?);
println!("part 2: {}", part2(input.clone())?);
Ok(())
}