J'ai récemment vu cette question sur stackoverflow. C'est une excellente question, mais il y a un problème fatal avec la question. Ils demandent la meilleure façon de le faire. Par exemple, les plus faciles à lire, les plus idiomatiques, les plus soignés, etc. Ne savent-ils pas que ce n'est pas ce qui compte? Vous êtes censé demander comment le faire avec le moins d'octets de code!
Comme je doute que cette question soit appréciée sur stackoverflow, j'ai décidé de la poser ici.
Le défi
Vous devez écrire le programme ou la fonction la plus courte possible qui génère toutes les manières possibles d'entrelacer deux chaînes arbitraires. Par exemple, si les deux chaînes sont 'ab'
et 'cd'
, la sortie est:
['abcd', 'acbd', 'acdb', 'cabd', 'cadb', 'cdab']
Comme vous pouvez le voir, a
c'est toujours avant b
, et c
c'est toujours avant d
.
IO peut être dans n'importe quel format raisonnable. Utilisez ce code python pour vérifier et vérifier votre sortie. (crédit: 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
Exemple d'E / S:
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']
Comme d'habitude, les failles standard s'appliquent et la réponse la plus courte en octets l'emporte. Puisque la question portait à l'origine sur python, j'aimerais voir la réponse la plus courte en python. (Et non, pyth n'est pas python). Cependant, les réponses dans n'importe quelle langue sont encouragées.
la source
Réponses:
Pyth, 26
Essayez-le ici
Il s'agit d'une implémentation très basique de la formule récursive donnée. Il définit une fonction
g
qui exécute la tâche requise. Le lien est un programme modifié qui lit les chaînes de la nouvelle ligne STDIN séparément, pour plus de commodité. Pour appeler la fonction, faitesg<string1><string2>
.Expansion:
Les deux appels récursifs sont très similaires, mais je n'ai plus réussi à les jouer au golf.
la source
Haskell,
5348 octetsDéfinit une fonction
%
pour laquellea%b
avec des chaînesa,b
donne une liste de chaînes.Étant donné deux chaînes, nous choisissons l'une des deux pour prendre le premier caractère. Nous répétons ensuite le reste des deux chaînes, en ajoutant ce caractère à chaque résultat.
Lorsque l'une des chaînes est vide, le seul résultat possible est l'autre chaîne.
""%""=[""]
serait également suffisant, mais c'est plus long.53 octets:
Définit une fonction
%
pour laquellea%d
avec des chaînesa,d
donne une liste de chaînes.La fonction est définie récursivement. Si nous prenons un caractère de la première chaîne, il doit être ajouté à chaque résultat de l'appel récursif sur le reste de la première chaîne avec la deuxième chaîne. Symétriquement pour l'autre chaîne.
Pour le cas de base, si l'une des chaînes est vide, le résultat est une liste à un élément de leur concaténation. C'est plus court que deux cas pour chaque chaîne étant vide.
la source
""%""=[""]
.Haskell, 47
%
est l'opérateur qui résout ce défi.#
est un opérateur qui prend deux listes et trouve toutes les façons de les entrelacer de telle sorte que le premier caractère soit de la première chaîne (avec un cas de bord - si la première liste est vide, alors le résultat est une liste vide) en récursif à%
.puis,
%
fonctionne en appliquant simplement#
deux fois.Edit: La version précédente avait un bug dans lequel
""%""
retourné["",""]
, donc je l'ai corrigé. Il a été corrigé en ajoutant un cas de base à%
, ce qui a ensuite permis de supprimer un cas de base de la même longueur#
(ce qui n'avait vraiment pas beaucoup de sens).la source
(#) :: [a]->[a]->[[a]]
, donca::[a]
et le résultat devrait être de type[[a]]
Python 2, 71 octets
Exemple d'exécution:
Étant donné deux chaînes,
x,y
nous pouvons prendre le premier caractère dex
et l'ajouter à chaque résultat de l'appel récursif manquantf(x[1:],y)
. Ou, nous pouvons faire de même avecx
ety
commuté. En prenantx,y
soit l'entréep
soit son inversion `p [:: - 1], nous obtenons les deux possibilités.Pour éviter de prendre dans une chaîne vide
x
, on court-circuite logiquement avecx and
. Si les deux chaînes sont vides, aucune chaîne ne peut l'êtrex
et nous obtenons une liste de possibilités vide, que nous corrigeons avecor
le cas de base correct['']
.Une stratégie générative similaire en Python 3 (73 octets):
la source
Python, 80
Comme demandé, voici une réponse en python:
Merci Sp3000 pour avoir mangé 4 octets :)
la source
CJam, 38
Essayez-le en ligne
Programmation dynamique (utilisant la récursion mémorisée).
Explication:
la source
CJam, 32 octets
Testez-le ici.
Cela semble vraiment jouable au golf, mais jusqu'à présent, je n'ai trouvé que 4 solutions alternatives qui ont toutes le même nombre d'octets:
L'idée de base est de générer toutes les permutations de
0
s et1
s correspondant à quelle chaîne prendre chaque caractère du résultat. C'est tout jusqu'à et y compris lee!
. Le reste extrait simplement les caractères dans cet ordre des deux chaînes.la source
e*
et.*
qui répète chaque élément d'une quantité différente. ;) (Soit un opérateur de faire:a.*:~
je suppose.e*
Pourrait être utilisé pour cela car elle actuellement des difficultés si on leur donne deux listes).JavaScript (Firefox 30-57),
888481 octetsEdit: sauvé 4 octets en améliorant ma condition de terminaison. Sauvegardé 3 octets grâce à @ edc65.
la source
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
comme condition, mais il ne m'est jamais venu à l'esprit de l'utiliserv[1]
.Brachylog , 8 octets
Essayez-le en ligne!
Prend l'entrée sous la forme d'une liste de deux chaînes via la variable d'entrée et génère tous les entrelacements possibles via la variable de sortie. Étant donné que les cas de test semblent permettre des entrelacements en double là où il y a des lettres partagées, je n'ai pas pris soin de les éviter, mais cela génère beaucoup plus de doublons et pas seulement avec des lettres partagées. (Si cela n'est pas autorisé, mais que les doublons de lettres partagées ne sont pas nécessaires, ajoutez simplement trois octets pour envelopper la
{}ᵘ
sortie sous forme de liste sans doublons.)Essentiellement, cela génère chaque partition des deux chaînes, puis les entrelace de la manière déterministe normale dans l'un ou l'autre ordre. Les entrelacements en double supplémentaires sont dus à des paires de partitions où la différence entre la longueur du premier et la longueur du second a une valeur autre que 0 ou 1, de sorte que l'un d'eux a des morceaux qui se concaténent à la fin. Donc, pour produire une sortie avec les mêmes multiplicités que la sortie échantillon:
Brachylog , 17 octets
Essayez-le en ligne!
Le code supplémentaire,,
{lᵐ-ℕ<2&}
échoue à toute paire de partitions où des divisions étrangères sont effectuées. (J'ai modifié l'en-tête sur TIO pour l'imprimer avec des guillemets pour une vérification plus facile des sorties dans le shell Python.)la source
MATL ,
3430 octetsCela utilise une idée de cette réponse : si les longueurs des chaînes sont
m
etn
, énumérer tousm+n
les modèles dem
bits avec des bits définis. Une façon de faire cette énumération est de générer toutes les permutations d'un vecteur avec desm
uns et desn
zéros, puis de supprimer les doublons.Essayez-le en ligne!
Explication
la source
Rubis, 83 octets
Une fonction récursive qui retourne
[a+b]
si l'une de ces chaînes est vide. Sinon, il renvoie une liste de chaînesa[0] + every string in v[a[1..-1],b]
ajoutées à une liste de chaînesb[0] + every string in v[a,b[1..-1]]
la source
Lot,
154152 octetsla source