Genera combinazioni con sostituzione


10

Elenca tutte le combinazioni con sostituzione (o combinazioni con ripetizione) di dimensione k da un set di n elementi.

Una combinazione con la sostituzione è un multiset non ordinato che ogni elemento in esso contenuto è anche nell'insieme di n elementi. Nota che:

  • Non è ordinato. Quindi un set precedentemente stampato con un ordine diverso non dovrebbe essere stampato di nuovo.
  • È un multiset. Lo stesso elemento può (ma non è richiesto) apparire più di una volta. Questa è l'unica differenza tra una combinazione con sostituzione e una combinazione normale.
  • Il set dovrebbe avere esattamente k elementi.

In alternativa, è anche un sottoinsieme di dimensioni k del multiset che contiene ciascuno degli n elementi k volte.

L'input dovrebbe essere n e k , dove gli elementi sono i primi n numeri interi positivi o non negativi, oppure gli elementi n e k , dove si può presumere che gli elementi n siano tutti diversi l'uno dall'altro.

L'output dovrebbe essere un elenco di tutte le combinazioni con sostituzione con dimensione k dal set specificato. Puoi stamparli e gli elementi in ognuno di essi in qualsiasi ordine.

Non è possibile utilizzare i builtin che generano combinazioni con sostituzione. Ma puoi usare i builtin per generare normali combinazioni, permutazioni, tuple, ecc.

Questo è code-golf, vince il codice più corto.

Esempio

Input: 4 2
Output: [0 0] [0 1] [0 2] [0 3] [1 1] [1 2] [1 3] [2 2] [2 3] [3 3]

Risposte:


8

Gelatina, 4 byte

Grazie a Sp3000 per aver salvato 2 byte.

ṗṢ€Q

L'input è ne kcome argomenti della riga di comando in quell'ordine. Usa elementi 1per n.

Provalo online!

Spiegazione

ṗ     # Get k-th Cartesion power of n.
 Ṣ€   # Sort each tuple.
   Q  # Remove duplicates.

8

CJam (8 byte)

{m*:$_&}

Demo online

Dissezione

{    e# Declare block (anonymous function); parameters are n k
  m* e# Cartesian product, which implicitly lifts n to [0 1 ... n-1]
  :$ e# Sort each element of the Cartesian product, to give them canonical forms
  _& e# Deduplicate
}

3

Mathematica, 31 29 byte

Grazie ad A Simmons per aver salvato 2 byte.

{}⋃Sort/@Range@#~Tuples~#2&

Una funzione senza nome che accetta ne kcome argomenti interi in quell'ordine e restituisce un elenco di elenchi. Gli elementi saranno 1a n. Funziona allo stesso modo della risposta CJam di Peter.


@ jimmy23013 Non ne sono a conoscenza.
Martin Ender

Penso che puoi salvare due byte con{}∪Sort/@Range@#~Tuples~#2&
A Simmons

@ASimmons Bella idea, grazie!
Martin Ender

3

MATL , 11 byte

(C'è una soluzione a 9 byte basata sul potere cartesiano, ma Peter Taylor l'ha già fatto . Proviamo qualcosa di diverso).

Le combinazioni con la sostituzione possono essere ridotte a combinazioni senza sostituzione come segue. Noi vogliamo n Cr k, per esempio con n=3, k=2:

0 0
0 1
0 2
1 1
1 2
2 2

Possiamo calcolare n+k-1 C k:

0 1
0 2
0 3
1 2
1 3
2 3

e quindi sottrarre 0 1 ... k-1da ogni riga:

+q:2GXn2G:-

Spiegazione:

+q     % take two inputs n, k and compute n+k-1
:      % range [1,2...,n+k-1]
2G     % push second input, k
Xn     % combinations without replacement
2G:    % range [1,2,...,k]
-      % subtract with broadcast. Display

Il codice funziona nella versione 13.1.0 del linguaggio / compilatore, che è precedente alla sfida.

Puoi provarlo online! Si noti che il compilatore online è stato aggiornato alla versione 14.0.0, quindi Xndeve essere modificato in XN.


3

JavaScript (Firefox 30-57), 71 byte

f=(n,k)=>k?[for(m of Array(n).keys())for(a of f(m+1,k-1))[...a,m]]:[[]]

Posso usarlo keys()per una volta.


2

Rubino, 56 55 byte

Due soluzioni, sorprendentemente entrambe della stessa lunghezza:

->n,k{[*1..n].repeated_permutation(k).map(&:sort).uniq}
->n,k{(a=[*1..n]).product(*[a]*(k-1)).map(&:sort).uniq}

Ehi, tu hai detto che potremmo usare i comandi incorporati di permutazione ...

Questo genera semplicemente tutte le permutazioni ripetute (la seconda genera prodotti cartesiani ripetuti) e rimuove quelle che non sono in ordine.

Grazie a Martin per aver salvato un byte con 0...n-> 1..n!


1

Pyth, 7 byte

{SM^UQE

Utilizza lo stesso algoritmo della risposta di Peter.

    UQ   range(input())
      E  input()
   ^     repeated Cartesian product of ^^, ^ times
 SM      map(sort)
{        uniq

1

Python, 63 byte

f=lambda n,k:n*k and[l+[n]for l in f(n,k-1)]+f(n-1,k)or[[]][k:]

Un metodo ricorsivo. Per creare un insieme multiplo di kelementi, 1a n, scegliamo di:

  • Includi un'altra istanza di n, e resta da fare un multiset di k-1elementi da 1an
  • Non includere un'altra istanza di n, e resta da fare un multiset di kelementi da a 1an-1

Terminiamo quando uno ko nraggiunge 0, e se ha kraggiunto 0, diamo un caso base dell'elenco vuoto. In caso contrario, abbiamo un numero errato di elementi e quindi forniamo l'elenco vuoto.


1

Python 3, 81 80

Soluzione ricorsiva:

t=lambda n,k,b=0:[[]]if k<=0 else [[i]+l for i in range(b,n)for l in t(n,k-1,i)]

La funzione t(n, k, b)restituisce l'elenco di tutti ki sottoinsiemi di tutti gli elementi dell'intervallo da ba n. Questo elenco è vuoto se k <= 0. Altrimenti, risolviamo il problema in base all'elemento più piccolo del sottoinsieme, che denotiamo i.

Per ognuno inell'intervallo da ba n, generiamo tutti i k-multi-sottoinsiemi con l'elemento più piccolo iiniziando con [i]e quindi aggiungendo ogni (k-1)-sottoinsieme dell'intervallo da ia n, che otteniamo chiamando ricorsivamente t(n, k-1, i).


Benvenuto in Programmazione di puzzle e codice golf! Questa è una bella prima risposta. Potresti fornire una spiegazione di come funziona il codice?
Alex A.

Sembra fantastico. Bella soluzione!
Alex A.

1

Dyalog APL , 22 byte

{∪{⍵[⍋⍵]}¨↓⍉⍺⊥⍣¯1⍳⍺*⍵}

Richiede ⎕IO←0, che è predefinito in molti sistemi APL. Prende k come argomento di sinistra, n come argomento di destra.

⍳⍺*⍵0 1 2 ... kⁿ
⍺⊥⍣¯1converti in k base
trasponi la
matrice in un elenco di elenchi
{⍵[⍋⍵]}¨ordina ogni ...
l'unico


1

J, 18 byte

[:~.#~<@/:~@#:i.@^

Approccio simile utilizzato nella soluzione di @Adám .

Un altro approccio che utilizza il prodotto cartesiano {per 24 byte. Assume kl'LHS e nl'RHS.

~.@:(/:~&.>)@,@{@(#<@i.)

uso

   f =: [:~.#~<@/:~@#:i.@^
   4 f 2
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│0 0│0 1│0 2│0 3│1 1│1 2│1 3│2 2│2 3│3 3│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

Spiegazione

[:~.#~<@/:~@#:i.@^ Input: n on LHS and k on RHS
                 ^ Compute n^k
              i.@  Create a range [0, 1, ... n^k-1]
    #~             Create k copies on n
            #:     On each value in the range above, convert each digit to base-n
                   and take the last k digits of it
        /:~@       For each array of digits, sort it in ascending order
      <@           Box each array of digits
[:~.               Take the distinct values in the array of boxes and return it

1

Clojure, 94 byte

(defn f[k n](if(= 1 k)(for[i(range n)][i])(sort(set(for[i(f(dec k)n)j(range n)](conj i j))))))

Nota l'ordine dei parametri modificato: 1 ° è ke 2 ° è n. Questo ha salvato 1 byte in (f(dec k)n).


0

Mathematica, 36 byte

{##}&~Array~Table@##~Flatten~(#2-1)&

Per favore, dimmi che c'è un bonus di 1/6 per l'utilizzo di no [] s ... O forse per i molti usi di ##?

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.