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
4673bdf9b4
45
2023/Cargo.lock
generated
45
2023/Cargo.lock
generated
@ -97,9 +97,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
@ -108,22 +108,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.15"
|
||||
version = "0.9.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@ -217,6 +216,8 @@ name = "day-12"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"itertools",
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -227,9 +228,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.9"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd"
|
||||
checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799"
|
||||
dependencies = [
|
||||
"indenter",
|
||||
"once_cell",
|
||||
@ -276,9 +277,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
version = "0.2.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
@ -344,9 +345,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
@ -404,12 +405,6 @@ version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
@ -421,9 +416,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
version = "2.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -432,18 +427,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||
checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.50"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||
checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@ -7,3 +7,5 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
color-eyre.workspace = true
|
||||
itertools.workspace = true
|
||||
nom.workspace = true
|
||||
|
||||
@ -1,125 +1,89 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use color_eyre::Result;
|
||||
use itertools::{repeat_n, Itertools};
|
||||
use nom::{
|
||||
bytes::complete::{is_a, tag},
|
||||
character::complete::{self, space1},
|
||||
multi::separated_list1,
|
||||
sequence::separated_pair,
|
||||
IResult,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
enum SpringStatus {
|
||||
Operational,
|
||||
Unknown,
|
||||
Damaged,
|
||||
#[derive(Debug)]
|
||||
struct Puzzle {
|
||||
spaces_to_fill: usize,
|
||||
line: String,
|
||||
batches: Vec<usize>,
|
||||
}
|
||||
|
||||
#[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 Puzzle {
|
||||
fn generate_permutations(&self) -> impl Iterator<Item = String> {
|
||||
repeat_n([".", "#"].into_iter(), self.spaces_to_fill)
|
||||
.multi_cartesian_product()
|
||||
.map(|x| x.join(""))
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
fn check_option(&self, option: &str) -> bool {
|
||||
let mut option_iter = option.chars();
|
||||
let filled_option = self
|
||||
.line
|
||||
.chars()
|
||||
.map(|ch| match ch {
|
||||
'?' => SpringStatus::Unknown,
|
||||
'.' => SpringStatus::Operational,
|
||||
'#' => SpringStatus::Damaged,
|
||||
_ => unreachable!(),
|
||||
'?' => option_iter
|
||||
.next()
|
||||
.expect("Should have a len similar to needed gaps"),
|
||||
value => value,
|
||||
})
|
||||
.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,
|
||||
})
|
||||
.collect::<String>();
|
||||
let counts = filled_option
|
||||
.chars()
|
||||
.group_by(|ch| ch == &'#')
|
||||
.into_iter()
|
||||
.filter_map(|(is_hashes, group)| is_hashes.then_some(group.into_iter().count()))
|
||||
.collect_vec();
|
||||
&self.batches[..] == &counts[..]
|
||||
}
|
||||
|
||||
fn possible_solution_count(&self) -> usize {
|
||||
let count = self
|
||||
.generate_permutations()
|
||||
.filter(|option| self.check_option(option))
|
||||
.count();
|
||||
count
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_line(input: &str) -> IResult<&str, Puzzle> {
|
||||
let (input, (line, batches)) = separated_pair(
|
||||
is_a("?.#"),
|
||||
space1,
|
||||
separated_list1(tag(","), complete::u32),
|
||||
)(input)?;
|
||||
let expanded_line = std::iter::repeat(line).take(5).join("?");
|
||||
let spaces_to_fill = expanded_line.chars().filter(|ch| ch != &'?').count();
|
||||
Ok((
|
||||
input,
|
||||
Puzzle {
|
||||
spaces_to_fill,
|
||||
line: expanded_line,
|
||||
batches: std::iter::repeat(batches)
|
||||
.take(5)
|
||||
.flatten()
|
||||
.map(|x| x as usize)
|
||||
.collect(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
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())
|
||||
let puzzles = input
|
||||
.lines()
|
||||
.map(parse_line)
|
||||
.collect::<std::result::Result<Vec<(&str, Puzzle)>, nom::Err<nom::error::Error<&str>>>>()
|
||||
.expect("Parsisng to succeed");
|
||||
let sum = puzzles
|
||||
.iter()
|
||||
.map(|(_, puzzle)| puzzle.possible_solution_count());
|
||||
Ok(sum.sum())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -137,110 +101,4 @@ mod tests {
|
||||
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