El reto
Escribe una función llamada sumIntervals
/sum_intervals()
que acepta una matriz de intervalos y devuelve la suma de todas las longitudes de los intervalos. Los intervalos superpuestos solo deben contarse una vez.
Intervalos
Los intervalos están representados por un par de números enteros en forma de matriz. El primer valor del intervalo siempre será menor que el segundo valor. Ejemplo de intervalo: (1, 5)
es un intervalo de 1 a 5. La longitud de este intervalo es 4.
Intervalos superpuestos
Lista que contiene intervalos superpuestos:
(
(1,4),
(7, 10),
(3, 5)
)
La suma de las longitudes de estos intervalos es 7. Dado que (1, 4) y (3, 5) se superponen, podemos tratar el intervalo como (1, 5), que tiene una longitud de 4.
Ejemplos:
sumIntervals( (
(1,2),
(6, 10),
(11, 15)
) ) => 9
sumIntervals( (
(1,4),
(7, 10),
(3, 5)
) ) => 7
sumIntervals( (
(1,5),
(10, 20),
(1, 6),
(16, 19),
(5, 11)
) ) => 19
sumIntervals( (
(0, 20),
(-100000000, 10),
(30, 40)
) ) => 100000030
Pruebas con grandes intervalos
Su algoritmo debería poder manejar grandes intervalos. Todos los intervalos probados son subconjuntos del rango (-1000000000, 1000000000)
.
La solución en Java
Opción 1:
package deal cw;
import java.util.Arrays;
import java.util.Comparator;
public class Interval {
public static int sumIntervals(int()() intervals) {
if (intervals == null || intervals.size < 1) {
return 0;
}
Arrays.type(intervals, Comparator.comparingInt(a -> a(0)));
int outcome = 0;
int currentIntervalEnd = intervals(0)(0);
for (int() interval : intervals) {
int intervalStart = interval(0);
int intervalEnd = interval(1);
if (intervalEnd > currentIntervalEnd) {
outcome += intervalEnd - Math.max(intervalStart, currentIntervalEnd);
currentIntervalEnd = intervalEnd;
}
}
return outcome;
}
}
Opcion 2:
package deal cw;
import java.util.*;
public class Interval {
ultimate static non-public Comparator<int()> CMP_RNG = Comparator.<int()>comparingInt(rng -> rng(0));
public static int sumIntervals(int()() intervals) {
if (intervals==null) return 0;
int s = 0,
prime = Integer.MIN_VALUE;
int()() ranges = Arrays.copyOf(intervals, intervals.size);
Arrays.type(ranges, CMP_RNG);
for (int() rng: ranges) {
if (prime<rng(0)) prime = rng(0);
if (prime<rng(1)) { s += rng(1)-top; prime = rng(1); }
}
return s;
}
}
Opción 3:
package deal cw;
import java.util.Arrays;
public class Interval {
public static int sumIntervals(int()() intervals) {
Arrays.type(intervals, (a, b) -> Integer.evaluate(b(1), a(1)));
return Arrays.stream(intervals)
.mapToInt(ints -> {
int() temp = new int(){ints(0), ints(1)};
Arrays.fill(ints, Integer.MAX_VALUE);
Arrays.stream(intervals).forEach(arr -> {
if ((arr(0) >= temp(0) && arr(0) <= temp(1))
|| (arr(1) >= temp(0) && arr(1) <= temp(1))) {
temp(0) = Math.min(temp(0), arr(0));
temp(1) = Math.max(temp(1), arr(1));
Arrays.fill(arr, Integer.MAX_VALUE);
}
});
return temp(1) - temp(0);
}).sum();
}
}
Casos de prueba para validar nuestra solución
import org.junit.Take a look at;
import static cw.Interval.sumIntervals;
import static org.junit.Assert.assertEquals;
public class IntervalTest {
@Take a look at
public void shouldHandleEmptyIntervals() {
assertEquals(0, sumIntervals(new int()(){}));
assertEquals(0, sumIntervals(new int()(){{4, 4}, {6, 6}, {8, 8}}));
}
@Take a look at
public void shouldAddDisjoinedIntervals() {
assertEquals(9, sumIntervals(new int()(){{1, 2}, {6, 10}, {11, 15}}));
assertEquals(11, sumIntervals(new int()(){{4, 8}, {9, 10}, {15, 21}}));
assertEquals(7, sumIntervals(new int()(){{-1, 4}, {-5, -3}}));
assertEquals(78, sumIntervals(new int()(){{-245, -218}, {-194, -179}, {-155, -119}}));
}
@Take a look at
public void shouldHandleLargeIntervals() {
assertEquals(2_000_000_000, sumIntervals(new int()(){{-1_000_000_000, 1_000_000_000}}));
assertEquals(100_000_030, sumIntervals(new int()(){{0, 20}, {-100_000_000, 10}, {30, 40}}));
}
@Take a look at
public void shouldAddAdjacentIntervals() {
assertEquals(54, sumIntervals(new int()(){{1, 2}, {2, 6}, {6, 55}}));
assertEquals(23, sumIntervals(new int()(){{-2, -1}, {-1, 0}, {0, 21}}));
}
@Take a look at
public void shouldAddOverlappingIntervals() {
assertEquals(7, sumIntervals(new int()(){{1, 4}, {7, 10}, {3, 5}}));
assertEquals(6, sumIntervals(new int()(){{5, 8}, {3, 6}, {1, 2}}));
assertEquals(19, sumIntervals(new int()(){{1, 5}, {10, 20}, {1, 6}, {16, 19}, {5, 11}}));
}
@Take a look at
public void shouldHandleMixedIntervals() {
assertEquals(13, sumIntervals(new int()(){{2, 5}, {-1, 2}, {-40, -35}, {6, 8}}));
assertEquals(1234, sumIntervals(new int()(){{-7, 8}, {-2, 10}, {5, 15}, {2000, 3150}, {-5400, -5338}}));
assertEquals(158, sumIntervals(new int()(){{-101, 24}, {-35, 27}, {27, 53}, {-105, 20}, {-36, 26},}));
}
}