Skip to content

Commit

Permalink
2024-20 Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jurisk committed Dec 21, 2024
1 parent 8195767 commit 479bb0c
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 57 deletions.
28 changes: 14 additions & 14 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions rust/common/src/coords2d.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt::Debug;
use std::iter::Step;
use std::ops::{Add, AddAssign, Neg, Sub};
use std::str::FromStr;

Expand Down Expand Up @@ -125,6 +126,24 @@ where
pub fn manhattan_distance_to_origin(self: Coords2D<T>) -> T {
self.x.abs() + self.y.abs()
}

pub fn all_coords_within_manhattan_distance(
self: Coords2D<T>,
distance_inclusive: T,
) -> Vec<Coords2D<T>>
where
T: Copy + Step,
{
let mut result = Vec::new();
for x in -distance_inclusive ..= distance_inclusive {
for y in -distance_inclusive ..= distance_inclusive {
if x.abs() + y.abs() <= distance_inclusive {
result.push(self + Coords2D::new(x, y));
}
}
}
result
}
}

impl<T: FromStr> FromStr for Coords2D<T>
Expand Down
36 changes: 18 additions & 18 deletions rust/y2024/src/bin/solution_2024_20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@ type N = i32;
type R = usize;
type Input = (Coords, MatrixGrid2D<bool>, Coords);

#[derive(Eq, PartialEq, Hash, Debug)]
#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)]
struct Cheat {
from: Coords,
to: Coords,
distance: N,
from: Coords,
to: Coords,
}

impl Cheat {
#[must_use]
fn distance(&self) -> N {
let from = self.from;
let to = self.to;
from.manhattan_distance(to)
}
}

fn parse(input: &str) -> Result<Input, Error> {
Expand Down Expand Up @@ -61,24 +69,17 @@ fn solve(data: &Input, save_at_least: N, max_cheat: N) -> R {
.map(|(_, c)| *c)
.unwrap_or_default();
let end_cost = from_end.get(&cheat.to).map(|(_, c)| *c).unwrap_or_default();
start_cost + end_cost + cheat.distance <= goal_cost_threshold
start_cost + end_cost + cheat.distance() <= goal_cost_threshold
};

let empties: Vec<_> = field
.coords()
.filter(|c| field.get(*c).is_some_and(|b| !*b))
.collect();
let is_empty = |c: &Coords| -> bool { field.get(*c).is_some_and(|b| !*b) };

let mut valid_cheats = HashSet::new();

// Could be optimised by avoiding processing all O(N^2), as if we know one coordinate, we can generate all others within maxCheat distance more efficiently
for from in &empties {
for to in &empties {
let from = *from;
let to = *to;
let distance = from.manhattan_distance(to);
if (1 ..= max_cheat).contains(&distance) {
let cheat = Cheat { from, to, distance };
for c1 in field.coords().filter(is_empty) {
for c2 in c1.all_coords_within_manhattan_distance(max_cheat) {
if is_empty(&c2) && c1 != c2 {
let cheat = Cheat { from: c1, to: c2 };
if valid_cheat(&cheat) {
valid_cheats.insert(cheat);
}
Expand Down Expand Up @@ -139,7 +140,6 @@ mod tests {
}

#[test]
#[ignore]
fn test_solve_1_real() {
assert_eq!(solve_1(&real_data(), 100), 1293);
}
Expand Down
33 changes: 11 additions & 22 deletions scala2/src/main/scala/jurisk/adventofcode/y2024/Advent20.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,17 @@ object Advent20 {
false
}

val empties = field.allCoords
.filter(field.at(_).contains(false))
val cheats =
for {
// Could be optimised by avoiding processing all O(N^2), as if we know one coordinate, we can generate all others within maxCheat distance more efficiently
c1 <- empties
c2 <- empties
if c1.manhattanDistance(c2) <= maxCheat
if c1 != c2
} yield Cheat(c1, c2)

println(s"Cheats: ${cheats.size}")

val selectedCheats =
cheats
.filter(validCheat)
.toSet

println(s"Selected cheats: ${selectedCheats.size}")
selectedCheats.foreach(println)

selectedCheats.size
def isEmpty(c: Coords2D): Boolean =
field.at(c).contains(false)

(for {
c1 <- field.allCoords.filter(isEmpty)
c2 <- c1.allCoordsWithinManhattanDistance(maxCheat)
if isEmpty(c2)
if c1 != c2
cheat = Cheat(c1, c2)
if validCheat(cheat)
} yield cheat).distinct.size
}

def part1(data: Input, saveAtLeast: Int): N =
Expand Down
12 changes: 11 additions & 1 deletion scala2/src/main/scala/jurisk/geometry/Coordinates2D.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package jurisk.geometry

import cats.Functor
import cats.implicits._
import jurisk.math.Enumerated
import jurisk.math.Enumerated._
import jurisk.utils.Parsing.StringOps

import scala.math.Numeric.Implicits.infixNumericOps
import scala.math.Ordered.orderingToOrdered

final case class Coordinates2D[N: Numeric](x: N, y: N) {
def +(other: Coordinates2D[N]): Coordinates2D[N] =
Expand All @@ -25,6 +26,15 @@ final case class Coordinates2D[N: Numeric](x: N, y: N) {
): N =
(this - other).manhattanDistanceToOrigin

def allCoordsWithinManhattanDistance(
distanceInclusive: N
)(implicit enumerated: Enumerated[N]): Seq[Coordinates2D[N]] =
for {
x <- -distanceInclusive to distanceInclusive
y <- -distanceInclusive to distanceInclusive
if x.abs + y.abs <= distanceInclusive
} yield this + Coordinates2D.of(x, y)

def adjacent4(implicit integral: Integral[N]): List[Coordinates2D[N]] =
neighbours(includeDiagonal = false)
def adjacent8(implicit integral: Integral[N]): List[Coordinates2D[N]] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Advent20Spec extends AnyFreeSpec {
part1(testData, 2) shouldEqual 1 + 1 + 1 + 1 + 1 + 3 + 2 + 4 + 2 + 14 + 14
}

"real" ignore {
"real" in {
part1(realData, 100) shouldEqual 1293
}
}
Expand All @@ -39,7 +39,7 @@ class Advent20Spec extends AnyFreeSpec {
part2(testData, 76) shouldEqual 3
}

"real" ignore {
"real" in {
part2(realData, 100) shouldEqual 977747
}
}
Expand Down

0 comments on commit 479bb0c

Please sign in to comment.