Enumerar las combinaciones de elementos en un conjunto.

10

Dado un conjunto de nelementos, el desafío es escribir una función que enumere todas las combinaciones de kelementos de este conjunto.

Ejemplo

Set: [1, 7, 4]
Input: 2
Output: [1,7], [1,4], [7,4]

Ejemplo

Set: ["Charlie", "Alice", "Daniel", "Bob"]
Input: 2
Output ["Daniel", "Bob"], ["Charlie", "Alice"], ["Alice", "Daniel"], ["Charlie", "Daniel"], ["Alice", "Bob"], ["Charlie",  "Bob"]

Reglas (editadas)

  • El orden de salida es de su elección.
  • La entrada puede ser cualquier tipo de datos. Pero la salida debe ser del mismo tipo que la entrada. Si la entrada es una lista de enteros, la salida también debería ser una lista de enteros. Si la entrada es una cadena (matriz de caracteres), la salida también debería ser una cadena.
  • El código debería funcionar con cualquier número de variables de entrada.
  • Puedes usar cualquier lenguaje de programación.
  • La respuesta también debería poder usar cualquier cosa (string, int, double ...) como entrada y salida.
  • Se prohíbe cualquier función integrada que esté relacionada con combinaciones y permutaciones.
  • El código más corto gana (en términos de bytes).
  • Desempate: votos.
  • Duración: 1 semana.

PD Tenga cuidado con las entradas extremas como números negativos, 0, etc.

padawan
fuente
1
Aunque codegolf.stackexchange.com/questions/6380/… tiene una restricción adicional, sus respuestas podrían copiarse sin cambios y aún serían difíciles de superar.
Peter Taylor
1
Por La entrada puede ser cualquier tipo de datos. ¿te refieres a algún tipo de datos iterables o un iterable lleno de cualquier tipo de datos? Por ejemplo, ¿es combos('ab', 1) -> ['a', 'b']válido?
Aficiones de Calvin
1
¿Cuál debería ser la salida si la entrada es negativa?
Ypnypn
55
No veo cómo esta pregunta es un duplicado de "Generar combinaciones sin recursividad" cuando casi todas las respuestas hasta ahora usan la recursividad.
xnor
2
La eliminación de una restricción no es un cambio significativo. Además, usar las respuestas existentes para determinar qué es o no un duplicado no es una buena idea, ya que no podría identificar duplicados hasta que ya hayan sido respondidos. A veces solo tienes que usar tu cabeza.
Rainbolt

Respuestas:

13

Haskell - 57 46 bytes

Adelante, golfscripters.

0%_=[[]]
n%(x:y)=map(x:)((n-1)%y)++n%y
_%_=[]

Caso de uso (la misma función funciona polimórficamente):

2% [1,2,3,4] ➔ [[1,2], [1,3], [1,4], [2,3], [2,4], [3,4]]

3% "trampa" ➔ ["che", "cha", "cht", "cea", "cet", "cat", "hea", "het", "hat", "eat"]

2% ["Charlie", "Alice", "Daniel", "Bob"] ➔ [["Charlie", "Alice"], ["Charlie", "Daniel"], ["Charlie", "Bob"] , ["Alice", "Daniel"], ["Alice", "Bob"], ["Daniel", "Bob"]]

ChaseC
fuente
1
Gracias Mark, ni siquiera consideré hacerlo infijo.
ChaseC
Por cierto, ¿qué significa "traerlo" en su dialecto? En el mío implica un desafío, pero eso no tiene sentido en contexto porque su versión final es aún más larga que mi versión inicial en la pregunta que duplica.
Peter Taylor
7

Pitón (72)

f=lambda S,k:S and[T+S[:1]for T in f(S[1:],k-1)]+f(S[1:],k)or[[]]*(k==0)

La función ftoma una lista Sy el número ky devuelve una lista de todas las sub-listas de longitud kde S. En lugar de enumerar todos los subconjuntos y luego filtrar por tamaño, solo obtengo los subconjuntos del tamaño necesario en cada paso.

Me gustaría ir S.pop()a trabajar para combinar obtener S[:1]con pasar S[1:]más tarde, pero parece consumir demasiado la lista.

Para evitar la objeción, cualquiera de estas soluciones de Python rompe la regla de que "el código debería funcionar en cualquier número de variables de entrada" debido a los límites de recursión, notaré que la implementación de Stackless Python no tiene límites de recursión (aunque en realidad no he probado este código con él).

Demostración:

S = [1, 2, 6, 8]
for i in range(-1,6):print(i, f(S,i))

#Output:    
-1 []
0 [[]]
1 [[1], [2], [6], [8]]
2 [[2, 1], [6, 1], [8, 1], [6, 2], [8, 2], [8, 6]]
3 [[6, 2, 1], [8, 2, 1], [8, 6, 1], [8, 6, 2]]
4 [[8, 6, 2, 1]]
5 []
xnor
fuente
3

Mathematica 10, 70 caracteres

Solo una traducción de la respuesta de Haskell.

_~f~_={};_~f~0={{}};{x_,y___}~f~n_:=Join[Append@x/@f[{y},n-1],{y}~f~n]

Uso:

En [1]: = f [{1, 7, 4}, 2]

Fuera [1] = {{7, 1}, {4, 1}, {4, 7}}

alephalpha
fuente
3

Carbón , 23 bytes

EΦEX²Lθ⮌↨ι²⁼ΣιηΦ…θLι§ιμ

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

    ²                   Literal 2
   X                    Raised to power
     L                  Length of
      θ                 Input array
  E                     Mapped over implicit range
         ι              Current index
        ↨               Converted to base
          ²             Literal 2
       ⮌                Reversed
 Φ                      Filtered on
            Σ           Digital sum of
             ι          Current base 2 value
           ⁼            Equal to
              η         Input `k`
E                       Mapped to
                 θ      Input array
                …       Chopped to length
                  L     Length of
                   ι    Current base 2 value
               Φ        Filtered on
                     ι  Current base 2 value
                    §   Indexed by
                      μ Current index
Neil
fuente
2

Python - 129

s es una lista, k es el tamaño de las combinaciones a producir.

def c(s, k):
    if k < 0: return []
    if len(s) == k: return [s]
    return list(map(lambda x: [s[0]]+x, c(s[1:], k-1))) + c(s[1:], k)
Chaqueta De CesioVida
fuente
2

Python, 102

p=lambda s:p(s[1:])+[x+[s[0]]for x in p(s[1:])]if s else[s];c=lambda s,k:[x for x in p(s)if len(x)==k]

Llame a c para ejecutar:

c ([5, 6, 7], 2) => [[6, 7], [5, 7], [5, 6]]

Obtiene todas las permutaciones de la lista sy filtra las que tienen longitud k.

Pasatiempos de Calvin
fuente
2

Pyth , 28

DcGHR?+m+]'HdctGtHcGtHH*]Y!G

Esto se basa (en gran medida) en la respuesta de Haskell.

Explicación:

DcGH                           def c(G,H):
    R                          return
     ?                         Python's short circuiting _ if _ else _
       m+]'Hd                  map to [head(H)]+d
             ctGtH             c(G-1,tail(H))
       m+]'HdctGtH             map [head(H)]+d for d in c(tail(G),tail(H))
      +m+]'HdctGtHcGtH         (the above) + c(G,tail(H))
     ?                H        (the above) if H else (the below)
                       *]Y!G   [[]]*(not G)

Nota: Si bien la versión más reciente de Pyth, 1.0.9, se lanzó esta noche y, por lo tanto, no es elegible para este desafío, el mismo código funciona bien en 1.0.8.

isaacg
fuente
2

Haskell + Data.List , 44 bytes

0%_=[[]]
n%y=do{a:b<-tails y;(a:)<$>(n-1)%b}

Pruébalo en línea!


La respuesta 46 bytes es bastante difícil de superar, pero si usted tiene tailsde Data.Listque puede hacer 44 bytes.

Ad Hoc Garf Hunter
fuente
2

05AB1E , 14 13 bytes

goLε¹ybRÏ}ʒgQ

Inspirado por la respuesta de @Neil 's Charcoal , ¡así que asegúrate de votarlo!

Pruébelo en línea o verifique algunos casos de prueba más .

Si se permitieran las incorporaciones, esto podría haber sido 2 bytes :

Pruébelo en línea o verifique algunos casos de prueba más .

Explicación:

g              # Get the length of the first (implicit) input-list
 o             # Take 2 to the power this length
  L            # Create a list in the range [1, 2**length]
   ε           # Map each integer `y` to:
    ¹          #  Push the first input-list again
     ybR       #  Convert integer `y` to binary, and reverse it
        Ï      #  And only keep values at truthy indices of `y` (so where the bit is a 1)
             # After the map: filter the list of lists by:
           g   #  Where the length of the inner list
            Q  #  Is equal to the (implicit) input-integer
               # (then the result is output implicitly)

             # Get all `b`-element combinations in list `a`,
               # where `b` is the first (implicit) input-integer,
               # and `a` is the second (implicit) input-list
               # (then the result is output implicitly)
Kevin Cruijssen
fuente
2

APL (NARS), 80 caracteres, 160 bytes

{h←{0=k←⍺-1:,¨⍵⋄(k<0)∨k≥i←≢w←⍵:⍬⋄↑,/{w[⍵],¨k h w[(⍳i)∼⍳⍵]}¨⍳i-k}⋄1≥≡⍵:⍺h⍵⋄⍺h⊂¨⍵}

prueba y cómo usarlo:

  f←{h←{0=k←⍺-1:,¨⍵⋄(k<0)∨k≥i←≢w←⍵:⍬⋄↑,/{w[⍵],¨k h w[(⍳i)∼⍳⍵]}¨⍳i-k}⋄1≥≡⍵:⍺h⍵⋄⍺h⊂¨⍵}
  o←⎕fmt
  o 5 f 1 2 3 4
┌0─┐
│ 0│
└~─┘
  o 4 f 1 2 3 4 
┌1─────────┐
│┌4───────┐│
││ 1 2 3 4││
│└~───────┘2
└∊─────────┘
  o 3 f 1 2 3 4
┌4──────────────────────────────────┐
│┌3─────┐ ┌3─────┐ ┌3─────┐ ┌3─────┐│
││ 1 2 3│ │ 1 2 4│ │ 1 3 4│ │ 2 3 4││
│└~─────┘ └~─────┘ └~─────┘ └~─────┘2
└∊──────────────────────────────────┘
  o 2 f 1 2 3 4
┌6────────────────────────────────────────┐
│┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐│
││ 1 2│ │ 1 3│ │ 1 4│ │ 2 3│ │ 2 4│ │ 3 4││
│└~───┘ └~───┘ └~───┘ └~───┘ └~───┘ └~───┘2
└∊────────────────────────────────────────┘
  o 1 f 1 2 3 4
┌4──────────────────┐
│┌1─┐ ┌1─┐ ┌1─┐ ┌1─┐│
││ 1│ │ 2│ │ 3│ │ 4││
│└~─┘ └~─┘ └~─┘ └~─┘2
└∊──────────────────┘
  o 0 f 1 2 3 4
┌0─┐
│ 0│
└~─┘
  o ¯1 f 1 2 3 4
┌0─┐
│ 0│
└~─┘
  o 3 f (0 0)(1 2)(3 ¯4)(4 ¯5)
┌4────────────────────────────────────────────────────────────────────────────────────────────────┐
│┌3────────────────────┐ ┌3────────────────────┐ ┌3─────────────────────┐ ┌3─────────────────────┐│
││┌2───┐ ┌2───┐ ┌2────┐│ │┌2───┐ ┌2───┐ ┌2────┐│ │┌2───┐ ┌2────┐ ┌2────┐│ │┌2───┐ ┌2────┐ ┌2────┐││
│││ 0 0│ │ 1 2│ │ 3 ¯4││ ││ 0 0│ │ 1 2│ │ 4 ¯5││ ││ 0 0│ │ 3 ¯4│ │ 4 ¯5││ ││ 1 2│ │ 3 ¯4│ │ 4 ¯5│││
││└~───┘ └~───┘ └~────┘2 │└~───┘ └~───┘ └~────┘2 │└~───┘ └~────┘ └~────┘2 │└~───┘ └~────┘ └~────┘2│
│└∊────────────────────┘ └∊────────────────────┘ └∊─────────────────────┘ └∊─────────────────────┘3
└∊────────────────────────────────────────────────────────────────────────────────────────────────┘
  o 4 f (0 0)(1 2)(3 ¯4)(4 ¯5)
┌1──────────────────────────────┐
│┌4────────────────────────────┐│
││┌2───┐ ┌2───┐ ┌2────┐ ┌2────┐││
│││ 0 0│ │ 1 2│ │ 3 ¯4│ │ 4 ¯5│││
││└~───┘ └~───┘ └~────┘ └~────┘2│
│└∊────────────────────────────┘3
└∊──────────────────────────────┘
  o 1 f (0 0)(1 2)(3 ¯4)(4 ¯5)
┌4────────────────────────────────────┐
│┌1─────┐ ┌1─────┐ ┌1──────┐ ┌1──────┐│
││┌2───┐│ │┌2───┐│ │┌2────┐│ │┌2────┐││
│││ 0 0││ ││ 1 2││ ││ 3 ¯4││ ││ 4 ¯5│││
││└~───┘2 │└~───┘2 │└~────┘2 │└~────┘2│
│└∊─────┘ └∊─────┘ └∊──────┘ └∊──────┘3
└∊────────────────────────────────────┘
  o 2 f ('Charli')('Alice')('Daniel')('Bob')
┌6──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│┌2─────────────────┐ ┌2──────────────────┐ ┌2───────────────┐ ┌2─────────────────┐ ┌2──────────────┐ ┌2───────────────┐│
││┌6──────┐ ┌5─────┐│ │┌6──────┐ ┌6──────┐│ │┌6──────┐ ┌3───┐│ │┌5─────┐ ┌6──────┐│ │┌5─────┐ ┌3───┐│ │┌6──────┐ ┌3───┐││
│││ Charli│ │ Alice││ ││ Charli│ │ Daniel││ ││ Charli│ │ Bob││ ││ Alice│ │ Daniel││ ││ Alice│ │ Bob││ ││ Daniel│ │ Bob│││
││└───────┘ └──────┘2 │└───────┘ └───────┘2 │└───────┘ └────┘2 │└──────┘ └───────┘2 │└──────┘ └────┘2 │└───────┘ └────┘2│
│└∊─────────────────┘ └∊──────────────────┘ └∊───────────────┘ └∊─────────────────┘ └∊──────────────┘ └∊───────────────┘3
└∊──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  o ¯2 f ('Charli')('Alice')('Daniel')('Bob')
┌0─┐
│ 0│
└~─┘

la salida parece estar bien ... pero los errores son posibles ...

En la práctica, devuelve void set como Zilde si la entrada alfa está fuera de rango; si alfa es 1, devuelve todos los elementos de su conjunto (¿es correcto?);

Esto a continuación parece un par de char menos pero 2 veces más lento arriba:

f←{(⍺>≢⍵)∨⍺≤0:⍬⋄1=⍺:,¨⍵⋄{w[⍵]}¨k/⍨{∧/</¨¯1↓{⍵,¨1⌽⍵}⍵}¨k←,⍳⍺⍴≢w←⍵}
RosLuP
fuente
1

JS - 117188

(a,b,c=[])=>((d=(e,f,g=[])=>f*e?g.push(e)+d(e-1,f-1,g)+g.pop
()+d(e-1,f,g):f||c.push(g.map(b=>a[b-1])))(a.length,b),c)

(<código fuente>) (['' Bob ',' Sally ',' Jonah '], 2)

     [['Jonás', 'Sally'] ['Jonás', 'Bob'] ['Sally', 'Bob']]

Método de matriz locura

combination = (arr, k) =>
    Array
        .apply(0, { length: Math.pow(k+1, arr.length) })
        .map(Number.call, Number)
        .map(a => a
              .toString(arr.length)
              .split('')
              .sort()
              .filter((a, b, c) => c.indexOf(a) == b)
              .join(''))
        .filter((a, b, c) => a.length == k && c.indexOf(a) == b)
        .map(x => x.split('').map(y => arr[+y]))
bebe
fuente
1

C # (compilador interactivo de Visual C #) , 141 bytes

l=>l.Any()?A(l.Skip(1)).Select(x=>l.Take(1).Union(x)).Union(A(l.Skip(1))):new object[][]{new object[]{}};B=(n,l)=>A(l).Where(x=>x.Count()==n)

Lamentablemente, Tio / Mono no parece admitir la declaración genérica de tipo T , por lo que me veo obligado a perder algunos bytes con el tipo de objeto .

//returns a list of all the subsets of a list
A=l=>l.Any()?A(l.Skip(1)).Select(x=>l.Take(1).Union(x)).Union(A(l.Skip(1))):new object[][]{new object[]{}};

//return the subsets of the required size
B=(n,l)=>A(l).Where(x=>x.Count()==n);

Pruébalo en línea!

Innat3
fuente