mirror of
https://github.com/kristoferssolo/Advent-of-Code.git
synced 2025-10-21 18:00:35 +00:00
Merge branch 'day-12'
This commit is contained in:
commit
1e9accd5d2
6
2023/Cargo.lock
generated
6
2023/Cargo.lock
generated
@ -204,6 +204,12 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"itertools",
|
||||
|
||||
[[package]]
|
||||
name = "day-12"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
9
2023/day-12/Cargo.toml
Normal file
9
2023/day-12/Cargo.toml
Normal 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
1000
2023/day-12/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
9
2023/day-12/src/bin/part1.rs
Normal file
9
2023/day-12/src/bin/part1.rs
Normal 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(())
|
||||
}
|
||||
9
2023/day-12/src/bin/part2.rs
Normal file
9
2023/day-12/src/bin/part2.rs
Normal 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
2
2023/day-12/src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod part1;
|
||||
pub mod part2;
|
||||
196
2023/day-12/src/part1.rs
Normal file
196
2023/day-12/src/part1.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
246
2023/day-12/src/part2.rs
Normal file
246
2023/day-12/src/part2.rs
Normal file
@ -0,0 +1,246 @@
|
||||
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<_>>();
|
||||
|
||||
let mut new_status = status.clone();
|
||||
let mut new_condition = condition.clone();
|
||||
|
||||
for _ in 0..4 {
|
||||
new_status.push(SpringStatus::Unknown);
|
||||
new_status.extend(status.clone().iter());
|
||||
new_condition.extend(condition.clone().iter());
|
||||
}
|
||||
|
||||
dbg!(&new_status, &new_condition);
|
||||
|
||||
Ok(Self {
|
||||
status: new_status,
|
||||
condition: new_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!(525152, 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,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Operational,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Operational,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Operational,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Unknown,
|
||||
SpringStatus::Operational,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Damaged,
|
||||
SpringStatus::Damaged,
|
||||
],
|
||||
spring.status
|
||||
);
|
||||
assert_eq!(
|
||||
vec![1, 1, 3, 1, 1, 3, 1, 1, 3, 1, 1, 3, 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!(
|
||||
16384,
|
||||
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!(
|
||||
16,
|
||||
Spring::from_str("????.#...#... 4,1,1")?.arragement_amount()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_line_5() -> Result<()> {
|
||||
assert_eq!(
|
||||
2500,
|
||||
Spring::from_str("????.######..#####. 1,6,5")?.arragement_amount()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_line_6() -> Result<()> {
|
||||
assert_eq!(
|
||||
506250,
|
||||
Spring::from_str("?###???????? 3,2,1")?.arragement_amount()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user