Compare commits
No commits in common. "294c0a8e6231ca4e8a1c1b776673b93a0d12422c" and "397a970a2cf00e4a40d8ffbcc1bc94522c919827" have entirely different histories.
294c0a8e62
...
397a970a2c
10 changed files with 167 additions and 329 deletions
2
.idea/AdventOfCode.iml
generated
2
.idea/AdventOfCode.iml
generated
|
|
@ -5,8 +5,6 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/aoc2023/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/aoc2023/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/shared/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/shared/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
|
|
||||||
16
Cargo.lock
generated
16
Cargo.lock
generated
|
|
@ -23,7 +23,6 @@ dependencies = [
|
||||||
name = "aoc2023"
|
name = "aoc2023"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
|
||||||
"regex",
|
"regex",
|
||||||
"shared",
|
"shared",
|
||||||
"substring",
|
"substring",
|
||||||
|
|
@ -35,21 +34,6 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "either"
|
|
||||||
version = "1.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itertools"
|
|
||||||
version = "0.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.6.4"
|
version = "2.6.4"
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,4 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
shared = { path = "../shared" }
|
shared = { path = "../shared" }
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
substring = "1.4.5"
|
substring = "1.4.5"
|
||||||
itertools = "0.12.0"
|
|
||||||
|
|
@ -133,6 +133,10 @@ struct Rule {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rule {
|
impl Rule {
|
||||||
|
fn new(start: i64, end: i64, offset: i64) -> Rule {
|
||||||
|
Rule {start, end, offset}
|
||||||
|
}
|
||||||
|
|
||||||
fn from_rules(dest: i64, source: i64, range: i64) -> Rule {
|
fn from_rules(dest: i64, source: i64, range: i64) -> Rule {
|
||||||
Rule {start: source, end: source + range - 1, offset: (dest - source)}
|
Rule {start: source, end: source + range - 1, offset: (dest - source)}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,108 +1,193 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::process::abort;
|
||||||
use shared::{Solution, Answer};
|
use shared::{Solution, Answer};
|
||||||
|
|
||||||
pub struct Day10;
|
pub struct Day10;
|
||||||
|
|
||||||
impl Solution for Day10 {
|
impl Solution for Day10 {
|
||||||
fn part_1(&self, input: &str) -> Answer {
|
fn part_1(&self, input: &str) -> Answer {
|
||||||
let mut grid: Vec<Vec<char>> = input.lines().map(|x| x.chars().collect()).collect();
|
let width: i64 = input.lines().next().unwrap().len() as i64;
|
||||||
let full_animal = grid.iter().flatten().position(|&x| x == 'S').unwrap();
|
let grid: Vec<_> = input.lines().collect::<Vec<&str>>().join("").chars().map(Pipes::from).collect();
|
||||||
let animal = (full_animal / grid.len(), full_animal % grid.len());
|
|
||||||
|
|
||||||
replace_animal(&mut grid, &animal);
|
let animal = grid.iter().position(|x| x == &Pipes::Animal).unwrap();
|
||||||
|
|
||||||
let mut pos = animal;
|
let mut seen: HashSet<usize> = HashSet::new();
|
||||||
let mut last: Option<(usize, usize)> = None;
|
|
||||||
|
|
||||||
let mut len_of_loop = 0;
|
let mut len = 2;
|
||||||
|
let mut current ;
|
||||||
|
|
||||||
|
if grid[animal + 1] == Pipes::Horizontal || grid[animal + 1] == Pipes::EtoS || grid[animal + 1] == Pipes::NtoE {
|
||||||
|
current = animal + 1;
|
||||||
|
} else if grid[animal - 1] == Pipes::Horizontal || grid[animal - 1] == Pipes::WtoN || grid[animal - 1] == Pipes::StoW {
|
||||||
|
current = animal - 1;
|
||||||
|
} else { current = animal + width as usize }
|
||||||
|
|
||||||
|
seen.insert(animal);
|
||||||
|
seen.insert(current);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
len_of_loop += 1;
|
let next = traverse(&grid, current as i64, width);
|
||||||
let tmp = pos;
|
if next.is_none() { panic!() }
|
||||||
pos = traverse(&grid[pos.0][pos.1], &pos, &last);
|
let (next1, next2) = next.unwrap();
|
||||||
last = Some(tmp);
|
if seen.contains(&next1) && seen.contains(&next2) {
|
||||||
|
break;
|
||||||
if pos == animal {break}
|
} else if !seen.contains(&next1) {
|
||||||
|
current = next1;
|
||||||
|
seen.insert(next1);
|
||||||
|
len += 1;
|
||||||
|
} else if !seen.contains(&next2) {
|
||||||
|
current = next2;
|
||||||
|
seen.insert(next2);
|
||||||
|
len += 1;
|
||||||
|
} else { panic!() }
|
||||||
}
|
}
|
||||||
|
|
||||||
Answer::from(len_of_loop / 2)
|
Answer::from(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part_2(&self, input: &str) -> Answer {
|
fn part_2(&self, input: &str) -> Answer {
|
||||||
let mut grid: Vec<Vec<char>> = input.lines().map(|x| x.chars().collect()).collect();
|
let width: usize = input.lines().next().unwrap().len();
|
||||||
let full_animal = grid.iter().flatten().position(|&x| x == 'S').unwrap();
|
let mut grid: Vec<_> = input.lines().collect::<Vec<&str>>().join("").chars().map(Pipes::from).collect();
|
||||||
let animal = (full_animal / grid.len(), full_animal % grid.len());
|
|
||||||
|
|
||||||
replace_animal(&mut grid, &animal);
|
let animal = grid.iter().position(|x| x == &Pipes::Animal).unwrap();
|
||||||
|
replace_animal(&mut grid, animal, width);
|
||||||
|
println!("{:?}", grid[animal]);
|
||||||
|
|
||||||
let mut pos = animal;
|
let mut seen: HashSet<usize> = HashSet::new();
|
||||||
let mut last: Option<(usize, usize)> = None;
|
|
||||||
|
|
||||||
let mut in_loop: HashSet<(usize, usize)> = HashSet::new();
|
let mut len = 2;
|
||||||
|
let mut current ;
|
||||||
|
|
||||||
|
if grid[animal + 1] == Pipes::Horizontal || grid[animal + 1] == Pipes::EtoS || grid[animal + 1] == Pipes::NtoE {
|
||||||
|
current = animal + 1;
|
||||||
|
} else if grid[animal - 1] == Pipes::Horizontal || grid[animal - 1] == Pipes::WtoN || grid[animal - 1] == Pipes::StoW {
|
||||||
|
current = animal - 1;
|
||||||
|
} else { current = animal + width as usize }
|
||||||
|
|
||||||
|
seen.insert(animal);
|
||||||
|
seen.insert(current);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
in_loop.insert(pos);
|
let next = traverse(&grid, current as i64, width as i64);
|
||||||
let tmp = pos;
|
if next.is_none() { panic!() }
|
||||||
pos = traverse(&grid[pos.0][pos.1], &pos, &last);
|
let (next1, next2) = next.unwrap();
|
||||||
last = Some(tmp);
|
if seen.contains(&next1) && seen.contains(&next2) {
|
||||||
|
break;
|
||||||
if pos == animal {break}
|
} else if !seen.contains(&next1) {
|
||||||
|
current = next1;
|
||||||
|
seen.insert(next1);
|
||||||
|
len += 1;
|
||||||
|
} else if !seen.contains(&next2) {
|
||||||
|
current = next2;
|
||||||
|
seen.insert(next2);
|
||||||
|
} else { panic!() }
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut total = 0;
|
let mut parity = grid.chunks(width).map(|_| [0].repeat(width)).collect::<Vec<_>>();
|
||||||
|
|
||||||
for (i, line) in grid.iter().enumerate() {
|
for (i, line) in grid.chunks(width).enumerate() {
|
||||||
let mut parity = false;
|
|
||||||
for (j, letter) in line.iter().enumerate() {
|
for (j, letter) in line.iter().enumerate() {
|
||||||
if in_loop.contains(&(i, j)) {
|
if seen.contains(&(width * i + j)) {
|
||||||
if ['|', 'J', 'L'].contains(letter) { parity = !parity }
|
for k in j..width {
|
||||||
continue
|
parity[i][k] += match letter {
|
||||||
}
|
Pipes::Vertical => 2, // using 2 and 1 instead of 1 and .5 for half parity, because integers
|
||||||
else if parity {
|
Pipes::StoW => 1,
|
||||||
total += 1
|
Pipes::NtoE => 1,
|
||||||
|
Pipes::EtoS => -1,
|
||||||
|
Pipes::WtoN => -1,
|
||||||
|
_ => 0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for i in seen {
|
||||||
|
parity[i / width][i % width] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Answer::from(total)
|
let mut enclosed = 0;
|
||||||
|
|
||||||
|
for line in parity {
|
||||||
|
enclosed += line.iter().map(|x| (x % 4 / 2)).map(i32::abs).sum::<i32>();
|
||||||
|
println!("{:?}", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
Answer::from(enclosed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse(pipe: &char, pos: &(usize, usize), last: &Option<(usize, usize)>) -> (usize, usize) {
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
let (offset1, offset2) = match *pipe {
|
enum Pipes {
|
||||||
'|' => ((-1, 0), (1, 0)),
|
Ground,
|
||||||
'-' => ((0, -1), (0, 1)),
|
Vertical,
|
||||||
'J' => ((-1, 0), (0, -1)),
|
Horizontal,
|
||||||
'L' => ((-1, 0), (0, 1)),
|
WtoN,
|
||||||
'F' => ((1, 0), (0, 1)),
|
NtoE,
|
||||||
'7' => ((1, 0), (0, -1)),
|
EtoS,
|
||||||
l => panic!("Invalid letter {l}")
|
StoW,
|
||||||
|
Animal
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<char> for Pipes {
|
||||||
|
fn from(value: char) -> Self {
|
||||||
|
match value {
|
||||||
|
'|' => Pipes::Vertical,
|
||||||
|
'-' => Pipes::Horizontal,
|
||||||
|
'J' => Pipes::WtoN,
|
||||||
|
'L' => Pipes::NtoE,
|
||||||
|
'F' => Pipes::EtoS,
|
||||||
|
'7' => Pipes::StoW,
|
||||||
|
'.' => Pipes::Ground,
|
||||||
|
'S' => Pipes::Animal,
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn traverse(grid: &Vec<Pipes>, current: i64, width: i64) -> Option<(usize, usize)> {
|
||||||
|
let next1 = current + match grid[current as usize] {
|
||||||
|
Pipes::Vertical => -width,
|
||||||
|
Pipes::Horizontal => -1,
|
||||||
|
Pipes::WtoN => -1,
|
||||||
|
Pipes::NtoE => -width,
|
||||||
|
Pipes::EtoS => 1,
|
||||||
|
Pipes::StoW => width,
|
||||||
|
Pipes::Animal => 0,
|
||||||
|
Pipes::Ground => unreachable!()
|
||||||
|
};
|
||||||
|
let next2 = current + match grid[current as usize] {
|
||||||
|
Pipes::Vertical => width,
|
||||||
|
Pipes::Horizontal => 1,
|
||||||
|
Pipes::WtoN => -width,
|
||||||
|
Pipes::NtoE => 1,
|
||||||
|
Pipes::EtoS => width,
|
||||||
|
Pipes::StoW => -1,
|
||||||
|
Pipes::Animal => 0,
|
||||||
|
Pipes::Ground => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let new1 = ((offset1.0 + pos.0 as i32) as usize, (offset1.1 + pos.1 as i32) as usize);
|
// println!("{next1}, {next2}: Current={current}, Width={width}");
|
||||||
let new2 = ((offset2.0 + pos.0 as i32) as usize, (offset2.1 + pos.1 as i32) as usize);
|
|
||||||
|
|
||||||
match last {
|
// if next1 - current == -1 || next1 - current == width || next1 == -1 || next1 == (grid.len() as i64) { return None };
|
||||||
None => new1,
|
// if next2 - current == -1 || next2 - current == width || next2 == -1 || next2 == (grid.len() as i64) { return None };
|
||||||
Some(p) if p == &new1 => new2,
|
|
||||||
Some(p) if p == &new2 => new1,
|
Some((next1 as usize, next2 as usize))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace_animal(grid: &mut Vec<Pipes>, animal: usize, width: usize) {
|
||||||
|
let east = grid[animal + 1] == Pipes::Horizontal || grid[animal + 1] == Pipes::WtoN || grid[animal + 1] == Pipes::StoW;
|
||||||
|
let north = grid[animal - width] == Pipes::Vertical || grid[animal - width] == Pipes::WtoN || grid[animal - width] == Pipes::NtoE;
|
||||||
|
let west = grid[animal - 1] == Pipes::Horizontal || grid[animal - 1] == Pipes::WtoN || grid[animal - 1] == Pipes::StoW;
|
||||||
|
let south = grid[animal + width] == Pipes::Vertical || grid[animal + width] == Pipes::StoW || grid[animal + width] == Pipes::EtoS;
|
||||||
|
|
||||||
|
match (east, north, south, west) {
|
||||||
|
(false, false, true, true) => grid[animal] = Pipes::StoW,
|
||||||
|
(false, true, true, false) => grid[animal] = Pipes::Vertical,
|
||||||
|
(true, true, false, false) => grid[animal] = Pipes::NtoE,
|
||||||
|
(false, true, false, true) => grid[animal] = Pipes::WtoN,
|
||||||
|
(true, false, true, false) => grid[animal] = Pipes::EtoS,
|
||||||
|
(true, false, false, true) => grid[animal] = Pipes::Horizontal,
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_animal(grid: &mut Vec<Vec<char>>, pos: &(usize, usize)) {
|
|
||||||
let left = match grid.get(pos.0) { Some(x) => x.get((pos.1 as i32 - 1) as usize), _ => None};
|
|
||||||
let right = match grid.get(pos.0) { Some(x) => x.get(pos.1 + 1), _ => None};
|
|
||||||
let top = match grid.get((pos.0 as i32 - 1) as usize) { Some(x) => x.get(pos.1), _ => None};
|
|
||||||
let bottom = match grid.get(pos.0 + 1) { Some(x) => x.get(pos.1), _ => None};
|
|
||||||
|
|
||||||
grid[pos.0][pos.1] = match (left, right, top, bottom) {
|
|
||||||
(Some(x), Some(y), _, _) if ['-', 'L', 'F'].contains(x) && ['-', 'J', '7'].contains(y) => '-',
|
|
||||||
(Some(x), _, Some(y), _) if ['-', 'L', 'F'].contains(x) && ['|', '7', 'F'].contains(y) => 'J',
|
|
||||||
(Some(x), _, _, Some(y)) if ['-', 'L', 'F'].contains(x) && ['|', 'J', 'L'].contains(y) => '7',
|
|
||||||
(_, Some(x), Some(y), _) if ['-', 'J', '7'].contains(x) && ['|', '7', 'F'].contains(y) => 'L',
|
|
||||||
(_, Some(x), _, Some(y)) if ['-', 'J', '7'].contains(x) && ['|', 'J', 'L'].contains(y) => 'F',
|
|
||||||
(_, _, Some(x), Some(y)) if ['|', '7', 'F'].contains(x) && ['|', 'J', 'L'].contains(y) => '|',
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,55 +1,13 @@
|
||||||
use shared::{Solution, Answer};
|
use shared::{Solution, Answer};
|
||||||
use itertools::Itertools;
|
|
||||||
|
|
||||||
pub struct Day11;
|
pub struct Day11;
|
||||||
|
|
||||||
impl Solution for Day11 {
|
impl Solution for Day11 {
|
||||||
fn part_1(&self, input: &str) -> Answer {
|
fn part_1(&self, input: &str) -> Answer {
|
||||||
Answer::from(solve(input, 2))
|
Answer::Unimplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part_2(&self, input: &str) -> Answer {
|
fn part_2(&self, input: &str) -> Answer {
|
||||||
Answer::from(solve(input, 1_000_000))
|
Answer::Unimplemented
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve(input: &str, inflation_arg: usize) -> u64 {
|
|
||||||
let grid = input.lines().map(|line| line.chars().map(|x| x == '#').collect::<Vec<bool>>()).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let mut distances = vec![vec![1; grid[0].len()]; grid.len()];
|
|
||||||
|
|
||||||
let mut empty_col = vec![true; grid[0].len()];
|
|
||||||
for (i, line) in grid.iter().enumerate() {
|
|
||||||
empty_col = empty_col.iter().enumerate().map(|(i, &l)| l && !line[i]).collect();
|
|
||||||
if !line.iter().any(|&x| x) {
|
|
||||||
distances[i] = vec![inflation_arg; line.len()];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, &col) in empty_col.iter().enumerate() {
|
|
||||||
if col {
|
|
||||||
for j in 0..distances.len() {
|
|
||||||
distances[j][i] = inflation_arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let galaxies: Vec<(usize, usize)> = grid.iter().
|
|
||||||
enumerate().
|
|
||||||
map(|(i, line)| line.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter_map(|(j, &x)| if x { Some((i, j)) } else { None })
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
).flatten().collect::<Vec<_>>();
|
|
||||||
|
|
||||||
galaxies.iter().permutations(2).map(|x| {
|
|
||||||
let (x1, y1): (usize, usize) = *x[0];
|
|
||||||
let (x2, y2): (usize, usize) = *x[1];
|
|
||||||
let mut out = 0;
|
|
||||||
let xrange = x1.min(x2)..x1.max(x2);
|
|
||||||
let yrange = if y1 <= y2 { y1..y2 } else { (y2+1)..(y1+1) };
|
|
||||||
for i in xrange { out += distances[i][if x1 <= x2 {y1} else {y2}] }
|
|
||||||
for j in yrange { out += distances[x1.min(x2)][j] }
|
|
||||||
out as u64
|
|
||||||
} ).sum::<u64>() / 2
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,13 @@
|
||||||
use std::iter;
|
|
||||||
use std::iter::zip;
|
|
||||||
use itertools::Itertools;
|
|
||||||
use shared::{Solution, Answer};
|
use shared::{Solution, Answer};
|
||||||
|
|
||||||
pub struct Day12;
|
pub struct Day12;
|
||||||
|
|
||||||
impl Solution for Day12 {
|
impl Solution for Day12 {
|
||||||
fn part_1(&self, input: &str) -> Answer {
|
fn part_1(&self, input: &str) -> Answer {
|
||||||
let lines = input.lines()
|
Answer::Unimplemented
|
||||||
.map(|x| x.split_once(' ').unwrap().0.chars().collect())
|
|
||||||
.collect::<Vec<Vec<char>>>();
|
|
||||||
let groups: Vec<Vec<u64>> = input.lines()
|
|
||||||
.map(|x| x.split_once(' ').unwrap().1.split(',').map(|y| y.parse::<u64>().unwrap()).collect())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut out = 0;
|
|
||||||
|
|
||||||
for (line, group) in zip(lines, groups) {
|
|
||||||
out += solve(&line, &group)
|
|
||||||
}
|
|
||||||
|
|
||||||
Answer::from(out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part_2(&self, input: &str) -> Answer {
|
fn part_2(&self, input: &str) -> Answer {
|
||||||
let lines = input.lines()
|
Answer::Unimplemented
|
||||||
.map(|x| iter::repeat(x.split_once(' ').unwrap().0).take(5).join("?").chars().collect())
|
|
||||||
.collect::<Vec<Vec<char>>>();
|
|
||||||
let groups: Vec<Vec<u64>> = input.lines()
|
|
||||||
.map(|x| iter::repeat(
|
|
||||||
x.split_once(' ')
|
|
||||||
.unwrap().1
|
|
||||||
.split(',')
|
|
||||||
.map(|a| a.parse::<u64>().unwrap())
|
|
||||||
).take(5)
|
|
||||||
.flatten()
|
|
||||||
.collect()
|
|
||||||
).collect();
|
|
||||||
|
|
||||||
let mut out = 0;
|
|
||||||
|
|
||||||
for (line, group) in zip(lines, groups) {
|
|
||||||
out += solve(&line, &group)
|
|
||||||
}
|
|
||||||
|
|
||||||
Answer::from(out)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve(springs: &Vec<char>, groups: &Vec<u64>) -> u64 {
|
|
||||||
let n = springs.len();
|
|
||||||
let m = groups.len();
|
|
||||||
|
|
||||||
let mut possibilities: Vec<Vec<u64>> = vec![vec![0; m+1]; n+1];
|
|
||||||
|
|
||||||
possibilities[0][0] = 1;
|
|
||||||
|
|
||||||
for i in 0..n {
|
|
||||||
for j in 0..=m {
|
|
||||||
if springs[i] != '#' {
|
|
||||||
possibilities[i+1][j] += possibilities[i][j];
|
|
||||||
}
|
|
||||||
if j < m
|
|
||||||
&& (i + groups[j] as usize) <= n
|
|
||||||
&& !springs[i..(i + groups[j] as usize)].contains(&'.')
|
|
||||||
&& (i + groups[j] as usize >= n || springs[i + groups[j] as usize ] != '#') {
|
|
||||||
possibilities[(i + groups[j] as usize + 1).min(n)][j+1] += possibilities[i][j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
possibilities[n][m]
|
|
||||||
}
|
|
||||||
|
|
|
||||||
80
flake.lock
generated
80
flake.lock
generated
|
|
@ -1,80 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681202837,
|
|
||||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1703134684,
|
|
||||||
"narHash": "sha256-SQmng1EnBFLzS7WSRyPM9HgmZP2kLJcPAz+Ug/nug6o=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "d6863cbcbbb80e71cecfc03356db1cda38919523",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"rust-overlay": "rust-overlay"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rust-overlay": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1689302058,
|
|
||||||
"narHash": "sha256-yD74lcHTrw4niXcE9goJLbzsgyce48rQQoy5jK5ZK40=",
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"rev": "7b8dbbf4c67ed05a9bf3d9e658c12d4108bc24c8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
||||||
50
flake.nix
50
flake.nix
|
|
@ -1,50 +0,0 @@
|
||||||
{
|
|
||||||
description = "A Nix-flake-based Rust development environment";
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
rust-overlay = {
|
|
||||||
url = "github:oxalica/rust-overlay";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = {
|
|
||||||
self,
|
|
||||||
nixpkgs,
|
|
||||||
rust-overlay,
|
|
||||||
}: let
|
|
||||||
overlays = [
|
|
||||||
rust-overlay.overlays.default
|
|
||||||
(final: prev: {
|
|
||||||
rustToolchain = let
|
|
||||||
rust = prev.rust-bin;
|
|
||||||
in
|
|
||||||
if builtins.pathExists ./rust-toolchain.toml
|
|
||||||
then rust.fromRustupToolchainFile ./rust-toolchain.toml
|
|
||||||
else if builtins.pathExists ./rust-toolchain
|
|
||||||
then rust.fromRustupToolchainFile ./rust-toolchain
|
|
||||||
else rust.stable.latest.default;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
supportedSystems = ["x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin"];
|
|
||||||
forEachSupportedSystem = f:
|
|
||||||
nixpkgs.lib.genAttrs supportedSystems (system:
|
|
||||||
f {
|
|
||||||
pkgs = import nixpkgs {inherit overlays system;};
|
|
||||||
});
|
|
||||||
in {
|
|
||||||
devShells = forEachSupportedSystem ({pkgs}: {
|
|
||||||
default = pkgs.mkShell {
|
|
||||||
packages = with pkgs; [
|
|
||||||
rustToolchain
|
|
||||||
openssl
|
|
||||||
pkg-config
|
|
||||||
cargo-deny
|
|
||||||
cargo-edit
|
|
||||||
cargo-watch
|
|
||||||
rust-analyzer
|
|
||||||
];
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +1,21 @@
|
||||||
use shared::Solution;
|
use shared::Solution;
|
||||||
|
|
||||||
use shared::load_actual;
|
use aoc2023;
|
||||||
|
use shared::{load_actual};
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
let Ok(data) = load_actual(2023, 12)
|
let Ok(data) = load_actual(2023, 10)
|
||||||
else { panic!("No Input Data"); };
|
else { panic!("No Input Data"); };
|
||||||
|
|
||||||
let result = aoc2023::day12::Day12.part_2(&data);
|
let result = aoc2023::day10::Day10.part_2(&data);
|
||||||
|
|
||||||
let elapsed = now.elapsed();
|
let elapsed = now.elapsed();
|
||||||
|
|
||||||
println!("{}", result);
|
println!("{}", result);
|
||||||
|
|
||||||
println!("{:?}", elapsed);
|
println!("{:?}", elapsed);
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue