day 13 part 1

This commit is contained in:
Andy Teijelo 2023-12-15 19:51:58 -05:00
parent f458030577
commit 50f217eea0
3 changed files with 1455 additions and 1097 deletions

View file

@ -1,6 +1,15 @@
???.### 1,1,3 #.##..##.
.??..??...?##. 1,1,3 ..#.##.#.
?#?#?#?#?#?#?#? 1,3,1,6 ##......#
????.#...#... 4,1,1 ##......#
????.######..#####. 1,6,5 ..#.##.#.
?###???????? 3,2,1 ..##..##.
#.#.##.#.
#...##..#
#....#..#
..##..###
#####.##.
#####.##.
..##..###
#....#..#

2367
input.txt

File diff suppressed because it is too large Load diff

View file

@ -1,90 +1,84 @@
use std::{collections::HashMap, io::stdin}; use std::{collections::HashSet, io::stdin, vec};
use anyhow::Result; use anyhow::Result;
fn matches(conditions: &str, group: &str) -> bool { fn mirror_points(line: &[char]) -> Vec<usize> {
for (g, c) in group.chars().zip(conditions.chars()) { let mut result = vec![];
if c == '?' { for i in 1..line.len() {
let mut mirror = true;
for j in 0..i {
if i + j >= line.len() {
continue; continue;
} }
if g == c { if line[i - j - 1] != line[i + j] {
continue; mirror = false;
} }
return false;
} }
true if mirror {
result.push(i);
}
}
result
} }
type Cache = HashMap<String, i64>; fn vertical_mirror_points(grid: &Vec<Vec<char>>) -> HashSet<usize> {
let mut s: HashSet<usize> = HashSet::new();
fn arrangements_inner(conditions: &str, groups: &[String], cache: &mut Cache) -> i64 { for row in grid {
let g = &groups[0]; let n: HashSet<usize> = mirror_points(row).iter().copied().collect();
let w = conditions.len() - groups.iter().skip(1).map(|s| s.len()).sum::<usize>(); if s.is_empty() {
s = n;
let positions = w - g.len() + 1;
let mut sum = 0;
for i in 0..positions {
if !matches(&conditions[i..], g) {
continue;
}
if conditions[..i].contains('#') {
continue;
}
let after = if (i + g.len()) < conditions.len() {
conditions.chars().nth(i + g.len()).unwrap()
} else { } else {
'.' s = s.intersection(&n).cloned().collect();
}; if s.is_empty() {
if after == '#' { return s;
continue;
}
if groups.len() == 1 {
if conditions[i + g.len()..].contains('#') {
continue;
}
sum += 1;
} else {
let cache_key = format!("{},{:?}", &conditions[i + g.len()..], &groups[1..]);
if let Some(v) = cache.get(&cache_key) {
sum += v;
} else {
let a = arrangements_inner(&conditions[i + g.len()..], &groups[1..], cache);
cache.insert(cache_key, a);
sum += a;
} }
} }
} }
sum s
} }
fn arrangements(conditions: &str, groups: &[usize]) -> i64 { fn horizontal_mirror_points(grid: &Vec<Vec<char>>) -> HashSet<usize> {
let mut group_strings = vec![]; let mut s: HashSet<usize> = HashSet::new();
group_strings.push("#".repeat(groups[0]).to_owned()); for x in 0..grid[0].len() {
for g in groups.iter().skip(1) { let mut column = vec![];
group_strings.push(".".to_owned() + &"#".to_owned().repeat(*g)); for row in grid {
column.push(row[x]);
} }
let mut cache: Cache = Cache::new(); let n: HashSet<usize> = mirror_points(&column).iter().copied().collect();
arrangements_inner(conditions, &group_strings, &mut cache) if s.is_empty() {
s = n;
} else {
s = s.intersection(&n).cloned().collect();
if s.is_empty() {
return s;
} }
}
}
s
}
type Grid = Vec<Vec<char>>;
fn main() -> Result<()> { fn main() -> Result<()> {
let mut sum = 0; let mut grids: Vec<Grid> = vec![];
grids.push(vec![]);
for line in stdin().lines().map_while(Result::ok) { for line in stdin().lines().map_while(Result::ok) {
let mut split = line.split_whitespace(); println!("{line}");
let conditions = split.next().unwrap(); if line.is_empty() {
let groups: Vec<usize> = split grids.push(vec![]);
.next() continue;
.unwrap() }
.split(',') grids.last_mut().unwrap().push(line.chars().collect());
.map(str::parse) }
.map_while(Result::ok) let mut sum = 0;
.collect(); for (i, grid) in grids.iter().enumerate() {
for v in vertical_mirror_points(grid) {
let conditions = [conditions].repeat(5).join("?"); println!("grid {i}: v = {v}");
let groups = groups.repeat(5); sum += v;
}
let a = arrangements(&conditions, &groups); for h in horizontal_mirror_points(grid) {
sum += a; println!("grid {i}: h = {h}");
sum += 100 * h;
}
} }
println!("{sum}"); println!("{sum}");
Ok(()) Ok(())
@ -95,24 +89,12 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
fn test_arrangements() { fn test_mirror_points() {
assert_eq!(arrangements(".??.?#??##???.", &[1, 6]), 5); let chars: Vec<char> = "#.##..##.".chars().collect();
assert_eq!(arrangements("???.###", &[1, 1, 3]), 1); assert_eq!(mirror_points(&chars), vec![5, 7]);
assert_eq!(arrangements(".??..??...?##.", &[1, 1, 3]), 4); let chars: Vec<char> = "#.##..#".chars().collect();
assert_eq!(arrangements("?#?#?#?#?#?#?#?", &[1, 3, 1, 6]), 1); assert_eq!(mirror_points(&chars), vec![5]);
assert_eq!(arrangements("????.#...#...", &[4, 1, 1]), 1); let chars: Vec<char> = ".#.##".chars().collect();
assert_eq!(arrangements("????.######..#####.", &[1, 6, 5]), 4); assert_eq!(mirror_points(&chars), vec![4]);
assert_eq!(arrangements("?###????????", &[3, 2, 1]), 10);
assert_eq!(arrangements("????#?#?..?#?", &[4, 1]), 2);
}
#[test]
fn test_matches() {
assert!(matches("?", "#"));
assert!(matches("?", "."));
assert!(matches("#", "#"));
assert!(matches(".", "."));
assert!(!matches("#", "."));
assert!(!matches(".", "#"));
} }
} }