essayer d'apprendre un peu de scala et courut dans ce problème. J'ai trouvé une solution pour toutes les combinaisons sans répétitions ici et je comprends quelque peu la l'idée em> derrière elle, mais une partie de la syntaxe me fait mal. Je ne pense pas non plus que la solution soit appropriée pour un cas avec des répétitions. Je me demandais si quelqu'un pouvait suggérer un peu de code que je pouvais travailler. J'ai beaucoup de matériel sur la combinatoire et j'ai compris le problème et les solutions itératives, je cherche juste la façon Scala-y de le faire. P>
merci p>
7 Réponses :
La question a été reformulée dans l'une des réponses - j'espère que la question elle-même est également modifiée. Quelqu'un d'autre a répondu à la bonne question. Je laisserai ce code ci-dessous au cas où quelqu'un le trouve utile.
Cette solution est confuse comme l'enfer, en effet. Une "combinaison" sans répétition est appelée permutation. Cela pourrait aller comme ceci: p> si la liste d'entrée n'est pas garantie de contenir des éléments uniques, comme suggéré dans une autre réponse, il peut être un peu plus difficile. Au lieu de filtrer, qui supprime tous les éléments, nous devons retirer uniquement le premier. P> juste un peu d'explication. Dans la mesure, nous prenons chaque élément de la liste et les listes de retour sont composées de celle-ci suivie de la permutation de tous les éléments de la liste, à l'exception de l'élément sélectionné. P> par exemple, si nous prenons la liste (1 , 2,3), nous composerons des listes formées par 1 et Perm (liste (2,3)), 2 et Perm (liste (1,3)) et 3 et perm (liste (1,2)). Puisque nous faisons des permutations de taille arbitraire, nous gardons une trace de combien de temps chaque sous-performatrice peut être. Si une sous-performatrice est la taille 0, il est important de renvoyer une liste contenant une liste vide. Notez que ce n'est pas une liste vide! Si nous sommes retournés nul au cas échéant, il n'y aurait aucun élément pour SL dans la permanente appelante, et l'ensemble "pour" céderait nul. De cette façon, SL sera attribué nul, et nous composerons une liste EL :: NIL, Cording List (El). P> Je pensais au problème initial, et je posterai mon solution ici pour référence. Si vous vouliez dire ne pas avoir des éléments dupliqués dans la réponse à la suite d'éléments dupliqués dans l'entrée, ajoutez simplement un retrait de retrait comme indiqué ci-dessous. P> def comb[T](n: Int, l: List[T]): List[List[T]] = {
def comb1[T](n: Int, l: List[T]): List[List[T]] =
n match {
case 0 => List(List())
case _ => for(i <- (0 to (l.size - n)).toList;
l1 = l.drop(i);
sl <- comb(n-1, l1.tail))
yield l1.head :: sl
}
comb1(n, l).removeDuplicates
}
"Une" combinaison "avec des répétitions est appelée permutation" - jamais dans un million d'années!
@Rokkralj c'était une faute de frappe. :( Merci d'avoir souligné, je l'ai maintenant réparé. Cinq ans plus tard.
Avoir un uppote, alors! Ce n'est toujours pas assez exact, mais mieux.
Daniel - Je ne sais pas ce que Alex signifiait par des duplicats, il se peut que ce qui suit fournit une réponse plus appropriée: exécuté comme p> Ceci donne: p> par opposition à: p> la nezsitude à l'intérieur de la permanente imbriquée Appel est en train de supprimer une seule "El" de la liste, j'imagine qu'il y a une meilleure façon de le faire, mais je ne peux pas penser à un. p> p>
Il suffit d'appliquer enlevez-vous à la sortie du match.
Oh! Je réalise maintenant ce que tu veux dire. J'ai eu ce problème ailleurs, je et je trouve cette étendue, suivie d'une queue à l'un des résultats est assez agréable. Je l'ai mis dans ma réponse ci-dessous, mais si c'est vraiment ce qu'il voulait dire, il veut alors la réponse à la combinaison, pas de permutation. Dans ce cas, il avait juste besoin d'ajouter un retrait à la fonction extérieure.
J'ai écrit une solution similaire au problème de mon blog: http://gabrielsw.blogspot.com/2009/05/my-take-on-99-problems-in-scala-23-a.html
Je pensais d'abord générer toutes les combinaisons possibles et éliminer les doublons (ou les ensembles d'utilisation, qui s'occupe des duplications elles-mêmes), mais comme le problème a été spécifié avec des listes et toutes les combinaisons possibles seraient trop nombreuses, je suis venu Avec une solution récursive au problème: p>
Pour obtenir les combinaisons de la taille N, prenez un élément de l'ensemble et appendez-le à toutes les combinaisons des ensembles de taille N-1 des éléments restants, Union les combinaisons de la taille n des éléments restants.
C'est ce que le code fait p> comment le lire: p> J'ai dû créer une fonction auxiliaire qui "soulever" une liste dans une liste de listes p> La logique est dans l'instruction de correspondance: p> Si vous souhaitez toutes les combinaisons de la taille 1 des éléments de la liste, créez une liste de listes dans lesquelles chaque subliste contient un Elément de l'original (c'est la fonction "Ascenseur") P> Si les combinaisons sont la longueur totale de la liste, renvoyez simplement une liste dans laquelle le seul élément est la liste des éléments (il n'y a qu'une combinaison possible !) p> Sinon, prenez la tête et la queue de la liste, calculez toutes les combinaisons de la taille N-1 de la queue (appel récursif) et appendez la tête à chacune des listes résultantes (.map (ys.head :: zs)) concaténate le résultat avec toutes les combinaisons de la taille N de la queue de la liste (un autre appel récursif) p> a un sens? p> p>
Je comprends votre question maintenant. Je pense que le moyen le plus simple de réaliser ce que vous voulez est de faire ce que vous voulez faire ce qui suit:
> comb(3, List(1,2,3)) > List[List[Int]] = List( List(1, 1, 1), List(1, 1, 2), List(1, 1, 3), List(1, 2, 2), List(1, 2, 3), List(1, 3, 3), List(2, 2, 2), List(2, 2, 3), List(2, 3, 3), List(3, 3, 3)) > comb(6, List(1,2,1,2,1,2,1,2,1,2)) > List[List[Int]] = List( List(1, 1, 1, 1, 1, 1), List(1, 1, 1, 1, 1, 2), List(1, 1, 1, 1, 2, 2), List(1, 1, 1, 2, 2, 2), List(1, 1, 2, 2, 2, 2), List(1, 2, 2, 2, 2, 2), List(2, 2, 2, 2, 2, 2))
Solution élégante, mais malheureusement, elle n'est pas récursive de la queue, alors méfiez-vous de l'utiliser sur de longues listes ...
Entre-temps, les combinaisons sont devenues une partie intégrante des collections Scala: Comme on le voit, il ne permet pas de répéter, mais de leur permettre est simple avec des combinaisons: énumérer chaque élément de votre collection (0 à li.size-1) et de la carte de l'élément dans la liste: P> scala> (0 to li.length-1).combinations (2).toList .map (v=>(li(v(0)), li(v(1))))
res214: List[(Int, Int)] = List((1,1), (1,0), (1,0), (1,0), (1,0), (0,0))
Solution intéressante, mais notez qu'il nécessite que la séquence d'entrée soit indexée ...
C'était ma première pensée lorsque j'ai entendu les répétitions sont ignorées, mais je pense que la génération des indices peut finir de mieux ...
Je préfère cette solution à la réponse acceptée car elle nécessite moins de code et exploite la méthode de combinaisons existante.
Cette solution a été postée sur Rosetta Code: http://roseettacode.org/wiki/comminations_with_repetitions#scala < / a>
Cette solution est fausse; juste essayer peigne (liste (1,1,1,2), 2) code>
Il est correct, il génère les combinaisons avec chaque élément apparaissant jusqu'à K fois. Mais ce list.fill (k) (as) code> est si moche. Je veux dire, vous reproduisez réellement toute la liste K fois au lieu de simplement jeter les éléments dans un ensemble, puis générer correctement les combinaisons de celle-ci ...
Ce n'est vraiment pas clair ce que vous demandez. Cela pourrait être une des rares choses différentes. Tout d'abord seraient des combinaisons simples d'éléments différents dans une liste. Scala offre qu'avec la méthode S'il y a des éléments répétés dans la liste, cependant, Scala générera des combinaisons avec l'élément apparaissant plus d'une fois dans les combinaisons. Mais juste les différentes combinaisons possibles, avec l'élément éventuellement reproduit autant de fois qu'ils existent dans l'entrée. Il génère uniquement l'ensemble des combinaisons possibles, des éléments répétés, mais pas des combinaisons répétées. Je ne sais pas si cela sous-jacent il y a un itérateur à un ensemble Maintenant ce que vous voulez réellement dire si je comprends bien, c'est des combinaisons d'un ensemble donné de différents éléments , lorsqu'un élément peut apparaître à plusieurs reprises n fois dans la combinaison. P> Eh bien, revenant un peu, pour générer des combinaisons lorsqu'il y a des éléments répétés dans l'entrée et que vous voulez voir les combinaisons répétées dans la sortie, La façon d'y aller est juste de le générer par "force brute" en utilisant n boucles imbriquées. Notez qu'il n'y a vraiment rien de brut à ce sujet, il ne s'agit que du nombre naturel de combinaisons, vraiment, qui est O (p ^ n) pour la petite N, et rien que vous puissiez faire à ce sujet. Vous devez seulement veiller à choisir ces valeurs correctement, comme ceci: p> résultant p> ceci génère les combinaisons de ces valeurs répétées en A, en créant d'abord les combinaisons intermédiaires de maintenant pour créer les "combinaisons avec des répétitions "Il suffit de changer les indices comme celui-ci: p> produira p> mais je ne suis pas sûr de ce qui est La meilleure façon de généraliser cela aux combinaisons plus grandes. P> Maintenant, je ferme avec ce que je cherchais quand j'ai trouvé ce post: une fonction permettant de générer les combinaisons d'une entrée contenant des éléments répétés, avec des indices intermédiaires générés par résulte p> combinaisons () code> de collections. Si des éléments sont distincts, le comportement est exactement ce que vous attendez de la définition classique des «combinaisons». Pour les combinaisons N-Element des éléments, il y aura P! / N! (P-N)! Combinaisons dans la sortie.
réel code>. P>
0 jusqu'à A.Size code> as (i, j) ... p>
combinaisons () code>. Il est agréable que cette méthode produit une liste au lieu d'un tuple, cela signifie donc que nous pouvons réellement résoudre le problème à l'aide d'une "carte de la carte", quelque chose que je ne suis pas sûr que quelqu'un d'autre a proposé ici, mais c'est assez artificiel et fera votre amour pour FP et Scala grandir un peu plus après que vous le voyiez! p>
Vous pouvez également coller le code sur la question, le marquant comme code source.
S'il vous plaît, modifiez la question au lieu de le republier comme une "réponse".