mirror of
https://github.com/mx42/aoc2024.rs.git
synced 2026-01-14 13:59:52 +01:00
feat: day 19
This commit is contained in:
@@ -49,8 +49,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
|
|||||||
| [Day 16](./src/bin/16.rs) | `-` | `-` |
|
| [Day 16](./src/bin/16.rs) | `-` | `-` |
|
||||||
| [Day 17](./src/bin/17.rs) | `1.5ms` | `-` |
|
| [Day 17](./src/bin/17.rs) | `1.5ms` | `-` |
|
||||||
| [Day 18](./src/bin/18.rs) | `2.1ms` | `5.0ms` |
|
| [Day 18](./src/bin/18.rs) | `2.1ms` | `5.0ms` |
|
||||||
|
| [Day 19](./src/bin/19.rs) | `21.1ms` | `707.2ms` |
|
||||||
|
|
||||||
**Total: 13275.60ms**
|
**Total: 14003.90ms**
|
||||||
<!--- benchmarking table --->
|
<!--- benchmarking table --->
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
10
data/examples/19.txt
Normal file
10
data/examples/19.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
r, wr, b, g, bwu, rb, gb, br
|
||||||
|
|
||||||
|
brwrr
|
||||||
|
bggr
|
||||||
|
gbbr
|
||||||
|
rrbgbr
|
||||||
|
ubwu
|
||||||
|
bwurrg
|
||||||
|
brgr
|
||||||
|
bbrgwb
|
||||||
127
src/bin/19.rs
Normal file
127
src/bin/19.rs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
advent_of_code::solution!(19);
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
fn is_possible(pat: String, towels: &Vec<String>) -> bool {
|
||||||
|
if towels.contains(&pat) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for towel in towels {
|
||||||
|
if pat.starts_with(towel) {
|
||||||
|
let sub_possible = is_possible((pat[towel.len()..]).to_owned(), towels);
|
||||||
|
if sub_possible {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct State {
|
||||||
|
towels: Vec<String>,
|
||||||
|
simplified: Vec<String>,
|
||||||
|
patterns: Vec<String>,
|
||||||
|
possible_cache: HashMap<String, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplified_towels(towels: Vec<String>) -> Vec<String> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
for t in &towels {
|
||||||
|
let remaining: Vec<String> = towels.clone().into_iter().filter(|t2| t2 != t).collect();
|
||||||
|
if t.len() == 1 || !is_possible(t.clone(), &remaining) {
|
||||||
|
res.push(t.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for State {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(input: &str) -> Result<State, Self::Error> {
|
||||||
|
let mut input: Vec<&str> = input.lines().collect();
|
||||||
|
if input.len() < 3 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let mut towels: Vec<String> = input.remove(0).split(", ").map(String::from).collect();
|
||||||
|
towels.sort_by_key(|t| (t.len(), t.clone()));
|
||||||
|
input.remove(0);
|
||||||
|
Ok(Self {
|
||||||
|
patterns: input.into_iter().map(|s| s.to_owned()).collect(),
|
||||||
|
simplified: simplified_towels(towels.clone()),
|
||||||
|
towels,
|
||||||
|
possible_cache: HashMap::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn is_possible(&self, pat: String) -> bool {
|
||||||
|
is_possible(pat, &self.simplified)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nb_possible(&mut self, pat: String) -> usize {
|
||||||
|
if let Some(cached) = self.possible_cache.get(&pat) {
|
||||||
|
return *cached;
|
||||||
|
}
|
||||||
|
if pat.is_empty() {
|
||||||
|
self.possible_cache.insert(pat, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
let mut res = 0;
|
||||||
|
for towel in &self.towels.clone() {
|
||||||
|
if pat.starts_with(towel) {
|
||||||
|
res += self.nb_possible((pat[towel.len()..]).to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.possible_cache.insert(pat, res);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_possible_patterns_count(&self) -> usize {
|
||||||
|
self.patterns
|
||||||
|
.iter()
|
||||||
|
.filter(|p| self.is_possible(p.to_string()))
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_nb_possible_configurations(&mut self) -> usize {
|
||||||
|
self.patterns
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|p| self.nb_possible(p.to_string()))
|
||||||
|
.sum::<usize>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_one(input: &str) -> Option<usize> {
|
||||||
|
State::try_from(input)
|
||||||
|
.ok()?
|
||||||
|
.get_possible_patterns_count()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_two(input: &str) -> Option<usize> {
|
||||||
|
State::try_from(input)
|
||||||
|
.ok()?
|
||||||
|
.get_nb_possible_configurations()
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_part_one() {
|
||||||
|
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
|
||||||
|
assert_eq!(result, Some(6));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_part_two() {
|
||||||
|
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
|
||||||
|
assert_eq!(result, Some(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user