fundo
Fui inspirado pelo vídeo recente do 3Blue1Brown sobre o problema de divisão de colar (ou como ele chama, o problema de colar roubado) e sua relação com o teorema de Borsuk-Ulam .
Neste problema, dois ladrões roubaram um colar valioso que consiste em vários tipos diferentes de jóias. Há um número par de cada tipo de joia e os ladrões desejam dividir cada tipo de joia igualmente entre os dois. O problema é que eles devem fazê-lo dividindo o colar em um número de segmentos contíguos e distribuir os segmentos entre os dois.
Aqui é um exemplo, com quatro tipos de jóias denotados S
, E
, D
, e R
(por safira, esmeralda, diamante, e rubi, respectivamente). Digamos que o colar é o seguinte:
[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]
Existem 8
safiras, 10
esmeraldas, 4
diamantes e 6
rubis. Podemos dividir o colar da seguinte maneira:
[[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
Então, se dermos o primeiro, o terceiro e o quinto segmentos para um ladrão e o segundo e o quarto segmentos para o outro ladrão, cada um terminará com 4
safiras, 5
esmeraldas, 2
diamantes e 3
rubis:
[S], [S,E,S,D,E,R,S], [R,R,D,E,E,E]
[S], [R,E,S,S,S,D,R,E,E,R,E,D,E],
Usando 0
-indexing, esses cortes ocorrem nos índices [1,2,9,22]
.
Objetivo
Acontece que essa divisão justa sempre pode ser feita usando, no máximo n
, cortes, onde n
está o número de tipos de jóias. Sua tarefa é escrever um programa ou função completa que use um colar como entrada e produza uma divisão mínima (menor número de cortes).
Entrada
A entrada pode estar em qualquer formato conveniente. O colar deve ser uma sequência de jóias e nada mais; por exemplo, uma lista de números inteiros, dicionário com chaves que representam os tipos e valores de joias, sendo listas de índices. Como opção, você pode incluir o comprimento do colar ou o número de tipos distintos de joias, mas não deve aceitar nenhuma outra entrada.
Você pode assumir que o colar de entrada é válido. Você não precisa lidar com o caso em que há um número ímpar de jóias de um determinado tipo ou o colar está vazio.
Resultado
Novamente, a saída pode estar em qualquer formato conveniente; por exemplo, uma lista de segmentos, uma lista de posições de corte, um dicionário com chaves representando os dois ladrões e os valores como listas de segmentos, etc. Os segmentos podem ser representados pelo índice inicial, final, lista de índices consecutivos, lista de jóias, seus comprimentos etc. Você pode usar 0
- ou 1
- indexação. Se a ordem não for significativa para o seu formato, sua saída poderá estar em qualquer ordem. Aqui está a saída acima em vários formatos diferentes:
list of segments: [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
list of cuts: [1,2,9,22]
list of lengths: [1,1,7,13,6]
dictionary: {'thief1' : [(R,R,D,E,E,E),(S),(S,E,S,D,E,R,S)], 'thief2' : [(S),(R,E,S,S,S,D,R,E,E,R,E,D,E)]}
Observe que a ordem é importante na lista de segmentos (segmentos alternados entre os ladrões) e na lista de comprimentos (para identificar os segmentos), mas não na lista de cortes ou no dicionário. Edit: Greg Martin apontou que estes não seriam resultados válidos, uma vez que uma divisão justa pode ser obtida em dois cortes
Casos de teste
[1,2,1,2,1,3,1,3,3,2,2,3] -> [[1,2,1],[2,1,3,1],[3,3,2],[2,3]]
[1,1,1,1,2,2,3,3,3,3,3,3] -> [[1,1],[1,1,2],[2,3,3,3],[3,3,3]]
[1,1,1,1,1,1,1,1,1,1,1,1] -> [[1,1,1,1,1,1],[1,1,1,1,1,1]]
[1,1,1,1,2,3,4,2,3,4,2,2] -> [[1,1],[1,1,2,3,4,2],[3,4,2,2]]
Notas
- As brechas padrão são proibidas.
- Isso é código-golfe ; a resposta mais curta (em bytes) vence.
[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]
, parece que a saída deve ser [[S,S,S,E,S,D,E,R],[S,R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
, pois isso tem menos cortes que [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
. Estou entendendo as especificações corretamente?