diff --git a/.idea/AdventOfCode.iml b/.idea/AdventOfCode.iml
index 4661634..a1dbddc 100644
--- a/.idea/AdventOfCode.iml
+++ b/.idea/AdventOfCode.iml
@@ -5,8 +5,6 @@
-
-
diff --git a/Cargo.lock b/Cargo.lock
index 7219f43..06c327d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -23,7 +23,6 @@ dependencies = [
name = "aoc2023"
version = "0.1.0"
dependencies = [
- "itertools",
"regex",
"shared",
"substring",
@@ -35,21 +34,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "memchr"
version = "2.6.4"
diff --git a/aoc2023/Cargo.toml b/aoc2023/Cargo.toml
index 81acc05..0b76455 100644
--- a/aoc2023/Cargo.toml
+++ b/aoc2023/Cargo.toml
@@ -6,5 +6,4 @@ edition = "2021"
[dependencies]
shared = { path = "../shared" }
regex = "1.10.2"
-substring = "1.4.5"
-itertools = "0.12.0"
\ No newline at end of file
+substring = "1.4.5"
\ No newline at end of file
diff --git a/aoc2023/src/day05.rs b/aoc2023/src/day05.rs
index e315821..5567f84 100644
--- a/aoc2023/src/day05.rs
+++ b/aoc2023/src/day05.rs
@@ -133,6 +133,10 @@ struct 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 {
Rule {start: source, end: source + range - 1, offset: (dest - source)}
}
diff --git a/aoc2023/src/day10.rs b/aoc2023/src/day10.rs
index afa65a1..517959e 100644
--- a/aoc2023/src/day10.rs
+++ b/aoc2023/src/day10.rs
@@ -1,108 +1,193 @@
use std::collections::HashSet;
+use std::process::abort;
use shared::{Solution, Answer};
pub struct Day10;
impl Solution for Day10 {
fn part_1(&self, input: &str) -> Answer {
- let mut grid: Vec> = input.lines().map(|x| x.chars().collect()).collect();
- let full_animal = grid.iter().flatten().position(|&x| x == 'S').unwrap();
- let animal = (full_animal / grid.len(), full_animal % grid.len());
+ let width: i64 = input.lines().next().unwrap().len() as i64;
+ let grid: Vec<_> = input.lines().collect::>().join("").chars().map(Pipes::from).collect();
- replace_animal(&mut grid, &animal);
+ let animal = grid.iter().position(|x| x == &Pipes::Animal).unwrap();
- let mut pos = animal;
- let mut last: Option<(usize, usize)> = None;
+ let mut seen: HashSet = HashSet::new();
- 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 {
- len_of_loop += 1;
- let tmp = pos;
- pos = traverse(&grid[pos.0][pos.1], &pos, &last);
- last = Some(tmp);
-
- if pos == animal {break}
+ let next = traverse(&grid, current as i64, width);
+ if next.is_none() { panic!() }
+ let (next1, next2) = next.unwrap();
+ if seen.contains(&next1) && seen.contains(&next2) {
+ 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 {
- let mut grid: Vec> = input.lines().map(|x| x.chars().collect()).collect();
- let full_animal = grid.iter().flatten().position(|&x| x == 'S').unwrap();
- let animal = (full_animal / grid.len(), full_animal % grid.len());
+ let width: usize = input.lines().next().unwrap().len();
+ let mut grid: Vec<_> = input.lines().collect::>().join("").chars().map(Pipes::from).collect();
- 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 last: Option<(usize, usize)> = None;
+ let mut seen: HashSet = HashSet::new();
- 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 {
- in_loop.insert(pos);
- let tmp = pos;
- pos = traverse(&grid[pos.0][pos.1], &pos, &last);
- last = Some(tmp);
-
- if pos == animal {break}
+ let next = traverse(&grid, current as i64, width as i64);
+ if next.is_none() { panic!() }
+ let (next1, next2) = next.unwrap();
+ if seen.contains(&next1) && seen.contains(&next2) {
+ 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::>();
- for (i, line) in grid.iter().enumerate() {
- let mut parity = false;
+ for (i, line) in grid.chunks(width).enumerate() {
for (j, letter) in line.iter().enumerate() {
- if in_loop.contains(&(i, j)) {
- if ['|', 'J', 'L'].contains(letter) { parity = !parity }
- continue
- }
- else if parity {
- total += 1
+ if seen.contains(&(width * i + j)) {
+ for k in j..width {
+ parity[i][k] += match letter {
+ Pipes::Vertical => 2, // using 2 and 1 instead of 1 and .5 for half parity, because integers
+ Pipes::StoW => 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::();
+ println!("{:?}", line);
+ }
+
+ Answer::from(enclosed)
}
}
-fn traverse(pipe: &char, pos: &(usize, usize), last: &Option<(usize, usize)>) -> (usize, usize) {
- let (offset1, offset2) = match *pipe {
- '|' => ((-1, 0), (1, 0)),
- '-' => ((0, -1), (0, 1)),
- 'J' => ((-1, 0), (0, -1)),
- 'L' => ((-1, 0), (0, 1)),
- 'F' => ((1, 0), (0, 1)),
- '7' => ((1, 0), (0, -1)),
- l => panic!("Invalid letter {l}")
+#[derive(Debug, PartialEq, Eq)]
+enum Pipes {
+ Ground,
+ Vertical,
+ Horizontal,
+ WtoN,
+ NtoE,
+ EtoS,
+ StoW,
+ Animal
+}
+
+impl From 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, 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);
- let new2 = ((offset2.0 + pos.0 as i32) as usize, (offset2.1 + pos.1 as i32) as usize);
+ // println!("{next1}, {next2}: Current={current}, Width={width}");
- match last {
- None => new1,
- Some(p) if p == &new1 => new2,
- Some(p) if p == &new2 => new1,
+ // if next1 - current == -1 || next1 - current == width || next1 == -1 || next1 == (grid.len() as i64) { return None };
+ // if next2 - current == -1 || next2 - current == width || next2 == -1 || next2 == (grid.len() as i64) { return None };
+
+ Some((next1 as usize, next2 as usize))
+}
+
+fn replace_animal(grid: &mut Vec, 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!()
}
}
-fn replace_animal(grid: &mut Vec>, 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!()
- }
-}
diff --git a/aoc2023/src/day11.rs b/aoc2023/src/day11.rs
index ae38301..2e4945b 100644
--- a/aoc2023/src/day11.rs
+++ b/aoc2023/src/day11.rs
@@ -1,55 +1,13 @@
use shared::{Solution, Answer};
-use itertools::Itertools;
pub struct Day11;
impl Solution for Day11 {
fn part_1(&self, input: &str) -> Answer {
- Answer::from(solve(input, 2))
+ Answer::Unimplemented
}
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::>()).collect::>();
-
- 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::>()
- ).flatten().collect::>();
-
- 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::() / 2
-}
diff --git a/aoc2023/src/day12.rs b/aoc2023/src/day12.rs
index 95e23cb..c82f532 100644
--- a/aoc2023/src/day12.rs
+++ b/aoc2023/src/day12.rs
@@ -1,74 +1,13 @@
-use std::iter;
-use std::iter::zip;
-use itertools::Itertools;
use shared::{Solution, Answer};
pub struct Day12;
impl Solution for Day12 {
fn part_1(&self, input: &str) -> Answer {
- let lines = input.lines()
- .map(|x| x.split_once(' ').unwrap().0.chars().collect())
- .collect::>>();
- let groups: Vec> = input.lines()
- .map(|x| x.split_once(' ').unwrap().1.split(',').map(|y| y.parse::().unwrap()).collect())
- .collect();
-
- let mut out = 0;
-
- for (line, group) in zip(lines, groups) {
- out += solve(&line, &group)
- }
-
- Answer::from(out)
+ Answer::Unimplemented
}
fn part_2(&self, input: &str) -> Answer {
- let lines = input.lines()
- .map(|x| iter::repeat(x.split_once(' ').unwrap().0).take(5).join("?").chars().collect())
- .collect::>>();
- let groups: Vec> = input.lines()
- .map(|x| iter::repeat(
- x.split_once(' ')
- .unwrap().1
- .split(',')
- .map(|a| a.parse::().unwrap())
- ).take(5)
- .flatten()
- .collect()
- ).collect();
-
- let mut out = 0;
-
- for (line, group) in zip(lines, groups) {
- out += solve(&line, &group)
- }
-
- Answer::from(out)
+ Answer::Unimplemented
}
}
-
-fn solve(springs: &Vec, groups: &Vec) -> u64 {
- let n = springs.len();
- let m = groups.len();
-
- let mut possibilities: Vec> = 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]
-}
diff --git a/flake.lock b/flake.lock
deleted file mode 100644
index e77b2e6..0000000
--- a/flake.lock
+++ /dev/null
@@ -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
-}
diff --git a/flake.nix b/flake.nix
deleted file mode 100644
index 11a3b21..0000000
--- a/flake.nix
+++ /dev/null
@@ -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
- ];
- };
- });
- };
-}
diff --git a/src/main.rs b/src/main.rs
index 61a10dd..8ac0506 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,20 +1,21 @@
use shared::Solution;
-use shared::load_actual;
+use aoc2023;
+use shared::{load_actual};
use std::time::Instant;
fn main() {
let now = Instant::now();
- let Ok(data) = load_actual(2023, 12)
+ let Ok(data) = load_actual(2023, 10)
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();
println!("{}", result);
println!("{:?}", elapsed);
-}
+}
\ No newline at end of file