day 12 part 1 (dirty)
This commit is contained in:
parent
f2b39c456d
commit
68c0f3c3a3
3 changed files with 1330 additions and 205 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
|
||||||
.........#
|
|
||||||
..........
|
|
||||||
.......#..
|
|
||||||
#...#.....
|
|
||||||
|
|
379
src/main.rs
379
src/main.rs
|
@ -1,65 +1,334 @@
|
||||||
use std::{cmp::max, collections::HashSet, io::stdin};
|
use std::{collections::HashMap, io::stdin, ops::Range};
|
||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn arrangements3_inner(
|
||||||
|
// conditions: &str,
|
||||||
|
// start: usize,
|
||||||
|
// groups: &[usize],
|
||||||
|
// cache: &mut Cache,
|
||||||
|
// ranges: &mut Vec<Range<usize>>,
|
||||||
|
// ) -> i64 {
|
||||||
|
// // println!("arrangements3_inner({conditions:?}, {groups:?}, {ranges:?}");
|
||||||
|
// if groups.is_empty() {
|
||||||
|
// let mut s = String::new();
|
||||||
|
// for i in 0..conditions.len() {
|
||||||
|
// if ranges.iter().any(|r| r.contains(&i)) {
|
||||||
|
// s.push('#');
|
||||||
|
// } else {
|
||||||
|
// s.push('.');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// let mut m = true;
|
||||||
|
// for (c, s) in conditions.chars().zip(s.chars()) {
|
||||||
|
// if c == '?' {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if c == s {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// m = false;
|
||||||
|
// }
|
||||||
|
// if m {
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
// // let mut start = ranges.last().unwrap_or(&(0..0usize)).end;
|
||||||
|
// // if start > 0 {
|
||||||
|
// // start += 1;
|
||||||
|
// // }
|
||||||
|
// let w = conditions.len() - start - groups.iter().skip(1).sum::<usize>();
|
||||||
|
// let g = groups[0];
|
||||||
|
// // println!("start={start} w={w} g={g}");
|
||||||
|
// if w < g {
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
// let positions = w - g + 1;
|
||||||
|
// let mut matches = 0;
|
||||||
|
// for i in start..(start + positions) {
|
||||||
|
// ranges.push(i..(i + g));
|
||||||
|
// let new_start = i + g + 1;
|
||||||
|
// let hash_key = format!("{},{:?},{:?}", new_start, &groups[1..], ranges);
|
||||||
|
// if let Some(value) = cache.get(&hash_key) {
|
||||||
|
// println!("cache hit");
|
||||||
|
// matches += value;
|
||||||
|
// } else {
|
||||||
|
// // println!("cache miss");
|
||||||
|
// let a = arrangements3_inner(conditions, new_start, &groups[1..], cache, ranges);
|
||||||
|
// cache.insert(hash_key, a);
|
||||||
|
// // insert into cache here
|
||||||
|
// matches += a;
|
||||||
|
// }
|
||||||
|
// ranges.pop();
|
||||||
|
// }
|
||||||
|
// matches
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type Cache = HashMap<String, i64>;
|
||||||
|
//
|
||||||
|
// fn arrangements3(conditions: &str, groups: &[usize]) -> i64 {
|
||||||
|
// let mut ranges = vec![];
|
||||||
|
// let mut cache: HashMap<String, i64> = HashMap::new();
|
||||||
|
// arrangements3_inner(conditions, 0, groups, &mut cache, &mut ranges)
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn arrangements2_inner(conditions: &str, groups: &[String]) -> i64 {
|
||||||
|
let g = &groups[0];
|
||||||
|
let w = conditions.len() - groups.iter().skip(1).map(|s| s.len()).sum::<usize>();
|
||||||
|
|
||||||
|
// println!(
|
||||||
|
// "{}conditions={conditions} groups={groups:?} w={w} g={g}",
|
||||||
|
// " ".repeat(depth)
|
||||||
|
// );
|
||||||
|
let positions = w - g.len() + 1;
|
||||||
|
// println!("positions={positions}");
|
||||||
|
let mut sum = 0;
|
||||||
|
for i in 0..positions {
|
||||||
|
if !matches(&conditions[i..], g) {
|
||||||
|
// println!("{}i={i} no match", " ".repeat(depth));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if conditions[..i].contains('#') {
|
||||||
|
// println!("{}i={i} found a # somewhere before", " ".repeat(depth));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let after = if (i + g.len()) < conditions.len() {
|
||||||
|
conditions.chars().nth(i + g.len()).unwrap()
|
||||||
|
} else {
|
||||||
|
'.'
|
||||||
|
};
|
||||||
|
if after == '#' {
|
||||||
|
// println!("{}i={i} found a # right after", " ".repeat(depth));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if groups.len() == 1 {
|
||||||
|
if conditions[i + g.len()..].contains('#') {
|
||||||
|
// println!(
|
||||||
|
// "{}i={i} last group, but there are unmatched '#'s after",
|
||||||
|
// " ".repeat(depth)
|
||||||
|
// );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// println!("{}i={i} last group, counting", " ".repeat(depth));
|
||||||
|
sum += 1;
|
||||||
|
} else {
|
||||||
|
// println!("{}i={i}:", " ".repeat(depth));
|
||||||
|
sum += arrangements2_inner(&conditions[i + g.len()..], &groups[1..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arrangements2(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));
|
||||||
|
}
|
||||||
|
arrangements2_inner(conditions, &group_strings)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn arrangements_inner(conditions: &str, groups: &[usize], indent: usize) -> i64 {
|
||||||
|
// println!(
|
||||||
|
// "{}arrangements(conditions: {}, groups: {:?})",
|
||||||
|
// " ".repeat(indent),
|
||||||
|
// conditions,
|
||||||
|
// groups
|
||||||
|
// );
|
||||||
|
// if groups.is_empty() {
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// let g = groups[0];
|
||||||
|
//
|
||||||
|
// // the max width for the 1st group is the length of the conditions string
|
||||||
|
// // minus the minimum width of the rest of the groups
|
||||||
|
// // which would be the length of each group (i.e. each # char) plus 1 (i.e. the .)
|
||||||
|
// let max_width: usize = conditions.len() - (groups.iter().skip(1).map(|n| n + 1).sum::<usize>());
|
||||||
|
// println!(" {}g={g}", " ".repeat(indent));
|
||||||
|
// println!(" {}max_width={max_width}", " ".repeat(indent));
|
||||||
|
//
|
||||||
|
// // if max_width == 1 {
|
||||||
|
// // return 1;
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// // the possible positions for the group would then be the width available
|
||||||
|
// // for it, minus its own width, plus 1
|
||||||
|
// //
|
||||||
|
// // ????.
|
||||||
|
// // ##...
|
||||||
|
// // .##..
|
||||||
|
// // ..##.
|
||||||
|
// // ...##
|
||||||
|
// let positions = max_width - g + 1;
|
||||||
|
//
|
||||||
|
// println!(" {}positions={positions}", " ".repeat(indent));
|
||||||
|
// let mut sum = 0;
|
||||||
|
// for i in 0..positions {
|
||||||
|
// let mut matches = true;
|
||||||
|
// for (j, c) in conditions.chars().take(max_width).enumerate() {
|
||||||
|
// if (i..(i + g)).contains(&j) {
|
||||||
|
// // inside the group, the conditions need to be # or ?
|
||||||
|
// if c == '.' {
|
||||||
|
// println!(
|
||||||
|
// " {}i={i} j={j} found a dot inside the group",
|
||||||
|
// " ".repeat(indent)
|
||||||
|
// );
|
||||||
|
// matches = false;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // outside the group, the conditions need to be . or ?
|
||||||
|
// if c == '#' {
|
||||||
|
// println!(
|
||||||
|
// " {}i={i} j={j} found a # outside the group",
|
||||||
|
// " ".repeat(indent)
|
||||||
|
// );
|
||||||
|
// matches = false;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if !matches {
|
||||||
|
// println!(" {}i={i} no match", " ".repeat(indent));
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// // if (conditions[i..(i + g)]).contains('.') {
|
||||||
|
// // println!(
|
||||||
|
// // " {}i={i} conditions[{i}..{}]({}) contains a dot",
|
||||||
|
// // " ".repeat(indent),
|
||||||
|
// // i + g,
|
||||||
|
// // &conditions[i..(i + g)]
|
||||||
|
// // );
|
||||||
|
// // continue;
|
||||||
|
// // }
|
||||||
|
// // if i + g >= conditions.len() {
|
||||||
|
// // println!(" {}i={i} # nothing left, counts", " ".repeat(indent));
|
||||||
|
// // // nothing left on the right
|
||||||
|
// // sum += 1; // count this arrangement
|
||||||
|
// // continue;
|
||||||
|
// // }
|
||||||
|
// // // after the group, there has to be a '.' or a '?'
|
||||||
|
// // if conditions.chars().nth(i + g) == Some('#') {
|
||||||
|
// // println!(" {}i={i} # found after", " ".repeat(indent));
|
||||||
|
// // continue;
|
||||||
|
// // }
|
||||||
|
// // // before the group, there has to be a '.' or a '?' or the beginning of the string
|
||||||
|
// // if i > 0 && conditions.chars().nth(i - 1) == Some('#') {
|
||||||
|
// // println!(" {}i={i} # found before", " ".repeat(indent));
|
||||||
|
// // continue;
|
||||||
|
// // }
|
||||||
|
// // // // after the group, there needs to be a dot, or the end of the string
|
||||||
|
// // // let valid = match conditions.get(i + g..i + g + 1) {
|
||||||
|
// // // Some(c) => c == ".",
|
||||||
|
// // // None => true,
|
||||||
|
// // // };
|
||||||
|
// // // if !valid {
|
||||||
|
// // // continue;
|
||||||
|
// // // }
|
||||||
|
// if groups.len() == 1 {
|
||||||
|
// println!(" {}i={i} counts", " ".repeat(indent));
|
||||||
|
// sum += 1;
|
||||||
|
// } else {
|
||||||
|
// let a = arrangements_inner(&conditions[(i + g + 1)..], &groups[1..], indent + 1);
|
||||||
|
// sum += a;
|
||||||
|
// println!(" {}returned {a}", " ".repeat(indent),);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// sum
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn arrangements(conditions: &str, groups: &[usize]) -> i64 {
|
||||||
|
// arrangements_inner(conditions, groups, 0)
|
||||||
|
// }
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let mut grid = vec![];
|
// println!("{}", arrangements("???.###", &[1, 1, 3], 0));
|
||||||
let mut galaxies = HashSet::new();
|
// println!("{}", arrangements3(".??.?#??##???.", &[1, 6]));
|
||||||
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() {
|
// print!("{line} ");
|
||||||
let dx = i64::abs(a.0 as i64 - b.0 as i64);
|
let mut split = line.split_whitespace();
|
||||||
let dy = i64::abs(a.1 as i64 - b.1 as i64);
|
let conditions = split.next().unwrap();
|
||||||
// println!("{a:?} -> {b:?} = {}", dx + dy);
|
let groups: Vec<usize> = split
|
||||||
sum += dx + dy;
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.split(',')
|
||||||
|
.map(str::parse)
|
||||||
|
.map_while(Result::ok)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// let conditions = conditions.repeat(5);
|
||||||
|
// let groups = groups.repeat(5);
|
||||||
|
|
||||||
|
// println!("{conditions} {groups:?}");
|
||||||
|
let a = arrangements2(&conditions, &groups);
|
||||||
|
// println!("{a}");
|
||||||
|
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);
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_arrangements2() {
|
||||||
|
// assert_eq!(arrangements2(".??.?#??##???.", &[1, 6]), 5);
|
||||||
|
// assert_eq!(arrangements2("???.###", &[1, 1, 3]), 1);
|
||||||
|
// assert_eq!(arrangements2(".??..??...?##.", &[1, 1, 3]), 4);
|
||||||
|
// assert_eq!(arrangements2("?#?#?#?#?#?#?#?", &[1, 3, 1, 6]), 1);
|
||||||
|
// assert_eq!(arrangements2("????.#...#...", &[4, 1, 1]), 1);
|
||||||
|
// assert_eq!(arrangements2("????.######..#####.", &[1, 6, 5]), 4);
|
||||||
|
// assert_eq!(arrangements2("?###????????", &[3, 2, 1]), 10);
|
||||||
|
assert_eq!(arrangements2("????#?#?..?#?", &[4, 1]), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// fn test_arrangements3() {
|
||||||
|
// assert_eq!(arrangements3(".??.?#??##???.", &[1, 6]), 5);
|
||||||
|
// assert_eq!(arrangements2("???.###", &[1, 1, 3]), 1);
|
||||||
|
// assert_eq!(arrangements2(".??..??...?##.", &[1, 1, 3]), 4);
|
||||||
|
// assert_eq!(arrangements2("?#?#?#?#?#?#?#?", &[1, 3, 1, 6]), 1);
|
||||||
|
// assert_eq!(arrangements2("????.#...#...", &[4, 1, 1]), 1);
|
||||||
|
// assert_eq!(arrangements2("????.######..#####.", &[1, 6, 5]), 4);
|
||||||
|
// assert_eq!(arrangements2("?###????????", &[3, 2, 1]), 10);
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches() {
|
||||||
|
assert!(matches("?", "#"));
|
||||||
|
assert!(matches("?", "."));
|
||||||
|
assert!(matches("#", "#"));
|
||||||
|
assert!(matches(".", "."));
|
||||||
|
assert!(!matches("#", "."));
|
||||||
|
assert!(!matches(".", "#"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue