1
0
Fork 0

Compare commits

...

2 Commits

Author SHA1 Message Date
Andrew Coleman fc5670b37e remove debug derives 2023-12-13 13:48:00 -05:00
Andrew Coleman e6cf50fb47 day12 solution. gross. 2023-12-13 13:47:53 -05:00
8 changed files with 220 additions and 23 deletions

View File

@ -4,14 +4,12 @@ const MAX_RED: u32 = 12;
const MAX_GREEN: u32 = 13; const MAX_GREEN: u32 = 13;
const MAX_BLUE: u32 = 14; const MAX_BLUE: u32 = 14;
#[derive(Debug)]
struct Turn { struct Turn {
red: u32, red: u32,
green: u32, green: u32,
blue: u32, blue: u32,
} }
#[derive(Debug)]
struct Game { struct Game {
id: u32, id: u32,
turns: Vec<Turn>, turns: Vec<Turn>,

View File

@ -1,7 +1,6 @@
use aoc_runner_derive::{aoc, aoc_generator}; use aoc_runner_derive::{aoc, aoc_generator};
use std::collections::HashSet; use std::collections::HashSet;
#[derive(Debug)]
struct Card { struct Card {
id: usize, id: usize,
winning: HashSet<u32>, winning: HashSet<u32>,

View File

@ -1,6 +1,5 @@
use aoc_runner_derive::{aoc, aoc_generator}; use aoc_runner_derive::{aoc, aoc_generator};
#[derive(Debug)]
struct Race { struct Race {
time: u64, time: u64,
distance: u64, distance: u64,

View File

@ -3,7 +3,7 @@ use std::cmp::Ordering;
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, HashSet};
use std::str::FromStr; use std::str::FromStr;
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)] #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
enum Card { enum Card {
A, A,
K, K,
@ -20,7 +20,7 @@ enum Card {
C2, C2,
} }
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)] #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
enum Part2Card { enum Part2Card {
A, A,
K, K,
@ -77,7 +77,7 @@ impl FromStr for Card {
} }
} }
#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)] #[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
enum HandKinds { enum HandKinds {
FiveAlike, FiveAlike,
FourAlike, FourAlike,
@ -88,7 +88,7 @@ enum HandKinds {
HighCard, HighCard,
} }
#[derive(Debug, Clone)] #[derive(Clone)]
struct Hand { struct Hand {
bid: u64, bid: u64,
cards: [Card; 5], cards: [Card; 5],
@ -123,10 +123,7 @@ impl Ord for Hand {
} else if self.cards[4] != other.cards[4] { } else if self.cards[4] != other.cards[4] {
self.cards[4].cmp(&other.cards[4]) self.cards[4].cmp(&other.cards[4])
} else { } else {
panic!( panic!("could not sort hand")
"could not sort hand {:?} with {:?}",
self.cards, other.cards
)
} }
} else { } else {
self.hand_kind.cmp(&other.hand_kind) self.hand_kind.cmp(&other.hand_kind)
@ -162,10 +159,7 @@ impl Ord for Part2Hand {
} else if self.cards[4] != other.cards[4] { } else if self.cards[4] != other.cards[4] {
self.cards[4].cmp(&other.cards[4]) self.cards[4].cmp(&other.cards[4])
} else { } else {
panic!( panic!("could not sort hand")
"could not sort hand {:?} with {:?}",
self.cards, other.cards
)
} }
} else { } else {
self.hand_kind.cmp(&other.hand_kind) self.hand_kind.cmp(&other.hand_kind)
@ -175,7 +169,7 @@ impl Ord for Part2Hand {
fn get_hand_type<T>(cards: &[T; 5]) -> HandKinds fn get_hand_type<T>(cards: &[T; 5]) -> HandKinds
where where
T: std::fmt::Debug + Eq + PartialEq + PartialOrd + std::hash::Hash, T: Eq + PartialEq + PartialOrd + std::hash::Hash,
{ {
let mut distinct_cards: HashSet<&T> = HashSet::new(); let mut distinct_cards: HashSet<&T> = HashSet::new();
for c in cards.iter() { for c in cards.iter() {
@ -212,14 +206,12 @@ where
4 => HandKinds::OnePair, 4 => HandKinds::OnePair,
5 => HandKinds::HighCard, 5 => HandKinds::HighCard,
_ => panic!( _ => panic!(
"expected to find size 1-5, but instead got {} from line {:?}", "expected to find size 1-5, but instead got {}",
distinct_cards.len(), distinct_cards.len()
cards
), ),
} }
} }
#[derive(Debug)]
struct Part2Hand { struct Part2Hand {
bid: u64, bid: u64,
cards: [Part2Card; 5], cards: [Part2Card; 5],

View File

@ -11,7 +11,7 @@ struct MetalIsland {
start: Step, start: Step,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq)]
enum Pieces { enum Pieces {
Empty, Empty,
Start, Start,

View File

@ -27,7 +27,7 @@ impl Galaxy {
} }
} }
#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[derive(Eq, PartialEq, Copy, Clone)]
struct Coord(usize, usize); struct Coord(usize, usize);
impl Coord { impl Coord {

208
2023/src/day12.rs Normal file
View File

@ -0,0 +1,208 @@
use aoc_runner_derive::{aoc, aoc_generator};
use std::collections::HashMap;
use std::str::FromStr;
type Cache = HashMap<(Vec<Condition>, Vec<usize>), usize>;
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
enum Condition {
Unknown,
Functional,
Damaged,
}
impl FromStr for Condition {
type Err = String;
fn from_str(input: &str) -> Result<Condition, Self::Err> {
match input {
"?" => Ok(Condition::Unknown),
"." => Ok(Condition::Functional),
"#" => Ok(Condition::Damaged),
n @ _ => Err(format!("Unknown character '{}'", n)),
}
}
}
#[derive(Clone)]
struct Spring {
list: Vec<Condition>,
groups: Vec<usize>,
}
#[aoc_generator(day12)]
fn parse(input: &str) -> Vec<Spring> {
input
.lines()
.filter_map(|line| {
if !line.is_empty() {
let parts = line.split(" ").collect::<Vec<&str>>();
let list = parts[0]
.split("")
.filter_map(|e| {
if e.is_empty() {
None
} else {
Condition::from_str(e).ok()
}
})
.collect();
let groups = parts[1]
.split(",")
.map(|e| e.parse::<usize>().unwrap())
.collect();
Some(Spring { list, groups })
} else {
None
}
})
.collect()
}
fn calc_solutions(list: &Vec<Condition>, groups: &Vec<usize>, cache: &mut Cache) -> usize {
if list.is_empty() {
if groups.is_empty() {
return 1;
} else {
return 0;
}
}
match list[0] {
Condition::Functional => calc_solutions(&list[1..].to_vec(), groups, cache),
Condition::Damaged => calc_damaged_solutions(list, groups, cache),
Condition::Unknown => {
calc_solutions(&list[1..].to_vec(), groups, cache)
+ calc_damaged_solutions(list, groups, cache)
}
}
}
fn calc_damaged_solutions(list: &Vec<Condition>, groups: &Vec<usize>, cache: &mut Cache) -> usize {
if let Some(&result) = cache.get(&(list.clone(), groups.clone())) {
return result;
}
if groups.is_empty() {
return 0;
}
if list.len() < groups[0] {
return 0;
}
for i in 0..groups[0] {
if list[i] == Condition::Functional {
return 0;
}
}
if list.len() == groups[0] {
if groups.len() == 1 {
return 1;
}
return 0;
}
if list[groups[0]] == Condition::Damaged {
return 0;
}
let result = calc_solutions(
&list[(groups[0] + 1)..].to_vec(),
&groups[1..].to_vec(),
cache,
);
cache.insert((list.clone(), groups.clone()), result);
result
}
#[aoc(day12, part1)]
fn part1(input: &[Spring]) -> usize {
let mut result: usize = 0;
for src in input.iter() {
let mut cache: Cache = HashMap::new();
result += calc_solutions(&src.list, &src.groups, &mut cache);
}
result
}
#[aoc(day12, part2)]
fn part2(input: &[Spring]) -> usize {
let mut result: usize = 0;
for src in input.iter() {
let mut l: Vec<Condition> = Vec::with_capacity(src.groups.len() * 5 + 5);
let mut g: Vec<usize> = Vec::with_capacity(src.list.len() * 5);
for index in 0..5 {
l.append(&mut src.list.clone());
if index < 4 {
l.push(Condition::Unknown);
}
g.append(&mut src.groups.clone());
}
let mut cache: Cache = HashMap::new();
let s = calc_solutions(&l, &g, &mut cache);
result += s;
}
result
}
#[cfg(test)]
mod tests {
use super::*;
const SAMPLE_DATA: &'static str = r#"???.### 1,1,3
.??..??...?##. 1,1,3
?#?#?#?#?#?#?#? 1,3,1,6
????.#...#... 4,1,1
????.######..#####. 1,6,5
?###???????? 3,2,1
"#;
#[test]
fn sample_data_part1() {
let input = parse(&SAMPLE_DATA);
assert_eq!(part1(&input), 21);
}
#[test]
fn sample_data_3() {
let line1 = Spring {
list: vec![
Condition::Unknown,
Condition::Unknown,
Condition::Unknown,
Condition::Functional,
Condition::Damaged,
Condition::Damaged,
Condition::Damaged,
],
groups: vec![1, 1, 3],
};
assert_eq!(part2(&[line1]), 1);
let line2 = Spring {
list: vec![
Condition::Functional,
Condition::Unknown,
Condition::Unknown,
Condition::Functional,
Condition::Functional,
Condition::Unknown,
Condition::Unknown,
Condition::Functional,
Condition::Functional,
Condition::Functional,
Condition::Unknown,
Condition::Damaged,
Condition::Damaged,
Condition::Functional,
],
groups: vec![1, 1, 3],
};
assert_eq!(part2(&[line2]), 16384);
}
#[test]
fn sample_data_part2() {
let input = parse(&SAMPLE_DATA);
assert_eq!(part2(&input), 525152);
}
}

View File

@ -11,5 +11,6 @@ mod day08;
mod day09; mod day09;
mod day10; mod day10;
mod day11; mod day11;
mod day12;
aoc_lib! { year = 2023 } aoc_lib! { year = 2023 }