mirror of
https://gitlab.com/mfocko/CodeWars.git
synced 2024-12-22 17:41:24 +01:00
4kyu: add „Sum of Intervals“
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
5dea8c097c
commit
f5df67ce62
1 changed files with 148 additions and 0 deletions
148
4kyu/sum_of_intervals/solution.java
Normal file
148
4kyu/sum_of_intervals/solution.java
Normal file
|
@ -0,0 +1,148 @@
|
|||
package cw;
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
class Interval {
|
||||
private static class Range implements Comparable<Range> {
|
||||
private int from;
|
||||
private int to;
|
||||
|
||||
public Range(int from, int to) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return to - from;
|
||||
}
|
||||
|
||||
public Range merge(Range other) {
|
||||
return new Range(Math.min(from, other.from), Math.max(to, other.to));
|
||||
}
|
||||
|
||||
public boolean mergeInSitu(Range other) {
|
||||
if (!canMerge(other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
from = Math.min(from, other.from);
|
||||
to = Math.max(to, other.to);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean has(int x) {
|
||||
return from <= x && x <= to;
|
||||
}
|
||||
|
||||
public boolean isSubrangeOf(Range other) {
|
||||
return other.has(from) && other.has(to);
|
||||
}
|
||||
|
||||
public boolean isPrefixOf(Range other) {
|
||||
return from <= other.from && other.has(to);
|
||||
}
|
||||
|
||||
public boolean isSuffixOf(Range other) {
|
||||
return to >= other.to && has(other.from);
|
||||
}
|
||||
|
||||
public boolean canMerge(Range other) {
|
||||
return isSubrangeOf(other) || isPrefixOf(other) || isSuffixOf(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Range other) {
|
||||
if (other == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (from == other.from && to == other.to) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (to < other.from || from < other.from) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void insertRange(TreeSet<Range> ranges, Range range) {
|
||||
for (Range r : ranges) {
|
||||
if (r.canMerge(range)) {
|
||||
ranges.remove(r);
|
||||
ranges.add(r.merge(range));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ranges.add(range);
|
||||
}
|
||||
|
||||
private static boolean mergeRanges(TreeSet<Range> ranges) {
|
||||
for (Range x : ranges) {
|
||||
for (Range y : ranges) {
|
||||
if (x == y) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x.canMerge(y)) {
|
||||
ranges.remove(x);
|
||||
ranges.remove(y);
|
||||
ranges.add(x.merge(y));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int sumIntervals(int[][] intervals) {
|
||||
if (intervals == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TreeSet<Range> ranges = new TreeSet<>();
|
||||
|
||||
// Go through the intervals and construct a set out of them
|
||||
// when adding each interval, try to merge it in-situ with any of the
|
||||
// existing intervals
|
||||
for (int[] interval : intervals) {
|
||||
insertRange(ranges, new Range(interval[0], interval[1]));
|
||||
}
|
||||
|
||||
// then iteratively merge the set of intervals while possible
|
||||
boolean hasChanged = true;
|
||||
while (hasChanged) {
|
||||
hasChanged = mergeRanges(ranges);
|
||||
}
|
||||
|
||||
for (Range r : ranges) {
|
||||
System.out.format("%d, %d; ", r.from, r.to);
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
return ranges.stream().map(Range::length).reduce(Integer::sum).orElse(0);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// null argument
|
||||
System.out.format("%d == %d\n", Interval.sumIntervals(null), 0); // => 0
|
||||
|
||||
// empty intervals
|
||||
System.out.format("%d == %d\n", Interval.sumIntervals(new int[][]{}), 0); // => 0
|
||||
System.out.format("%d == %d\n", Interval.sumIntervals(new int[][]{{2,2}, {5,5}}), 0); // => 0
|
||||
|
||||
// disjoined intervals
|
||||
System.out.format("%d == %d\n", Interval.sumIntervals(new int[][]{
|
||||
{1,2},{3,5}
|
||||
}), 3); // => (2-1) + (5-3) = 3
|
||||
|
||||
// overlapping intervals
|
||||
System.out.format("%d == %d\n", Interval.sumIntervals(new int[][]{
|
||||
{1,4},{3,6},{2,8}
|
||||
}), 7); // [1,8] => 7
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue