Recientemente vi esta pregunta en stackoverflow. Es una gran pregunta, pero hay un problema fatal con la pregunta. Piden la mejor manera de hacerlo. Por ejemplo, el más fácil de leer, el más idiomático, el más ordenado, etc. ¿No saben que eso no es lo que importa? ¡Se supone que debes preguntar cómo hacerlo con la menor cantidad de bytes de código!
Como dudo que esa pregunta sea apreciada en stackoverflow, decidí preguntarla aquí.
El reto
Debe escribir el programa o función más breve posible que genere todas las formas posibles de intercalar dos cadenas arbitrarias. Por ejemplo, si las dos cadenas son 'ab'
y 'cd'
, la salida es:
['abcd', 'acbd', 'acdb', 'cabd', 'cadb', 'cdab']
Como puede ver, a
siempre está antes b
y c
siempre está antes d
.
IO puede estar en cualquier formato razonable. Use este código de Python para verificar y verificar su salida. (crédito: JeD )
def shuffle(s,t):
if s=="":
return [t]
elif t=="":
return [s]
else:
leftShuffle=[s[0]+val for val in shuffle(s[1:],t)]
rightShuffle=[t[0]+val for val in shuffle(s,t[1:])]
leftShuffle.extend(rightShuffle)
return leftShuffle
Muestra IO:
shuffle("$", "1234"):
['$1234', '1$234', '12$34', '123$4', '1234$']
shuffle("az", "by"):
['azby', 'abzy', 'abyz', 'bazy', 'bayz', 'byaz']
shuffle("code", "golf"):
['codegolf', 'codgeolf', 'codgoelf', 'codgolef', 'codgolfe', 'cogdeolf', 'cogdoelf',
'cogdolef', 'cogdolfe', 'cogodelf', 'cogodlef', 'cogodlfe', 'cogoldef', 'cogoldfe',
'cogolfde', 'cgodeolf', 'cgodoelf', 'cgodolef', 'cgodolfe', 'cgoodelf', 'cgoodlef',
'cgoodlfe', 'cgooldef', 'cgooldfe', 'cgoolfde', 'cgoodelf', 'cgoodlef', 'cgoodlfe',
'cgooldef', 'cgooldfe', 'cgoolfde', 'cgolodef', 'cgolodfe', 'cgolofde', 'cgolfode',
'gcodeolf', 'gcodoelf', 'gcodolef', 'gcodolfe', 'gcoodelf', 'gcoodlef', 'gcoodlfe',
'gcooldef', 'gcooldfe', 'gcoolfde', 'gcoodelf', 'gcoodlef', 'gcoodlfe', 'gcooldef',
'gcooldfe', 'gcoolfde', 'gcolodef', 'gcolodfe', 'gcolofde', 'gcolfode', 'gocodelf',
'gocodlef', 'gocodlfe', 'gocoldef', 'gocoldfe', 'gocolfde', 'goclodef', 'goclodfe',
'goclofde', 'goclfode', 'golcodef', 'golcodfe', 'golcofde', 'golcfode', 'golfcode']
Como de costumbre, se aplican las lagunas estándar y gana la respuesta más corta en bytes. Dado que la pregunta era originalmente sobre Python, me encantaría ver la respuesta más corta de Python. (Y no, pyth no es python). Sin embargo, se alientan las respuestas en cualquier idioma.
fuente
Respuestas:
Pyth, 26
Pruébalo aquí
Esta es una implementación muy básica de la fórmula recursiva dada. Define una función
g
que realiza la tarea requerida. El enlace es un programa modificado que lee las cadenas de la nueva línea STDIN separadas, para ser más conveniente. Para llamar a la función dog<string1><string2>
.Expansión:
Las dos llamadas recursivas son muy similares, pero ya no he podido encontrar una manera de jugar golf.
fuente
Haskell,
5348 bytesDefine una función
%
para la cuala%b
con cadenasa,b
da una lista de cadenas.Dadas dos cadenas, elegimos una de las dos para tomar el primer personaje. Luego recurrimos en el resto de dos cadenas, anteponiendo ese carácter a cada resultado.
Cuando una de las cadenas está vacía, el único resultado posible es la otra cadena.
""%""=[""]
También sería suficiente, pero es más largo.53 bytes:
Define una función
%
para la cuala%d
con cadenasa,d
da una lista de cadenas.La función se define de forma recursiva. Si tomamos un carácter de la primera cadena, debe anteponerse a cada resultado de la llamada recursiva en el resto de la primera cadena con la segunda cadena. Simétricamente para la otra cuerda.
Para el caso base, si una de las cadenas está vacía, el resultado es una lista de un solo elemento de su concatenación. Esto es más corto que dos casos para cada cadena que está vacía.
fuente
""%""=[""]
.Haskell, 47
%
es el operador que resuelve este desafío.#
es un operador que toma dos listas y encuentra todas las formas de intercalarlas de modo que el primer carácter sea de la primera cadena (con un caso de borde, si la primera lista está vacía, entonces el resultado es una lista vacía) recurriendo a%
.entonces,
%
funciona simplemente aplicando#
dos veces.Editar: La versión anterior tenía un error en el que
""%""
regresó["",""]
, así que lo arreglé. Se solucionó agregando un caso base a%
, que luego permitió eliminar un caso base de la misma longitud#
(que realmente no tenía mucho sentido).fuente
(#) :: [a]->[a]->[[a]]
, por lo quea::[a]
el resultado debería ser de tipo[[a]]
Python 2, 71 bytes
Ejemplo de ejecución:
Dadas dos cadenas
x,y
, podemos tomar el primer carácterx
y anteponerlo a cada resultado de la llamada recursiva sin élf(x[1:],y)
. O podemos hacer lo mismo conx
yy
cambiar. Al tomarx,y
como entradap
o como inversión `p [:: - 1], obtenemos ambas posibilidades.Para evitar tomar de una cadena vacía
x
, hacemos un cortocircuito lógico conx and
. Si ambas cadenas están vacías, ninguna cadena puede serx
y obtenemos una lista vacía de posibilidades, que corregimos conor
el caso base correcto['']
.Una estrategia generativa similar en Python 3 (73 bytes):
fuente
Python, 80
Según lo solicitado, aquí hay una respuesta de Python:
Gracias Sp3000 por comer 4 bytes :)
fuente
CJam, 38
Pruébalo en línea
Programación dinámica (usando recursión memorable).
Explicación:
fuente
CJam, 32 bytes
Pruébalo aquí.
Esto se siente realmente golfable, pero hasta ahora solo he encontrado 4 soluciones alternativas que tienen el mismo número de bytes:
La idea básica es generar todas las permutaciones de
0
s y1
S que corresponde a qué cadena de tomar cada carácter en el resultado de. Eso es todo, incluido ele!
. El resto simplemente saca caracteres en ese orden de las dos cadenas.fuente
e*
y.*
que repita cada elemento en una cantidad diferente. ;) (Es decir, un operador que hacer:a.*:~
. Supongo quee*
podría usarse para eso, ya que actualmente se equivoca si se le dan dos listas.)JavaScript (Firefox 30-57),
888481 bytesEditar: guardado 4 bytes al mejorar mi condición de terminación. Guardado 3 bytes gracias a @ edc65.
fuente
f=(a,b,z=(v,w)=>v[1]?f(v.slice(1),w).map(x=>v[0]+x):[v+w])=>z(a,b).concat(z(b,a))
v
como condición, pero nunca se me ocurrió usarlov[1]
.Brachylog , 8 bytes
Pruébalo en línea!
Toma la entrada como una lista de dos cadenas a través de la variable de entrada y genera todos los entrelazamientos posibles a través de la variable de salida. Dado que los casos de prueba parecen permitir entrelazados duplicados donde hay letras compartidas, no he tenido cuidado de evitarlos, pero esto genera muchos más duplicados y no solo con letras compartidas. (Si esto no está permitido, pero los duplicados de letras compartidas no son necesarios, solo agregue tres bytes para envolverlos
{}ᵘ
para la salida como una lista sin duplicados).Esencialmente, esto genera cada partición de ambas cadenas, luego las intercala en la forma determinista normal en cualquier orden. Los entrelazados duplicados adicionales se deben a pares de particiones donde la diferencia entre la longitud de la primera y la longitud de la segunda tiene algún valor distinto de 0 o 1, de modo que uno de ellos tiene fragmentos que se concatenan entre sí al final. Entonces, para producir una salida con las mismas multiplicidades que la salida de muestra:
Brachylog , 17 bytes
Pruébalo en línea!
El código extra
{lᵐ-ℕ<2&}
falla cualquier par de particiones donde se realizan divisiones extrañas. (Modifiqué el encabezado en TIO para imprimir con comillas para facilitar la comprobación de salida en el shell de Python).fuente
MATL ,
3430 bytesEsto utiliza una idea de esta respuesta : si las longitudes de las cadenas son
m
yn
, enumere todosm+n
los patrones dem
bits con los bits establecidos. Una forma de hacer esa enumeración es: generar todas las permutaciones de un vector conm
unos yn
ceros y luego eliminar duplicados.Pruébalo en línea!
Explicación
fuente
Ruby, 83 bytes
Una función recursiva que devuelve
[a+b]
si cualquiera de esas cadenas está vacía. De lo contrario, devuelve una lista de cadenasa[0] + every string in v[a[1..-1],b]
agregadas a una lista de cadenasb[0] + every string in v[a,b[1..-1]]
fuente
Lote,
154152 bytesfuente