day 12 part 1

This commit is contained in:
Kristofers Solo 2023-12-12 12:04:55 +02:00
parent 605037250c
commit 14893c5d01
8 changed files with 1251 additions and 0 deletions

7
2023/Cargo.lock generated
View File

@ -198,6 +198,13 @@ dependencies = [
"itertools",
]
[[package]]
name = "day-12"
version = "0.1.0"
dependencies = [
"color-eyre",
]
[[package]]
name = "either"
version = "1.9.0"

9
2023/day-12/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "day-12"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
color-eyre.workspace = true

1000
2023/day-12/input.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
use color_eyre::Result;
use day_12::part1::process;
fn main() -> Result<()> {
let file = include_str!("../../input.txt");
let result = process(file)?;
println!("{}", result);
Ok(())
}

View File

@ -0,0 +1,9 @@
use color_eyre::Result;
use day_12::part2::process;
fn main() -> Result<()> {
let file = include_str!("../../input.txt");
let result = process(file)?;
println!("{}", result);
Ok(())
}

2
2023/day-12/src/lib.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod part1;
pub mod part2;

196
2023/day-12/src/part1.rs Normal file
View File

@ -0,0 +1,196 @@
use std::str::FromStr;
use color_eyre::Result;
#[derive(Debug, Clone, Copy, PartialEq)]
enum SpringStatus {
Operational,
Unknown,
Damaged,
}
#[derive(Debug, Clone, PartialEq, Default)]
struct Spring {
status: Vec<SpringStatus>,
condition: Vec<usize>,
}
impl Spring {
fn arragement_amount(&self) -> usize {
let mut combinations = vec![vec![]];
for status in &self.status {
let mut new_combinations = Vec::new();
for combination in &combinations {
match status {
SpringStatus::Operational => {
let mut new_combination = combination.clone();
new_combination.push(*status);
new_combinations.push(new_combination);
}
SpringStatus::Unknown => {
let mut new_combination = combination.clone();
new_combination.push(SpringStatus::Operational);
new_combinations.push(new_combination);
let mut new_combination = combination.clone();
new_combination.push(SpringStatus::Damaged);
new_combinations.push(new_combination);
}
SpringStatus::Damaged => {
let mut new_combination = combination.clone();
new_combination.push(*status);
new_combinations.push(new_combination);
}
}
}
combinations = new_combinations;
}
let combinations = combinations
.iter()
.map(|combination| {
let mut combination_status: Vec<usize> = Vec::new();
let mut count = 0;
combination.iter().for_each(|status| {
match status {
SpringStatus::Operational => {
if count > 0 {
combination_status.push(count);
}
count = 0;
}
SpringStatus::Damaged => count += 1,
SpringStatus::Unknown => unimplemented!("Should not happen"),
};
});
if count > 0 {
combination_status.push(count);
}
combination_status
})
.filter(|status| status == &self.condition);
combinations.count()
}
}
impl FromStr for Spring {
type Err = color_eyre::Report;
fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
let line = s.split_whitespace().collect::<Vec<_>>();
let status = line
.first()
.unwrap()
.chars()
.map(|ch| match ch {
'?' => SpringStatus::Unknown,
'.' => SpringStatus::Operational,
'#' => SpringStatus::Damaged,
_ => unreachable!(),
})
.collect::<Vec<_>>();
let condition = line
.last()
.unwrap()
.split(',')
.map(|s| s.parse::<usize>().unwrap())
.collect::<Vec<_>>();
Ok(Self { status, condition })
}
}
pub fn process(input: &str) -> Result<usize> {
let springs = input.lines().map(|line| {
Spring::from_str(line)
.unwrap_or_default()
.arragement_amount()
});
Ok(springs.sum())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_process() -> Result<()> {
let input = "???.### 1,1,3
.??..??...?##. 1,1,3
?#?#?#?#?#?#?#? 1,3,1,6
????.#...#... 4,1,1
????.######..#####. 1,6,5
?###???????? 3,2,1";
assert_eq!(21, process(input)?);
Ok(())
}
#[test]
fn test_from_str() -> Result<()> {
let input = "???.### 1,1,3";
let spring = Spring::from_str(input)?;
assert_eq!(
vec![
SpringStatus::Unknown,
SpringStatus::Unknown,
SpringStatus::Unknown,
SpringStatus::Operational,
SpringStatus::Damaged,
SpringStatus::Damaged,
SpringStatus::Damaged
],
spring.status
);
assert_eq!(vec![1, 1, 3], spring.condition);
Ok(())
}
#[test]
fn test_line_1() -> Result<()> {
assert_eq!(1, Spring::from_str("???.### 1,1,3")?.arragement_amount());
Ok(())
}
#[test]
fn test_line_2() -> Result<()> {
assert_eq!(
4,
Spring::from_str(".??..??...?##. 1,1,3")?.arragement_amount()
);
Ok(())
}
#[test]
fn test_line_3() -> Result<()> {
assert_eq!(
1,
Spring::from_str("?#?#?#?#?#?#?#? 1,3,1,6")?.arragement_amount()
);
Ok(())
}
#[test]
fn test_line_4() -> Result<()> {
assert_eq!(
1,
Spring::from_str("????.#...#... 4,1,1")?.arragement_amount()
);
Ok(())
}
#[test]
fn test_line_5() -> Result<()> {
assert_eq!(
4,
Spring::from_str("????.######..#####. 1,6,5")?.arragement_amount()
);
Ok(())
}
#[test]
fn test_line_6() -> Result<()> {
assert_eq!(
10,
Spring::from_str("?###???????? 3,2,1")?.arragement_amount()
);
Ok(())
}
}

19
2023/day-12/src/part2.rs Normal file
View File

@ -0,0 +1,19 @@
use color_eyre::Result;
pub fn process(input: &str) -> Result<usize> {
todo!("day xx - part 2");
Ok(0)
}
// #[cfg(test)]
// mod tests {
// use super::*;
//
// #[test]
// fn test_process() -> Result<()> {
// let input = "";
// todo!("haven't built test yet");
// assert_eq!(0, process(input)?);
// Ok(())
// }
// }