Day 12
This commit is contained in:
parent
4df00cc74d
commit
1bc006c82e
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,143 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
type Cache = HashMap<(usize, u32, usize), u64>;
|
||||||
|
|
||||||
|
fn try_get_consume(
|
||||||
|
remaining_str: &[u8],
|
||||||
|
curr_run: u32,
|
||||||
|
remaining_spec: &[u32],
|
||||||
|
cache: &mut Cache,
|
||||||
|
) -> u64 {
|
||||||
|
let cache_key = (remaining_str.len(), curr_run, remaining_spec.len());
|
||||||
|
if cache.contains_key(&cache_key) {
|
||||||
|
return *cache.get(&(cache_key)).unwrap();
|
||||||
|
}
|
||||||
|
let result = try_consume(remaining_str, curr_run, remaining_spec, cache);
|
||||||
|
cache.insert(cache_key, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
fn try_consume(
|
||||||
|
remaining_str: &[u8],
|
||||||
|
curr_run: u32,
|
||||||
|
remaining_spec: &[u32],
|
||||||
|
cache: &mut Cache,
|
||||||
|
) -> u64 {
|
||||||
|
if !remaining_spec.is_empty()
|
||||||
|
&& (remaining_spec.iter().sum::<u32>() + remaining_spec.len() as u32 - 1)
|
||||||
|
> (remaining_str.len() as u32 + curr_run)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if remaining_str.is_empty() {
|
||||||
|
if curr_run != 0 {
|
||||||
|
if remaining_spec.len() != 1 || curr_run != remaining_spec[0] {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// No current run, check that the remaining spec is empty.
|
||||||
|
if remaining_spec.is_empty() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if remaining_spec.is_empty() && curr_run > 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
match remaining_str[0] {
|
||||||
|
b'.' => {
|
||||||
|
if curr_run == 0 {
|
||||||
|
return try_get_consume(&remaining_str[1..], 0, &remaining_spec, cache);
|
||||||
|
} else if curr_run == remaining_spec[0] {
|
||||||
|
return try_get_consume(&remaining_str[1..], 0, &remaining_spec[1..], cache);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b'#' => {
|
||||||
|
return try_get_consume(&remaining_str[1..], curr_run + 1, remaining_spec, cache);
|
||||||
|
}
|
||||||
|
b'?' => {
|
||||||
|
if remaining_spec.is_empty() {
|
||||||
|
// This must be a .
|
||||||
|
return try_get_consume(&remaining_str[1..], 0, &remaining_spec, cache);
|
||||||
|
} else if curr_run == remaining_spec[0] {
|
||||||
|
// This must be a .
|
||||||
|
return try_get_consume(&remaining_str[1..], 0, &remaining_spec[1..], cache);
|
||||||
|
} else if curr_run > 0 {
|
||||||
|
// This must be a #
|
||||||
|
return try_get_consume(&remaining_str[1..], curr_run + 1, &remaining_spec, cache);
|
||||||
|
} else {
|
||||||
|
// Try both
|
||||||
|
let dot_cnt = try_get_consume(&remaining_str[1..], 0, &remaining_spec, cache);
|
||||||
|
let hash_cnt = try_get_consume(&remaining_str[1..], 1, &remaining_spec, cache);
|
||||||
|
|
||||||
|
/*
|
||||||
|
println!(
|
||||||
|
"String: {:?}\nSpec: {:?}\nDot: {}, Hash: {}",
|
||||||
|
std::str::from_utf8(remaining_str),
|
||||||
|
remaining_spec,
|
||||||
|
dot_cnt,
|
||||||
|
hash_cnt
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
return dot_cnt + hash_cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Unexpected character"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_record(record: &(Vec<u8>, Vec<u32>)) -> u64 {
|
||||||
|
let mut cache: Cache = HashMap::new();
|
||||||
|
try_consume(&record.0, 0, &record.1, &mut cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_records(records: Vec<(Vec<u8>, Vec<u32>)>) -> u64 {
|
||||||
|
records.iter().fold(0, |acc, r| acc + check_record(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sum_arrangements(duplicate: bool) -> u64 {
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
io::stdin().read_to_end(&mut buffer).unwrap();
|
||||||
|
let lines = buffer.split(|c| *c == b'\n');
|
||||||
|
let mut records: Vec<(Vec<u8>, Vec<u32>)> = Vec::new();
|
||||||
|
for line in lines {
|
||||||
|
if line.len() == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut linesplit = line.split(|c| *c == b' ');
|
||||||
|
let springs = linesplit.next().unwrap();
|
||||||
|
let configs: Vec<_> = linesplit
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.split(|c| *c == b',')
|
||||||
|
.map(|n| std::str::from_utf8(n).expect("").parse().expect(""))
|
||||||
|
.collect();
|
||||||
|
let spring_vec = if duplicate {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
for _ in 0..5 {
|
||||||
|
vec.extend_from_slice(springs);
|
||||||
|
vec.push(b'?');
|
||||||
|
}
|
||||||
|
vec.pop();
|
||||||
|
vec
|
||||||
|
} else {
|
||||||
|
springs.to_vec()
|
||||||
|
};
|
||||||
|
let config_vec = if duplicate {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
for _ in 0..5 {
|
||||||
|
vec.extend_from_slice(&configs);
|
||||||
|
}
|
||||||
|
vec
|
||||||
|
} else {
|
||||||
|
configs.to_vec()
|
||||||
|
};
|
||||||
|
records.push((spring_vec, config_vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
check_records(records)
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ use std::env;
|
||||||
mod day1;
|
mod day1;
|
||||||
mod day10;
|
mod day10;
|
||||||
mod day11;
|
mod day11;
|
||||||
|
mod day12;
|
||||||
mod day2;
|
mod day2;
|
||||||
mod day3;
|
mod day3;
|
||||||
mod day4;
|
mod day4;
|
||||||
|
@ -41,6 +42,8 @@ fn main() {
|
||||||
"day10b" => println!("Contains: {}", day10::num_steps().1),
|
"day10b" => println!("Contains: {}", day10::num_steps().1),
|
||||||
"day11a" => println!("Sum: {}", day11::sum_lengths(1)),
|
"day11a" => println!("Sum: {}", day11::sum_lengths(1)),
|
||||||
"day11b" => println!("Sum: {}", day11::sum_lengths(999999)),
|
"day11b" => println!("Sum: {}", day11::sum_lengths(999999)),
|
||||||
|
"day12a" => println!("Sum: {}", day12::sum_arrangements(false)),
|
||||||
|
"day12b" => println!("Sum: {}", day12::sum_arrangements(true)),
|
||||||
_ => println!("Unrecognized day: {}", args[1]),
|
_ => println!("Unrecognized day: {}", args[1]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue