Day 19 - Linen Layout
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Rust
I figured that Part 2 would want something to do with unique paths, so I tried to generate all paths in Part 1, which took too long. So I then decided to go with dynamic programming. In Part 1, I stored a cache of whether a given state can lead to the solution. In Part 2, I updated it to store how many options are possible from a given state.
https://gitlab.com/bricka/advent-of-code-2024-rust/-/blob/main/src/days/day19.rs?ref_type=heads
The Code
use std::collections::HashMap; use crate::solver::DaySolver; fn parse_input(input: String) -> (Vec<String>, Vec<String>) { let towels = input.lines().take(1).collect::<String>().split(", ").map(|s| s.to_string()).collect(); let designs = input.lines().skip(2).map(|s| s.to_string()).collect(); (towels, designs) } fn how_many_ways(cache: &mut HashMap<String, usize>, towels: &[String], current: String, target: &str) -> usize { if let Some(ways) = cache.get(¤t) { *ways } else if current == target { cache.insert(current.clone(), 1); 1 } else if !target.starts_with(¤t) { cache.insert(current.clone(), 0); 0 } else { let ways = towels.iter() .map(|t| format!("{}{}", current, t)) .map(|next| how_many_ways(cache, towels, next, target)) .sum(); cache.insert(current, ways); ways } } pub struct Day19Solver; impl DaySolver for Day19Solver { fn part1(&self, input: String) -> String { let (towels, designs) = parse_input(input); designs.into_iter() .filter(|d| how_many_ways(&mut HashMap::new(), &towels, "".to_string(), d) > 0) .count() .to_string() } fn part2(&self, input: String) -> String { let (towels, designs) = parse_input(input); designs.into_iter() .map(|d| how_many_ways(&mut HashMap::new(), &towels, "".to_string(), &d)) .sum::<usize>() .to_string() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_part1() { let input = include_str!("../../inputs/test/19"); let solver = Day19Solver {}; assert_eq!("6", solver.part1(input.to_string())); } #[test] fn test_part2() { let input = include_str!("../../inputs/test/19"); let solver = Day19Solver {}; assert_eq!("16", solver.part2(input.to_string())); } }