Merge branch 'day-12'

This commit is contained in:
Kristofers Solo 2023-12-16 20:30:32 +02:00
commit 4673bdf9b4
3 changed files with 95 additions and 240 deletions

45
2023/Cargo.lock generated
View File

@ -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",

View File

@ -7,3 +7,5 @@ edition = "2021"
[dependencies]
color-eyre.workspace = true
itertools.workspace = true
nom.workspace = true

View File

@ -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(())
}
}