Antecedentes
Me inspiró el reciente video de 3Blue1Brown sobre el problema de división del collar (o como él lo llama, el problema del collar robado) y su relación con el teorema de Borsuk-Ulam .
En este problema, dos ladrones han robado un collar valioso que consta de varios tipos diferentes de joyas. Hay un número par de cada tipo de joya y los ladrones desean dividir cada tipo de joya de manera uniforme entre los dos. El problema es que deben hacerlo dividiendo el collar en un número de segmentos contiguos y distribuir los segmentos entre los dos.
Aquí hay un ejemplo con cuatro tipos de joya denotados S
, E
, D
, y R
(por zafiro, esmeralda, diamante y rubí, respectivamente). Digamos que el collar es el siguiente:
[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]
Hay 8
zafiros, 10
esmeraldas, 4
diamantes y 6
rubíes. Podemos dividir el collar de la siguiente manera:
[[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]]
Luego, si le damos los segmentos primero, tercero y quinto a un ladrón y el segundo y cuarto segmentos al otro ladrón, cada uno terminará con 4
zafiros, 5
esmeraldas, 2
diamantes y 3
rubíes:
[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, estos cortes ocurren en los índices [1,2,9,22]
.
Objetivo
Resulta que una división tan justa siempre se puede hacer con la mayoría de los n
cortes, donde n
está el número de tipos de joyas. Su tarea es escribir un programa o función completa que tome un collar como entrada y produzca una división mínima (número mínimo de cortes).
Entrada
La entrada puede estar en cualquier formato conveniente. El collar debe ser una secuencia de joyas y nada más; Por ejemplo, una lista de enteros, diccionario con claves que representan los tipos de joyas y los valores que son listas de índices. Opcionalmente, puede incluir la longitud del collar o el número de tipos distintos de joyas, pero no debe tomar ninguna otra entrada.
Puede suponer que el collar de entrada es válido. No es necesario manejar el caso donde hay un número impar de joyas de un tipo dado o el collar está vacío.
Salida
Nuevamente, la salida puede estar en cualquier formato conveniente; por ejemplo, una lista de segmentos, una lista de posiciones de corte, un diccionario con claves que representan a los dos ladrones y los valores como listas de segmentos, etc. Los segmentos pueden representarse por su índice inicial, índice final, lista de índices consecutivos, lista de joyas, sus longitudes, etc. Puede usar 0
- o 1
- indexación. Si el orden no es significativo para su formato, entonces su salida puede estar en cualquier orden. Aquí está la salida anterior en varios 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)]}
Tenga en cuenta que el orden es importante en la lista de segmentos (los segmentos se alternan entre los ladrones) y la lista de longitudes (para identificar los segmentos), pero no en la lista de cortes o el diccionario. Editar: Greg Martin señaló que estos no serían resultados válidos ya que se puede obtener una división justa en dos cortes
Casos de prueba
[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
- Las lagunas estándar están prohibidas.
- Este es el código de golf ; la respuesta más corta (en bytes) gana.
fuente
[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 la salida debería 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]]
, ya que tiene 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]]
. ¿Estoy entendiendo la especificación correctamente?Respuestas:
Brachylog , 13 bytes
Pruébalo en línea!
Nota: el metapredicado
ᵛ
es más nuevo que este desafío.Explicación
Las particiones se enumeran en orden creciente de la cantidad de bloques, por lo que el resultado tendrá la menor cantidad de bloques posible.
fuente
Jalea , 18 bytes
Pruébalo en línea!
No es eficiente: el ejemplo tiene 28 joyas que no funcionarán sin grandes recursos, ya que el primer paso de esta implementación sería crear una lista de las 2 27 posibles particiones.
Devuelve una lista de listas: los segmentos en el orden para distribuirlos entre ladrones alternativos. (Re la salida TIO: cuando una lista solo tiene un único elemento, la impresión implícita no molesta con los corchetes
[]
)¿Cómo?
fuente
Mathematica, 118 bytes
Casi venció a Jelly ... solo 1 de descuento;)
Función pura tomando tres argumentos: el collar, como una lista de tokens como
{A, A, A, A, B, C, D, B, C, D, B, B}
; la longitud del collar; y el número de tiempos de joya distintos. Devuelve una lista de sublistas en el formulario{{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}
, donde las fichas sin signos negativos van a un ladrón y las fichas con signos negativos van al otro ladrón. (Si bien esta es información redundante, el algoritmo conduce a esta representación, y eliminar los signos negativos costaría varios bytes).Primero tenemos que implementar una función que tome una lista y un conjunto de
n
lugares de corte y devuelva la lista den+1
sublistas obtenidas cortando la lista de entrada en esosn
lugares de corte; el operador infijo binario±
se usa para este propósito y se define de forma recursiva a través del_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};
. Debido al signo negativo justo despuésAppend
, el resultado es que las sublistas alternativamente tienen y no tienen signos negativos adjuntos a cada token.Luego generamos todos los conjuntos de lugares de corte posibles cuya longitud es como máximo el número de tipos de joyas, utilizando
Range@#2~Subsets~#3
y utilizamosi=#;(i±#)&/@
para aplicar el±
operador (con la lista de entrada de joyas) a cada uno de estos conjuntos de lugares de corte a su vez.Finalmente,
SelectFirst[...,Tr[Tr/@#]==0&]&
elige la primera de las divisiones de collar resultantes que es justa. Lo hace al agregar literalmente todos los elementos en todas las sublistas; Mathematica es lo suficientemente inteligente como para cancelar las copias positivas y negativas de cada token de la manera obvia.fuente
Pyth, 16 bytes
Pruébelo en línea: Demostración o conjunto de pruebas
Explicación:
fuente
05AB1E , 14 bytes
Pruébelo en línea o verifique todos los casos de prueba .
Explicación:
fuente