Permutações com itens indistinguíveis

12

Dada uma lista de números inteiros, imprima o número de permutações dos números inteiros, com permutações indistinguíveis contadas uma vez. Se houver nnúmeros inteiros e cada grupo de números indistinguíveis tiver comprimento n_i, isso én! / (n_1! * n_2! * ...)

Regras

  • A entrada será uma forma de lista como argumento para uma função ou programa com 1 a 12 números inteiros não negativos.

  • A saída estará imprimindo ou retornando o número de permutações, conforme descrito acima.

  • Não há brechas padrão ou funções internas (gerando permutações, combinações, etc.). Fatoriais são permitidos.

Casos de teste

Entradas:

1, 3000, 2, 2, 8
1, 1, 1
2, 4, 3, 2, 3, 4, 4, 4, 4, 4, 1, 1

Saídas:

60
1
83160
qwr
fonte
quando você diz que não há builtins, isso inclui o que fiz quando usei um builtin para gerar todas as permutações?
Maltysen
1
Isso parece basicamente o mesmo que Computar o coeficiente multinomial . Contar entradas idênticas para a entrada faz com que seja suficientemente diferente para não ser um tolo?
Xnor
@ xnor bem, aqui você realmente precisa contar as duplicatas, portanto não é tão simples assim. O outro é basicamente conectar valores.
QWR
@Maltysen infelizmente sim, vou ter que atualizar a questão
QWR
1
@LuisMendo Sim, é, no entanto, não deve fazer a diferença, tanto quanto eu posso imaginar
QWR

Respostas:

6

Python, 48 bytes

f=lambda l:l==[]or len(l)*f(l[1:])/l.count(l[0])

Uma implementação recursiva.

Na fórmula, n! / (n_1! * n_2! * ...)se removermos o primeiro elemento (digamos que seja 1), o número de permutação para os n-1elementos restantes é

(n-1)! / ((n_1-1)! * n_2! * ...) ==
n! / n / (n_1! / n_1! * n_2! * ...) == 
n/n_1 * (n! / (n_1! * n_2! * ...)`)

Então, obtemos a resposta multiplicando pela n/n1fração recíproca de elementos que iguala o primeiro, pelo resultado recursivo para o resto da lista. A lista vazia fornece o caso base de 1.

xnor
fonte
Por que você não coloca /l.count(l[0])no final? Então você não precisa desse ponto flutuante nojento.
feersum
4

MATL , 14 13 12 bytes

fpGu"@G=s:p/

Experimente online!

Explicação

A abordagem é muito semelhante à da resposta de @ Adnan .

f       % Take input implicitly. Push array of indices of nonzero entries.
        % This gives [1 2 ... n] where n is input length.
p       % Product (compute factorial)
Gu      % Push input. Array of its unique elements
"       % For each of those unique values
  @     %   Push unique value of current iteration
  G=s   %   Number of times (s) it's present (=) in the input (G)
  :p    %   Range, product (compute factorial)
  /     %   Divide
        % End for each implicitly. Display implicitly
Luis Mendo
fonte
3

05AB1E , 15 14 13 bytes

Código:

D©g!rÙv®yQO!/

Explicação:

               # implicit input
D©             # duplicate and save a copy to register
  g!           # factorial of input length (total nr of permutations without duplicates)
    rÙv        # for each unique number in input
       ®yQO!   # factorial of number of occurances in input
            /  # divide total nr of permutations by this
               # implicit output

Usa a codificação CP-1252 .

Experimente online! .

Adnan
fonte
2

JavaScript (ES6), 64 61 bytes

a=>a.sort().map((x,i)=>r=r*++i/(x-y?(y=x,c=1):++c),y=r=-1)|-r

Usa a fórmula fornecida, exceto o cálculo incremental de cada fatorial (por exemplo, os r=r*++icálculos efetivos n!).

Edit: Originalmente eu aceitei qualquer número finito, mas salvei 3 bytes quando @ user81655 apontou que eu só precisava suportar números inteiros positivos (embora eu realmente aceite números inteiros não negativos).

Neil
fonte
r*=++i/(x-y?(y=x,c=1):++c),y=r=-1)|-r?
user81655
@ user81655 Ah, eu não tinha lido a pergunta o suficiente e esquecido que podia confiar nos valores como números inteiros positivos. Não gosto do *=fato de introduzir erros de arredondamento.
Neil
2

Pitão, 11 bytes

/.!lQ*F/V._

Suíte de teste

Usa a fórmula padrão n! / (count1! * count2! * ...), exceto que os fatoriais das contagens são encontrados contando quantas vezes cada elemento ocorre no prefixo anterior a ele e multiplicando todos esses números juntos.

Explicação:

/.!lQ*F/V._
/.!lQ*F/V._QQ    Implicit variable introduction.
                 Q = eval(input())
         ._Q     Form all prefixes of the input.
       /V   Q    Count how many times each element occurs in the prefix
                 ending with that element.
     *F          Fold on multiplication - take the product.
 .!lQ            Take the factorial of the input length
/                Divide.
isaacg
fonte
1

Pitão - 14 12 bytes

/F.!M+lQ/LQ{

Conjunto de Teste .

Maltysen
fonte
1

Ruby, 75 74 bytes

Meio que desejo que o Mathmódulo de Ruby tivesse uma função fatorial, para que eu não tivesse que construir o meu.

->l{f=->x{x<2?1:x*f[x-1]};l.uniq.map{|e|f[l.count e]}.inject f[l.size],:/}
Value Ink
fonte
1

CJam, 17 bytes

q~_,\$e`0f=+:m!:/

Teste aqui.

Explicação

q~   e# Read input and evaluate.
_,   e# Duplicate and get length.
\$   e# Swap with other copy and sort it.
e`   e# Run-length encode. Since the list is sorted, this tallies the numbers.
0f=  e# Select the tally of each number.
+    e# Prepend the length of the input.
:m!  e# Compute the factorial of each number in the list.
:/   e# Fold division over it, which divides each factorial of a tally into
     e# the factorial of the length.
Martin Ender
fonte
1

Geléia, 8 bytes

W;ĠL€!:/

Experimente online!

W;ĠL€!:/ example input:             [1, 3000, 2, 2, 8]
W        wrap:                      [[1, 3000, 2, 2, 8]]
  Ġ      group index by appearance: [[1], [3, 4], [5], [2]]
 ;       concatenate:               [[1, 3000, 2, 2, 8], [1], [3, 4], [5], [2]]
   L€    map by length:             [5, 1, 2, 1, 1]
     !   [map by] factorial:        [120, 1, 2, 1, 1]
      :/ reduce by division:        120÷1÷2÷1÷1 = 60
Freira Furada
fonte
1

J, 13 bytes

#(%*/)&:!#/.~

Uso

   f =: #(%*/)&:!#/.~
   f 1 3000 2 2 8
60
   f 1 1 1
1
   f 2 4 3 2 3 4 4 4 4 4 1 1
83160

Explicação

#(%*/)&:!#/.~  Input: A
         #/.~  Partition A by equal values and get the size of each, these are the tallies
#              Get the size of A
      &:!      Take the factorial of both the size and the tallies
   */          Reduce using multiplication the factorial of the tallies
  %            Divide the factorial of the size by that product and return
milhas
fonte