Resolvi experimentar. Estou praticando Java funcional, então não estou utilizando os loops tradicionais, mas sim os range
no lugar deles.
class EscadaPerfeita {
static int calcular(final List<Integer> escada) {
var escadaPerfeita = escadaPerfeita(escada);
if (escadaPerfeita.isEmpty()) {
System.out.println(escada + " -> -1");
return -1;
}
var numeroDeMovimentos = range(0, escada.size())
.map(i -> escada.get(i) - escadaPerfeita.get(i))
.filter(i -> i > 0)
.sum();
System.out.println(escada + " -> " + escadaPerfeita + " -> " + numeroDeMovimentos);
return numeroDeMovimentos;
}
private static List<Integer> escadaPerfeita(List<Integer> escada) {
Function<Integer, List<Integer>> gerarProjecaoLinear =
(inicio) -> range(inicio, inicio + escada.size())
.boxed()
.toList();
int somaDasAlturas = escada.stream().mapToInt(Integer::intValue).sum();
return rangeClosed(0, somaDasAlturas)
.boxed()
.map(gerarProjecaoLinear)
.filter(projecaoLinear -> projecaoLinear
.stream()
.mapToInt(Integer::intValue)
.sum() == somaDasAlturas)
.findFirst()
.orElse(List.of());
}
}
Testes de unidade
class EscadaPerfeitaTest {
@ParameterizedTest
@MethodSource("dadosDeTeste")
void numeroDeMovimentosParaEscadaPerfeita(List<Integer> escada, int expectativa) {
assertEquals(expectativa, EscadaPerfeita.calcular(escada));
}
static Stream<Arguments> dadosDeTeste() {
return Stream.of(
// Dados do artigo
arguments(List.of(5, 4, 5, 4, 2), 5),
arguments(List.of(9, 8, 7, 6, 5, 4), 9),
arguments(List.of(1, 5), -1),
// Meus dados adicionais
arguments(List.of(0), 0),
arguments(List.of(7), 0),
arguments(List.of(1, 2, 3), 0),
arguments(List.of(4, 1, 1), 3),
arguments(List.of(7, 1, 1), 5),
arguments(List.of(10, 9, 8), 2),
arguments(List.of(14, 13, 7, 16, 10), 9),
arguments(List.of(15, 1, 2), 10),
arguments(List.of(5, 5), -1),
arguments(List.of(5, 6, 5), -1)
);
}
}
A saida do console (ajuda a visualizar):
[5, 4, 5, 4, 2] -> [2, 3, 4, 5, 6] -> 5
[9, 8, 7, 6, 5, 4] -> [4, 5, 6, 7, 8, 9] -> 9
[1, 5] -> -1
[0] -> [0] -> 0
[7] -> [7] -> 0
[1, 2, 3] -> [1, 2, 3] -> 0
[4, 1, 1] -> [1, 2, 3] -> 3
[7, 1, 1] -> [2, 3, 4] -> 5
[10, 9, 8] -> [8, 9, 10] -> 2
[14, 13, 7, 16, 10] -> [10, 11, 12, 13, 14] -> 9
[15, 1, 2] -> [5, 6, 7] -> 10
[5, 5] -> -1
[5, 6, 5] -> -1