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.
fonte
[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?Respostas:
Braquilog , 13 bytes
Experimente online!
Nota: o metapredicado
ᵛ
é mais novo que esse desafio.Explicação
As partições são enumeradas em ordem crescente do número de blocos, portanto o resultado terá o menor número possível de blocos.
fonte
Geléia , 18 bytes
Experimente online!
Não eficiente - o exemplo tem 28 jóias que não funcionarão sem grandes recursos, pois o primeiro passo dessa implementação seria criar uma lista das 2 27 partições possíveis.
Retorna uma lista de listas - os segmentos na ordem para separá-los entre ladrões alternativos. (Na saída do TIO: quando uma lista possui apenas um único item, a impressão implícita não se preocupa com os colchetes.
[]
)Quão?
fonte
Mathematica, 118 bytes
Quase venceu Jelly ... apenas 1 fora;)
Função pura tomando três argumentos: o colar, como uma lista de fichas como
{A, A, A, A, B, C, D, B, C, D, B, B}
; o comprimento do colar; e o número de momentos distintos da joia. Ele retorna uma lista de sublistas no formulário{{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}
, onde os tokens sem sinais negativos vão para um ladrão e os tokens com sinais negativos vão para o outro ladrão. (Embora seja uma informação redundante, o algoritmo leva a essa representação e a remoção dos sinais negativos custaria vários bytes.)Primeiro, temos que implementar uma função que pega uma lista e um conjunto de
n
locais de corte e retorna a lista den+1
sublistas obtida cortando a lista de entrada nessesn
locais de corte; o operador de binário infix±
é usado para essa finalidade e definido recursivamentel_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};
. Devido ao sinal negativo logo apósAppend
, o resultado é que os sublistas alternadamente possuem e não têm sinais negativos anexados a cada token.Em seguida, geramos todos os conjuntos de locais de corte possíveis cujo comprimento é no máximo o número de tipos de joias, usando
Range@#2~Subsets~#3
e usadoi=#;(i±#)&/@
para aplicar o±
operador (com a lista de entrada de jóias) a cada um desses conjuntos de locais de corte.Por fim,
SelectFirst[...,Tr[Tr/@#]==0&]&
escolhe a primeira das divisões de colar resultantes que é justa. Isso é feito somando literalmente todos os elementos em todas as sublistas; O Mathematica é inteligente o suficiente para cancelar as cópias positivas e negativas de cada token da maneira óbvia.fonte
Pitão, 16 bytes
Experimente on-line: Demonstration or Test Suite
Explicação:
fonte
05AB1E , 14 bytes
Experimente online ou verifique todos os casos de teste .
Explicação:
fonte