Compare commits
3 commits
f2b39c456d
...
f458030577
Author | SHA1 | Date | |
---|---|---|---|
f458030577 | |||
92b37dbfce | |||
68c0f3c3a3 |
3 changed files with 1110 additions and 201 deletions
16
example.txt
16
example.txt
|
@ -1,10 +1,6 @@
|
||||||
...#......
|
???.### 1,1,3
|
||||||
.......#..
|
.??..??...?##. 1,1,3
|
||||||
#.........
|
?#?#?#?#?#?#?#? 1,3,1,6
|
||||||
..........
|
????.#...#... 4,1,1
|
||||||
......#...
|
????.######..#####. 1,6,5
|
||||||
.#........
|
?###???????? 3,2,1
|
||||||
.........#
|
|
||||||
..........
|
|
||||||
.......#..
|
|
||||||
#...#.....
|
|
||||||
|
|
163
src/main.rs
163
src/main.rs
|
@ -1,65 +1,118 @@
|
||||||
use std::{cmp::max, collections::HashSet, io::stdin};
|
use std::{collections::HashMap, io::stdin};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::Result;
|
||||||
|
|
||||||
|
fn matches(conditions: &str, group: &str) -> bool {
|
||||||
|
for (g, c) in group.chars().zip(conditions.chars()) {
|
||||||
|
if c == '?' {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if g == c {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cache = HashMap<String, i64>;
|
||||||
|
|
||||||
|
fn arrangements_inner(conditions: &str, groups: &[String], cache: &mut Cache) -> i64 {
|
||||||
|
let g = &groups[0];
|
||||||
|
let w = conditions.len() - groups.iter().skip(1).map(|s| s.len()).sum::<usize>();
|
||||||
|
|
||||||
|
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 {
|
||||||
|
'.'
|
||||||
|
};
|
||||||
|
if after == '#' {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arrangements(conditions: &str, groups: &[usize]) -> i64 {
|
||||||
|
let mut group_strings = vec![];
|
||||||
|
group_strings.push("#".repeat(groups[0]).to_owned());
|
||||||
|
for g in groups.iter().skip(1) {
|
||||||
|
group_strings.push(".".to_owned() + &"#".to_owned().repeat(*g));
|
||||||
|
}
|
||||||
|
let mut cache: Cache = Cache::new();
|
||||||
|
arrangements_inner(conditions, &group_strings, &mut cache)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let mut grid = vec![];
|
|
||||||
let mut galaxies = HashSet::new();
|
|
||||||
let mut occupied_columns = HashSet::new();
|
|
||||||
let mut occupied_rows = HashSet::new();
|
|
||||||
let mut max_x = 0;
|
|
||||||
let mut max_y = 0;
|
|
||||||
for (y, line) in stdin().lines().map_while(Result::ok).enumerate() {
|
|
||||||
let cells: Vec<char> = line.chars().collect();
|
|
||||||
max_y = max(max_y, y);
|
|
||||||
for (x, c) in cells.iter().enumerate() {
|
|
||||||
max_x = max(max_x, x);
|
|
||||||
if *c == '#' {
|
|
||||||
galaxies.insert((x, y));
|
|
||||||
occupied_columns.insert(x);
|
|
||||||
occupied_rows.insert(y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
grid.push(cells);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut empty_columns: Vec<usize> = HashSet::from_iter(0..max_x)
|
|
||||||
.difference(&occupied_columns)
|
|
||||||
.copied()
|
|
||||||
.collect();
|
|
||||||
let mut empty_rows: Vec<usize> = HashSet::from_iter(0..max_y)
|
|
||||||
.difference(&occupied_rows)
|
|
||||||
.copied()
|
|
||||||
.collect();
|
|
||||||
empty_columns.sort();
|
|
||||||
empty_rows.sort();
|
|
||||||
|
|
||||||
let mut expanded_galaxies = HashSet::new();
|
|
||||||
let expansion = 1_000_000;
|
|
||||||
for (x, y) in galaxies.into_iter() {
|
|
||||||
let Err(col) = empty_columns.binary_search(&x) else {
|
|
||||||
bail!("x={x} found in empty columns");
|
|
||||||
};
|
|
||||||
let new_x = x + col * (expansion - 1);
|
|
||||||
let Err(row) = empty_rows.binary_search(&y) else {
|
|
||||||
bail!("y={y} found in empty rows");
|
|
||||||
};
|
|
||||||
let new_y = y + row * (expansion - 1);
|
|
||||||
expanded_galaxies.insert((new_x, new_y));
|
|
||||||
}
|
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
for a in expanded_galaxies.iter() {
|
for line in stdin().lines().map_while(Result::ok) {
|
||||||
for b in expanded_galaxies.iter() {
|
let mut split = line.split_whitespace();
|
||||||
let dx = i64::abs(a.0 as i64 - b.0 as i64);
|
let conditions = split.next().unwrap();
|
||||||
let dy = i64::abs(a.1 as i64 - b.1 as i64);
|
let groups: Vec<usize> = split
|
||||||
// println!("{a:?} -> {b:?} = {}", dx + dy);
|
.next()
|
||||||
sum += dx + dy;
|
.unwrap()
|
||||||
|
.split(',')
|
||||||
|
.map(str::parse)
|
||||||
|
.map_while(Result::ok)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let conditions = [conditions].repeat(5).join("?");
|
||||||
|
let groups = groups.repeat(5);
|
||||||
|
|
||||||
|
let a = arrangements(&conditions, &groups);
|
||||||
|
sum += a;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
sum /= 2;
|
|
||||||
println!("{sum}");
|
println!("{sum}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {}
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_arrangements() {
|
||||||
|
assert_eq!(arrangements(".??.?#??##???.", &[1, 6]), 5);
|
||||||
|
assert_eq!(arrangements("???.###", &[1, 1, 3]), 1);
|
||||||
|
assert_eq!(arrangements(".??..??...?##.", &[1, 1, 3]), 4);
|
||||||
|
assert_eq!(arrangements("?#?#?#?#?#?#?#?", &[1, 3, 1, 6]), 1);
|
||||||
|
assert_eq!(arrangements("????.#...#...", &[4, 1, 1]), 1);
|
||||||
|
assert_eq!(arrangements("????.######..#####.", &[1, 6, 5]), 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(".", "#"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue