From 04620ff04b2ca20d4820311b83411eae87a61e38 Mon Sep 17 00:00:00 2001 From: pareronia <49491686+pareronia@users.noreply.github.com> Date: Sat, 9 Dec 2023 23:26:47 +0100 Subject: [PATCH] java - refactor Range --- src/main/java/AoC2016_20.java | 24 ++-- src/main/java/AoC2020_04.java | 12 +- src/main/java/AoC2020_16.java | 6 +- src/main/java/AoC2021_22.java | 14 +-- src/main/java/AoC2022_04.java | 8 +- src/main/java/AoC2022_15.java | 26 ++-- src/main/java/AoC2023_02.java | 6 +- src/main/java/AoC2023_03.java | 6 +- .../com/github/pareronia/aoc/LongRange.java | 61 +++++++++ .../java/com/github/pareronia/aoc/Range.java | 97 ++++++++------- .../github/pareronia/aoc/RangeInclusive.java | 117 ++++++++++++++++++ .../pareronia/aoc/geometry3d/Cuboid.java | 14 +-- src/test/java/AoC2022_15TestCase.java | 54 ++++---- .../pareronia/aoc/RangeInclusiveTestCase.java | 51 ++++++++ .../github/pareronia/aoc/RangeTestCase.java | 55 ++++---- 15 files changed, 395 insertions(+), 156 deletions(-) create mode 100644 src/main/java/com/github/pareronia/aoc/LongRange.java create mode 100644 src/main/java/com/github/pareronia/aoc/RangeInclusive.java create mode 100644 src/test/java/com/github/pareronia/aoc/RangeInclusiveTestCase.java diff --git a/src/main/java/AoC2016_20.java b/src/main/java/AoC2016_20.java index d694f410..c3777e30 100644 --- a/src/main/java/AoC2016_20.java +++ b/src/main/java/AoC2016_20.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.List; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; import com.github.pareronia.aocd.Aocd; import com.github.pareronia.aocd.Puzzle; @@ -12,13 +12,13 @@ public class AoC2016_20 extends AoCBase { private static final long TOTAL_IPS = 4294967296L; - private final List> ranges; + private final List> ranges; private AoC2016_20(final List input, final boolean debug) { super(debug); this.ranges = input.stream() .map(s -> s.split("-")) - .map(sp -> Range.between(Long.valueOf(sp[0]), Long.valueOf(sp[1]))) + .map(sp -> RangeInclusive.between(Long.valueOf(sp[0]), Long.valueOf(sp[1]))) .collect(toList()); } @@ -30,25 +30,25 @@ public static AoC2016_20 createDebug(final List input) { return new AoC2016_20(input, true); } - private List> combineRanges() { - final List> combines = new ArrayList<>(); - this.ranges.sort(comparing(Range::getMinimum)); // why doesn't this work without sorting? + private List> combineRanges() { + final List> combines = new ArrayList<>(); + this.ranges.sort(comparing(RangeInclusive::getMinimum)); // why doesn't this work without sorting? combines.add(this.ranges.get(0)); for (int i = 1; i < ranges.size(); i++) { - final Range r = ranges.get(i); + final RangeInclusive r = ranges.get(i); boolean combined = false; for (int j = 0; j < combines.size(); j++) { - final Range combine = combines.get(j); + final RangeInclusive combine = combines.get(j); if (combine.isOverlappedBy(r)) { final long min = Math.min(combine.getMinimum(), r.getMinimum()); final long max = Math.max(combine.getMaximum(), r.getMaximum()); - combines.set(j, Range.between(min, max)); + combines.set(j, RangeInclusive.between(min, max)); combined = true; } else if (r.getMaximum() + 1 == combine.getMinimum()) { - combines.set(j, Range.between(r.getMinimum(), combine.getMaximum())); + combines.set(j, RangeInclusive.between(r.getMinimum(), combine.getMaximum())); combined = true; } else if (combine.getMaximum() + 1 == r.getMinimum()) { - combines.set(j, Range.between(combine.getMinimum(), r.getMaximum())); + combines.set(j, RangeInclusive.between(combine.getMinimum(), r.getMaximum())); combined = true; } } @@ -62,7 +62,7 @@ private List> combineRanges() { @Override public Long solvePart1() { return combineRanges().stream() - .sorted(comparing(Range::getMinimum)) + .sorted(comparing(RangeInclusive::getMinimum)) .findFirst() .map(c -> c.getMaximum() + 1) .orElseThrow(); diff --git a/src/main/java/AoC2020_04.java b/src/main/java/AoC2020_04.java index 9f5abe6e..f169c991 100644 --- a/src/main/java/AoC2020_04.java +++ b/src/main/java/AoC2020_04.java @@ -9,7 +9,7 @@ import java.util.function.Function; import java.util.function.Predicate; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; import com.github.pareronia.aoc.StringUtils; import com.github.pareronia.aoc.Utils; import com.github.pareronia.aocd.Puzzle; @@ -150,23 +150,23 @@ public boolean isValid1() { } private boolean byrValid() { - return Range.between(1920, 2002).contains(Integer.valueOf(this.byr)); + return RangeInclusive.between(1920, 2002).contains(Integer.valueOf(this.byr)); } private boolean iyrValid() { - return Range.between(2010, 2020).contains(Integer.valueOf(this.iyr)); + return RangeInclusive.between(2010, 2020).contains(Integer.valueOf(this.iyr)); } private boolean eyrValid() { - return Range.between(2020, 2030).contains(Integer.valueOf(this.eyr)); + return RangeInclusive.between(2020, 2030).contains(Integer.valueOf(this.eyr)); } private boolean hgtValid() { final Integer hgt = Integer.valueOf(this.hgt.substring(0, this.hgt.length() - 2)); if (this.hgt.endsWith("in")) { - return Range.between(59, 76).contains(hgt); + return RangeInclusive.between(59, 76).contains(hgt); } else if (this.hgt.endsWith("cm")) { - return Range.between(150, 193).contains(hgt); + return RangeInclusive.between(150, 193).contains(hgt); } else { return false; } diff --git a/src/main/java/AoC2020_16.java b/src/main/java/AoC2020_16.java index 42134125..a06259ad 100644 --- a/src/main/java/AoC2020_16.java +++ b/src/main/java/AoC2020_16.java @@ -12,7 +12,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; import com.github.pareronia.aocd.Puzzle; import lombok.Builder; @@ -46,7 +46,7 @@ private final Rule parseRule(final String s) { final String[] splits3 = split.split("-"); final int start = Integer.parseInt(splits3[0]); final int end = Integer.parseInt(splits3[1]); - builder.validRange(Range.between(start, end)); + builder.validRange(RangeInclusive.between(start, end)); } return builder.build(); } @@ -127,7 +127,7 @@ public static void main(final String[] args) throws Exception { private static final class Rule { private final String field; @Singular - private final Set> validRanges; + private final Set> validRanges; public boolean validate(final int value) { return this.validRanges.stream().anyMatch(r -> r.contains(value)); diff --git a/src/main/java/AoC2021_22.java b/src/main/java/AoC2021_22.java index 9f662e6a..0852eb56 100644 --- a/src/main/java/AoC2021_22.java +++ b/src/main/java/AoC2021_22.java @@ -7,7 +7,7 @@ import java.util.Optional; import java.util.regex.Pattern; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; import com.github.pareronia.aoc.geometry3d.Cuboid; import com.github.pareronia.aocd.Aocd; import com.github.pareronia.aocd.Puzzle; @@ -36,9 +36,9 @@ private AoC2021_22(final List input, final boolean debug) { final Integer z1 = Integer.valueOf(m.group(6)); final Integer z2 = Integer.valueOf(m.group(7)); assert x1 <= x2 && y1 <= y2 && z1 <= z2; - final Range x = Range.between(x1, x2); - final Range y = Range.between(y1, y2); - final Range z = Range.between(z1, z2); + final RangeInclusive x = RangeInclusive.between(x1, x2); + final RangeInclusive y = RangeInclusive.between(y1, y2); + final RangeInclusive z = RangeInclusive.between(z1, z2); final boolean on = "on".equals(m.group(1)); return new RebootStep(x, y, z, on); }) @@ -204,9 +204,9 @@ public static void main(final String[] args) throws Exception { @RequiredArgsConstructor @ToString private static final class RebootStep { - private final Range x; - private final Range y; - private final Range z; + private final RangeInclusive x; + private final RangeInclusive y; + private final RangeInclusive z; private final boolean on; } } \ No newline at end of file diff --git a/src/main/java/AoC2022_04.java b/src/main/java/AoC2022_04.java index 228ad562..75c1806a 100644 --- a/src/main/java/AoC2022_04.java +++ b/src/main/java/AoC2022_04.java @@ -3,7 +3,7 @@ import java.util.regex.MatchResult; import java.util.regex.Pattern; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; import com.github.pareronia.aocd.Aocd; import com.github.pareronia.aocd.Puzzle; @@ -33,12 +33,12 @@ private final int[] numbers(final String string) { .toArray(); } - private int solve(final BiPredicate, Range> predicate) { + private int solve(final BiPredicate, RangeInclusive> predicate) { return (int) this.input.stream() .map(this::numbers) .filter(nums -> predicate.test( - Range.between(nums[0], nums[1]), - Range.between(nums[2], nums[3]))) + RangeInclusive.between(nums[0], nums[1]), + RangeInclusive.between(nums[2], nums[3]))) .count(); } diff --git a/src/main/java/AoC2022_15.java b/src/main/java/AoC2022_15.java index 0e35c05f..67e5c406 100644 --- a/src/main/java/AoC2022_15.java +++ b/src/main/java/AoC2022_15.java @@ -8,7 +8,7 @@ import java.util.Map; import java.util.Set; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; import com.github.pareronia.aoc.Utils; import com.github.pareronia.aoc.geometry.Position; import com.github.pareronia.aocd.Aocd; @@ -44,8 +44,8 @@ public static final AoC2022_15 createDebug(final List input) { return new AoC2022_15(input, true); } - private Deque> getRanges(final int y) { - final Set> ranges = new HashSet<>(); + private Deque> getRanges(final int y) { + final Set> ranges = new HashSet<>(); for (final Sensor sensor : this.sensors) { if (Math.abs(sensor.y - y) > sensor.distanceToBeacon) { continue; @@ -65,9 +65,9 @@ private int solve1(final int y) { private long solve2(final int max) { for (int y = max; y >= 0; y--) { - final Deque> ranges = getRanges(y); + final Deque> ranges = getRanges(y); for (int x = 0; x <= max; x++) { - for (final Range merged : ranges) { + for (final RangeInclusive merged : ranges) { if (merged.isAfter(x)) { log(Position.of(x, y)); return x * 4_000_000L + y; @@ -131,10 +131,10 @@ public Sensor(final int x, final int y, final int beaconX, final int beaconY) { this.distanceToBeacon = Math.abs(beaconX - x) + Math.abs(beaconY - y); } - public Range xRangeAt(final int y) { + public RangeInclusive xRangeAt(final int y) { final int dy = Math.abs(this.y - y); assert dy <= distanceToBeacon; - return Range.between( + return RangeInclusive.between( x - distanceToBeacon + dy, x + distanceToBeacon - dy); } @@ -142,9 +142,9 @@ public Range xRangeAt(final int y) { static final class RangeMerger { - public static Deque> mergeRanges(final Set> ranges) { - final Deque> m = new ArrayDeque<>(); - final List> sorted = new ArrayList<>(ranges); + public static Deque> mergeRanges(final Set> ranges) { + final Deque> m = new ArrayDeque<>(); + final List> sorted = new ArrayList<>(ranges); Collections.sort(sorted, (r1, r2) -> { final int first = Integer.compare(r1.getMinimum(), r2.getMinimum()); if (first == 0) { @@ -152,15 +152,15 @@ public static Deque> mergeRanges(final Set> ranges } return first; }); - for (final Range range : sorted) { + for (final RangeInclusive range : sorted) { if (m.isEmpty()) { m.addLast(range); continue; } - final Range last = m.peekLast(); + final RangeInclusive last = m.peekLast(); if (range.isOverlappedBy(last)) { m.removeLast(); - m.add(Range.between( + m.add(RangeInclusive.between( last.getMinimum(), Math.max(last.getMaximum(), range.getMaximum()))); } else { diff --git a/src/main/java/AoC2023_02.java b/src/main/java/AoC2023_02.java index a67e48dc..ad4da165 100644 --- a/src/main/java/AoC2023_02.java +++ b/src/main/java/AoC2023_02.java @@ -1,4 +1,4 @@ -import static com.github.pareronia.aoc.Utils.enumerate; +import static com.github.pareronia.aoc.IterTools.enumerate; import java.util.Arrays; import java.util.List; @@ -43,8 +43,8 @@ protected List parseInput(final List inputs) { }; return enumerate(inputs.stream()) .map(e -> new Game( - e.getIndex() + 1, - Arrays.stream(e.getValue().split(":")[1].split(";")) + e.index() + 1, + Arrays.stream(e.value().split(":")[1].split(";")) .map(parseDraw).toList())) .toList(); } diff --git a/src/main/java/AoC2023_03.java b/src/main/java/AoC2023_03.java index d3c4feb4..0ede2139 100644 --- a/src/main/java/AoC2023_03.java +++ b/src/main/java/AoC2023_03.java @@ -8,7 +8,7 @@ import com.github.pareronia.aoc.CharGrid; import com.github.pareronia.aoc.Grid.Cell; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; import com.github.pareronia.aoc.solution.Sample; import com.github.pareronia.aoc.solution.Samples; import com.github.pareronia.aoc.solution.SolutionBase; @@ -35,14 +35,14 @@ protected List parseInput(final List inputs) { return enumerate(grid.getRowsAsStrings()) .flatMap(e -> regex.matcher(e.value()).results() .map(m -> findEnginePart(grid, e.index(), - Range.between(m.start(), m.end())))) + RangeInclusive.between(m.start(), m.end())))) .filter(Optional::isPresent) .map(Optional::get) .toList(); } private Optional findEnginePart( - final CharGrid grid, final int row, final Range colspan + final CharGrid grid, final int row, final RangeInclusive colspan ) { return IntStream.range(colspan.getMinimum(), colspan.getMaximum()) .boxed() diff --git a/src/main/java/com/github/pareronia/aoc/LongRange.java b/src/main/java/com/github/pareronia/aoc/LongRange.java new file mode 100644 index 00000000..a07e1cd3 --- /dev/null +++ b/src/main/java/com/github/pareronia/aoc/LongRange.java @@ -0,0 +1,61 @@ +package com.github.pareronia.aoc; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; + +public class LongRange extends Range { + + public LongRange(final long element1, final long element2) { + super(element1, element2); + } + + public static LongRange between(final long fromInclusive, final long toExclusive) { + return new LongRange(fromInclusive, toExclusive); + } + + public Iterator iterator() { + return new Iterator<>() { + private long n = LongRange.this.minimum; + + @Override + public Long next() { + final long next = n; + n += 1; + return next; + } + + @Override + public boolean hasNext() { + return n < LongRange.this.maximum; + } + }; + } + + public JoinResult leftJoin(final LongRange other) { + final long o0 = Math.max(this.minimum, other.minimum); + final long o1 = Math.min(this.maximum, other.maximum); + if (o0 < o1) { + final Set others = new HashSet<>(); + if (this.minimum < o0) { + others.add(LongRange.between(this.minimum, o0)); + } + if (o1 < this.maximum) { + others.add(LongRange.between(o1, this.maximum)); + } + return new JoinResult( + Optional.of(LongRange.between(o0, o1)), others); + } else { + return new JoinResult( + Optional.empty(), + Set.of(LongRange.between(this.minimum.longValue(), this.maximum.longValue()))); + } + } + + public LongRange translate(final long amount) { + return LongRange.between(this.minimum + amount, this.maximum + amount); + } + + public record JoinResult(Optional intersection, Set others) {} +} diff --git a/src/main/java/com/github/pareronia/aoc/Range.java b/src/main/java/com/github/pareronia/aoc/Range.java index e51967d5..5c2498d2 100644 --- a/src/main/java/com/github/pareronia/aoc/Range.java +++ b/src/main/java/com/github/pareronia/aoc/Range.java @@ -1,12 +1,9 @@ package com.github.pareronia.aoc; import java.util.Comparator; +import java.util.Objects; -import lombok.EqualsAndHashCode; -import lombok.Getter; - -@EqualsAndHashCode(onlyExplicitlyIncluded = true) -public final class Range { +public class Range implements Comparable> { @SuppressWarnings({"rawtypes", "unchecked"}) private enum ComparableComparator implements Comparator { @@ -18,23 +15,23 @@ public int compare(final Object obj1, final Object obj2) { } } - @Getter - @EqualsAndHashCode.Include - private final T minimum; - @Getter - @EqualsAndHashCode.Include - private final T maximum; + protected final T minimum; + protected final T maximum; private final Comparator comparator; private String toString; @SuppressWarnings({ "unchecked" }) - private Range(final T element1, final T element2) { + protected Range(final T element1, final T element2) { AssertUtils.assertTrue( element1 != null && element2 != null, () -> String.format("Elements in a range must not be null: element1=%s, element2=%s", element1, element2)); this.comparator = ComparableComparator.INSTANCE; - if (comparator.compare(element1, element2) < 1) { + final int compare = comparator.compare(element1, element2); + AssertUtils.assertFalse(compare == 0, + () -> String.format("Elements must not be equal: element1=%s, element2=%s", + element1, element2)); + if (compare < 1) { this.minimum = element1; this.maximum = element2; } else { @@ -43,53 +40,69 @@ private Range(final T element1, final T element2) { } } - public static Range between(final T fromInclusive, final T toInclusive) { - return new Range<>(fromInclusive, toInclusive); - } - - public boolean isBefore(final T element) { + public boolean contains(final T element) { if (element == null) { return false; } - return comparator.compare(element, maximum) > 0; + return comparator.compare(element, minimum) > -1 + && comparator.compare(element, maximum) < 0; } - - public boolean isAfter(final T element) { - if (element == null) { - return false; + + private T min(final T t1, final T t2) { + if (this.comparator.compare(t1, t2) < 0) { + return t1; } - return comparator.compare(element, minimum) < 0; + return t2; } - - public boolean contains(final T element) { - if (element == null) { - return false; + + private T max(final T t1, final T t2) { + if (this.comparator.compare(t1, t2) > 0) { + return t1; } - return comparator.compare(element, minimum) > -1 - && comparator.compare(element, maximum) < 1; + return t2; + } + + public boolean isOverlappedBy(final Range other) { + final T o0 = max(this.minimum, other.minimum); + final T o1 = min(this.maximum, other.maximum); + return this.comparator.compare(o0, o1) < 0; + } + + @Override + public int hashCode() { + return Objects.hash(maximum, minimum); } - public boolean containsRange(final Range otherRange) { - if (otherRange == null) { + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { return false; } - return contains(otherRange.minimum) && contains(otherRange.maximum); - } - - public boolean isOverlappedBy(final Range otherRange) { - if (otherRange == null) { + if (getClass() != obj.getClass()) { return false; } - return otherRange.contains(minimum) - || otherRange.contains(maximum) - || contains(otherRange.minimum); + final Range other = (Range) obj; + return Objects.equals(maximum, other.maximum) + && Objects.equals(minimum, other.minimum); } @Override public String toString() { if (toString == null) { - toString = String.format("[%s..%s]", minimum, maximum); + toString = String.format("[%s..%s)", minimum, maximum); } return toString; } -} \ No newline at end of file + + @Override + public int compareTo(final Range other) { + final int cmin = this.comparator.compare(this.minimum, other.minimum); + if (cmin == 0) { + return this.comparator.compare(this.maximum, other.maximum); + } + return cmin; + } +} diff --git a/src/main/java/com/github/pareronia/aoc/RangeInclusive.java b/src/main/java/com/github/pareronia/aoc/RangeInclusive.java new file mode 100644 index 00000000..4c99a3d2 --- /dev/null +++ b/src/main/java/com/github/pareronia/aoc/RangeInclusive.java @@ -0,0 +1,117 @@ +package com.github.pareronia.aoc; + +import java.util.Comparator; +import java.util.Objects; + +public final class RangeInclusive { + + @SuppressWarnings({"rawtypes", "unchecked"}) + private enum ComparableComparator implements Comparator { + INSTANCE; + + @Override + public int compare(final Object obj1, final Object obj2) { + return ((Comparable) obj1).compareTo(obj2); + } + } + + private final T minimum; + private final T maximum; + private final Comparator comparator; + private String toString; + + @SuppressWarnings({ "unchecked" }) + private RangeInclusive(final T element1, final T element2) { + AssertUtils.assertTrue( + element1 != null && element2 != null, + () -> String.format("Elements in a range must not be null: element1=%s, element2=%s", + element1, element2)); + this.comparator = ComparableComparator.INSTANCE; + if (comparator.compare(element1, element2) < 1) { + this.minimum = element1; + this.maximum = element2; + } else { + this.minimum = element2; + this.maximum = element1; + } + } + + public static RangeInclusive between(final T fromInclusive, final T toInclusive) { + return new RangeInclusive<>(fromInclusive, toInclusive); + } + + public T getMinimum() { + return minimum; + } + + public T getMaximum() { + return maximum; + } + + public boolean isBefore(final T element) { + if (element == null) { + return false; + } + return comparator.compare(element, maximum) > 0; + } + + public boolean isAfter(final T element) { + if (element == null) { + return false; + } + return comparator.compare(element, minimum) < 0; + } + + public boolean contains(final T element) { + if (element == null) { + return false; + } + return comparator.compare(element, minimum) > -1 + && comparator.compare(element, maximum) < 1; + } + + public boolean containsRange(final RangeInclusive otherRange) { + if (otherRange == null) { + return false; + } + return contains(otherRange.minimum) && contains(otherRange.maximum); + } + + public boolean isOverlappedBy(final RangeInclusive otherRange) { + if (otherRange == null) { + return false; + } + return otherRange.contains(minimum) + || otherRange.contains(maximum) + || contains(otherRange.minimum); + } + + @Override + public int hashCode() { + return Objects.hash(maximum, minimum); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final RangeInclusive other = (RangeInclusive) obj; + return Objects.equals(maximum, other.maximum) + && Objects.equals(minimum, other.minimum); + } + + @Override + public String toString() { + if (toString == null) { + toString = String.format("[%s..%s]", minimum, maximum); + } + return toString; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/pareronia/aoc/geometry3d/Cuboid.java b/src/main/java/com/github/pareronia/aoc/geometry3d/Cuboid.java index c0102903..18ddc941 100644 --- a/src/main/java/com/github/pareronia/aoc/geometry3d/Cuboid.java +++ b/src/main/java/com/github/pareronia/aoc/geometry3d/Cuboid.java @@ -4,7 +4,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; import com.github.pareronia.aoc.geometry.Position; import lombok.EqualsAndHashCode; @@ -59,18 +59,18 @@ public static boolean overlap(final Cuboid cuboid1, final Cuboid cuboid2) { } private static boolean overlapX(final Cuboid cuboid1, final Cuboid cuboid2) { - return Range.between(cuboid1.x1, cuboid1.x2) - .isOverlappedBy(Range.between(cuboid2.x1, cuboid2.x2)); + return RangeInclusive.between(cuboid1.x1, cuboid1.x2) + .isOverlappedBy(RangeInclusive.between(cuboid2.x1, cuboid2.x2)); } private static boolean overlapY(final Cuboid cuboid1, final Cuboid cuboid2) { - return Range.between(cuboid1.y1, cuboid1.y2) - .isOverlappedBy(Range.between(cuboid2.y1, cuboid2.y2)); + return RangeInclusive.between(cuboid1.y1, cuboid1.y2) + .isOverlappedBy(RangeInclusive.between(cuboid2.y1, cuboid2.y2)); } private static boolean overlapZ(final Cuboid cuboid1, final Cuboid cuboid2) { - return Range.between(cuboid1.z1, cuboid1.z2) - .isOverlappedBy(Range.between(cuboid2.z1, cuboid2.z2)); + return RangeInclusive.between(cuboid1.z1, cuboid1.z2) + .isOverlappedBy(RangeInclusive.between(cuboid2.z1, cuboid2.z2)); } public static diff --git a/src/test/java/AoC2022_15TestCase.java b/src/test/java/AoC2022_15TestCase.java index 0ba4b765..1e311fcd 100644 --- a/src/test/java/AoC2022_15TestCase.java +++ b/src/test/java/AoC2022_15TestCase.java @@ -5,62 +5,62 @@ import org.junit.jupiter.api.Test; -import com.github.pareronia.aoc.Range; +import com.github.pareronia.aoc.RangeInclusive; public class AoC2022_15TestCase { @Test public void testRangeMergerDisjoint() { - final Set> ranges = Set.of( - Range.between(1, 6), - Range.between(8, 11) + final Set> ranges = Set.of( + RangeInclusive.between(1, 6), + RangeInclusive.between(8, 11) ); - final Deque> result = AoC2022_15.RangeMerger.mergeRanges(ranges); + final Deque> result = AoC2022_15.RangeMerger.mergeRanges(ranges); - assertThat(result).containsExactly(Range.between(1, 6), Range.between(8, 11)); + assertThat(result).containsExactly(RangeInclusive.between(1, 6), RangeInclusive.between(8, 11)); } @Test public void testRangeMergerOverlap() { - final Set> ranges = Set.of( - Range.between(1, 6), - Range.between(5, 11) + final Set> ranges = Set.of( + RangeInclusive.between(1, 6), + RangeInclusive.between(5, 11) ); - final Deque> result = AoC2022_15.RangeMerger.mergeRanges(ranges); + final Deque> result = AoC2022_15.RangeMerger.mergeRanges(ranges); - assertThat(result).containsExactly(Range.between(1, 11)); + assertThat(result).containsExactly(RangeInclusive.between(1, 11)); } @Test public void testRangeMergerDisjointAndOverlap() { - final Set> ranges = Set.of( - Range.between(5, 11), - Range.between(8, 11), - Range.between(1, 6), - Range.between(15, 21) + final Set> ranges = Set.of( + RangeInclusive.between(5, 11), + RangeInclusive.between(8, 11), + RangeInclusive.between(1, 6), + RangeInclusive.between(15, 21) ); - final Deque> result = AoC2022_15.RangeMerger.mergeRanges(ranges); + final Deque> result = AoC2022_15.RangeMerger.mergeRanges(ranges); - assertThat(result).containsExactly(Range.between(1, 11), Range.between(15, 21)); + assertThat(result).containsExactly(RangeInclusive.between(1, 11), RangeInclusive.between(15, 21)); } @Test public void mergeSample() { // [[-2..2], [12..12], [2..14], [14..18], [16..24], [2..2]] - final Set> ranges = Set.of( - Range.between(-2, 2), - Range.between(2, 14), - Range.between(14, 18), - Range.between(16, 24), - Range.between(2, 2), - Range.between(12, 12) + final Set> ranges = Set.of( + RangeInclusive.between(-2, 2), + RangeInclusive.between(2, 14), + RangeInclusive.between(14, 18), + RangeInclusive.between(16, 24), + RangeInclusive.between(2, 2), + RangeInclusive.between(12, 12) ); - final Deque> result = AoC2022_15.RangeMerger.mergeRanges(ranges); + final Deque> result = AoC2022_15.RangeMerger.mergeRanges(ranges); - assertThat(result).containsExactly(Range.between(-2, 24)); + assertThat(result).containsExactly(RangeInclusive.between(-2, 24)); } } diff --git a/src/test/java/com/github/pareronia/aoc/RangeInclusiveTestCase.java b/src/test/java/com/github/pareronia/aoc/RangeInclusiveTestCase.java new file mode 100644 index 00000000..35520af3 --- /dev/null +++ b/src/test/java/com/github/pareronia/aoc/RangeInclusiveTestCase.java @@ -0,0 +1,51 @@ +package com.github.pareronia.aoc; + +import static com.github.pareronia.aoc.RangeInclusive.between; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class RangeInclusiveTestCase { + + + @Test + public void isOverlappedBy() { + assertThat(between(1, 4).isOverlappedBy(between(3, 5))).isTrue(); + assertThat(between(1, 4).isOverlappedBy(between(0, 4))).isTrue(); + assertThat(between(1, 4).isOverlappedBy(between(-4, 5))).isTrue(); + assertThat(between(1, 4).isOverlappedBy(between(-4, 0))).isFalse(); + assertThat(between(1, 4).isOverlappedBy(between(14, 15))).isFalse(); + assertThat(between(1, 4).isOverlappedBy(between(1, 4))).isTrue(); + assertThat(between(1, 4).isOverlappedBy(between(2, 3))).isTrue(); + assertThat(between(-5, 5).isOverlappedBy(between(1, 3))).isTrue(); + assertThat(between(1, 1).isOverlappedBy(between(0, 1))).isTrue(); + assertThat(between(1, 1).isOverlappedBy(between(1, 1))).isTrue(); + } + + @Test + public void containsRange() { + assertThat(between(1, 4).containsRange(between(3, 5))).isFalse(); + assertThat(between(1, 4).containsRange(between(0, 4))).isFalse(); + assertThat(between(1, 4).containsRange(between(-4, 5))).isFalse(); + assertThat(between(1, 4).containsRange(between(-4, 0))).isFalse(); + assertThat(between(1, 4).containsRange(between(14, 15))).isFalse(); + assertThat(between(1, 4).containsRange(between(1, 4))).isTrue(); + assertThat(between(1, 4).containsRange(between(2, 3))).isTrue(); + assertThat(between(-5, 5).containsRange(between(1, 3))).isTrue(); + assertThat(between(1, 1).containsRange(between(0, 1))).isFalse(); + assertThat(between(1, 1).containsRange(between(1, 1))).isTrue(); + assertThat(between(2, 8).containsRange(between(3, 7))).isTrue(); + assertThat(between(4, 6).containsRange(between(6, 6))).isTrue(); + } + + @Test + public void contains() { + assertThat(between(1, 4).contains(0)).isFalse(); + assertThat(between(1, 4).contains(1)).isTrue(); + assertThat(between(1, 4).contains(2)).isTrue(); + assertThat(between(1, 4).contains(3)).isTrue(); + assertThat(between(1, 4).contains(4)).isTrue(); + assertThat(between(-4, 0).contains(1)).isFalse(); + assertThat(between(1, 1).contains(1)).isTrue(); + } +} diff --git a/src/test/java/com/github/pareronia/aoc/RangeTestCase.java b/src/test/java/com/github/pareronia/aoc/RangeTestCase.java index 88ef0c9e..574fa5c9 100644 --- a/src/test/java/com/github/pareronia/aoc/RangeTestCase.java +++ b/src/test/java/com/github/pareronia/aoc/RangeTestCase.java @@ -1,16 +1,16 @@ package com.github.pareronia.aoc; -import static com.github.pareronia.aoc.Range.between; +import static com.github.pareronia.aoc.LongRange.between; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.Test; class RangeTestCase { - @Test public void isOverlappedBy() { - assertThat(between(1, 4).isOverlappedBy(between(3, 5))).isTrue(); + assertThat(between(1, 4).isOverlappedBy(between(3, 5))).isTrue(); // ?? + assertThat(between(1, 4).isOverlappedBy(between(2, 5))).isTrue(); assertThat(between(1, 4).isOverlappedBy(between(0, 4))).isTrue(); assertThat(between(1, 4).isOverlappedBy(between(-4, 5))).isTrue(); assertThat(between(1, 4).isOverlappedBy(between(-4, 0))).isFalse(); @@ -18,34 +18,31 @@ public void isOverlappedBy() { assertThat(between(1, 4).isOverlappedBy(between(1, 4))).isTrue(); assertThat(between(1, 4).isOverlappedBy(between(2, 3))).isTrue(); assertThat(between(-5, 5).isOverlappedBy(between(1, 3))).isTrue(); - assertThat(between(1, 1).isOverlappedBy(between(0, 1))).isTrue(); - assertThat(between(1, 1).isOverlappedBy(between(1, 1))).isTrue(); } - - @Test - public void containsRange() { - assertThat(between(1, 4).containsRange(between(3, 5))).isFalse(); - assertThat(between(1, 4).containsRange(between(0, 4))).isFalse(); - assertThat(between(1, 4).containsRange(between(-4, 5))).isFalse(); - assertThat(between(1, 4).containsRange(between(-4, 0))).isFalse(); - assertThat(between(1, 4).containsRange(between(14, 15))).isFalse(); - assertThat(between(1, 4).containsRange(between(1, 4))).isTrue(); - assertThat(between(1, 4).containsRange(between(2, 3))).isTrue(); - assertThat(between(-5, 5).containsRange(between(1, 3))).isTrue(); - assertThat(between(1, 1).containsRange(between(0, 1))).isFalse(); - assertThat(between(1, 1).containsRange(between(1, 1))).isTrue(); - assertThat(between(2, 8).containsRange(between(3, 7))).isTrue(); - assertThat(between(4, 6).containsRange(between(6, 6))).isTrue(); - } - + +// @Test +// public void containsRange() { +// assertThat(between(1, 4).containsRange(between(3, 5))).isFalse(); +// assertThat(between(1, 4).containsRange(between(0, 4))).isFalse(); +// assertThat(between(1, 4).containsRange(between(-4, 5))).isFalse(); +// assertThat(between(1, 4).containsRange(between(-4, 0))).isFalse(); +// assertThat(between(1, 4).containsRange(between(14, 15))).isFalse(); +// assertThat(between(1, 4).containsRange(between(1, 4))).isTrue(); +// assertThat(between(1, 4).containsRange(between(2, 3))).isTrue(); +// assertThat(between(-5, 5).containsRange(between(1, 3))).isTrue(); +// assertThat(between(1, 1).containsRange(between(0, 1))).isFalse(); +// assertThat(between(1, 1).containsRange(between(1, 1))).isTrue(); +// assertThat(between(2, 8).containsRange(between(3, 7))).isTrue(); +// assertThat(between(4, 6).containsRange(between(6, 6))).isTrue(); +// } +// @Test public void contains() { - assertThat(between(1, 4).contains(0)).isFalse(); - assertThat(between(1, 4).contains(1)).isTrue(); - assertThat(between(1, 4).contains(2)).isTrue(); - assertThat(between(1, 4).contains(3)).isTrue(); - assertThat(between(1, 4).contains(4)).isTrue(); - assertThat(between(-4, 0).contains(1)).isFalse(); - assertThat(between(1, 1).contains(1)).isTrue(); + assertThat(between(1, 4).contains(0L)).isFalse(); + assertThat(between(1, 4).contains(1L)).isTrue(); + assertThat(between(1, 4).contains(2L)).isTrue(); + assertThat(between(1, 4).contains(3L)).isTrue(); + assertThat(between(1, 4).contains(4L)).isFalse(); + assertThat(between(-4, 0).contains(1L)).isFalse(); } }