Contar todas as combinações únicas possíveis de letras em uma palavra

11

Você recebe uma string, que conterá caracteres az comuns. (Você pode assumir que isso sempre será o caso em qualquer teste e assumir que todas as letras também serão minúsculas). Você deve determinar quantas combinações únicas podem ser feitas dos caracteres individuais na sequência e imprimir esse número.

No entanto, letras duplicadas podem ser ignoradas na contagem das combinações possíveis. Em outras palavras, se a sequência fornecida for "olá", simplesmente mudar as posições dos dois ls não conta como uma frase única e, portanto, não pode ser contada no total.

O menor número de bytes vence, ansioso para ver algumas soluções criativas em idiomas que não são de golfe!

Exemplos:

hello -> 60
aaaaa -> 1
abcde -> 120
I_P_Edwards
fonte
4
@ Giuseppe Eu não acho que isso seja uma bobagem disso; as especificidades desta questão permitem muito implementações mais curtos
Arbo
4
Adicionar alguns casos de teste pode ajudar.
TSH
1
@JonathanAllan Boa sugestão! O título foi alterado em conformidade.
I_P_Edwards 18/06/19

Respostas:

29

Python 2 , 50 48 bytes

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

Experimente online!

Sem built-ins chatos! Para minha surpresa, isso é ainda mais curto que a abordagem da força bruta, calculando todas as permutações com itertoolse tomando o comprimento.

Esta função usa a fórmula

# de permutações únicas=(número de elementos)!elementos únicos(número de ocorrências desse elemento)!

e calcula em tempo real. O fatorial no numerador é calculado multiplicando por len(s)em cada chamada de função. O denominador é um pouco mais sutil; em cada chamada, dividimos pelo número de ocorrências desse elemento no que resta da string, garantindo que, para cada caractere c, todos os números entre 1 e a quantidade de ocorrências de c(inclusive) sejam divididos exatamente uma vez. Como dividimos apenas no final, garantimos que não temos problemas com a divisão de piso padrão do Python 2.

ArBo
fonte
itertools é muito detalhado em seus nomes de função
qwr 18/06/19
16

05AB1E , 3 bytes

œÙg

Experimente online!

Explicação

  g  # length of the list
 Ù   # of unique
œ    # permutations
     # of the input
Emigna
fonte
7

CJam , 4 bytes

le!,

Experimente online!

Explicação

Leia a linha como uma string ( l), permutações exclusivas como uma matriz de strings ( e!), length ( ,), exibição implícita.

Luis Mendo
fonte
4
Parece "lel", +1! : D
KeyWeeUsr
5

R , 69 65 bytes

function(s,`!`=factorial)(!nchar(s))/prod(!table(strsplit(s,"")))

Experimente online!

4 bytes salvos graças a Zahiro Mor nas duas respostas.

Calcula o coeficiente multinomial diretamente.

R , 72 68 bytes

function(s,x=table(strsplit(s,"")))dmultinom(x,,!!x)*sum(1|x)^sum(x)

Experimente online!

Usa a função de distribuição multinomial fornecida por dmultinompara extrair o coeficiente multinomial.

Observe que o habitual (golfista) x<-table(strsplit(s,""))não funciona dentro da dmultinomchamada por um motivo desconhecido.

Giuseppe
fonte
2
function(s,! =factorial)(!nchar(s))/prod(!table(strsplit(s,""))) vai funcionar. o el () é reduntant - Mesa sabe olhar para os elementos ....
Zahiro Mor
1
@ZahiroMor ah, é claro. Eu pretendia testar isso, mas nunca cheguei a isso.
18719 Giuseppe
5

JavaScript (Node.js) , 49 bytes

t=t*é usado em vez de t*=evitar erro de arredondamento (o |tnúmero arredonda para baixo) como t=t*garantia de que todos os resultados intermediários (em termos de operador) são números inteiros.

a=>[...a].map(g=x=>t=t*y++/(g[x]=-~g[x]),t=y=1)|t

Experimente online!

a=>
 [...a].map(        // Loop over the characters
  g=x=>
   t=t*             // using t*= instead may result in rounding error 
    y++             // (Length of string)!
    /(g[x]=-~g[x])  // divided by product of (Count of character)!
  ,t=y=1            // Initialization
 )
 |t
Shieru Asakoto
fonte
2
(Potencial de ponto flutuante erro de arredondamento, o uso t=t*se você quer evitar isso.)
Neil
@Neil Sim, falhou quando a entrada é aaadegfbbbcccexatamente devido ao arredondamento de ponto flutuante erro
Shieru Asakoto
Huh, como você encontrou esse caso de teste?
Neil
@Neil Continue adicionando personagens para a cadeia até que ocorra tal erro de arredondamento lol
Shieru Asakoto
O título @ShieruAsakoto foi alterado; contagem é muito melhor. Obrigado e boa resposta!
I_P_Edwards 18/06/19
4

APL (Dyalog Unicode) , 14 bytes

!∘⍴÷⊂×.(!∘⍴∩)∪

Experimente online!

Retorna o resultado como um singleton.

Erik, o Outgolfer
fonte
-> para fazer com que ele retorne escalares simples, ÷⍨/g⌸,g←!⊢∘≢para -2
ngn 04/08/19
4

Japonês , 5 3 bytes

-2 bytes graças a @Shaggy

á l

Experimente online!

Luis felipe De jesus Munoz
fonte
O TIO parece estar executando uma versão antiga do Japt, permitindo que você abandone o â.
Shaggy
@ Shay Lol, eu não percebi isso. obrigado!
Luis felipe De jesus Munoz
4

J , 15 , 14 bytes

[:#@=i.@!@#A.]

Experimente online!

-1 byte graças a FrownyFrog

Jonah
fonte
~.pode ser=
FrownyFrog
Agradável. Obrigado, @FrownyFrog
Jonah
3

Gelatina , 4 bytes

Œ!QL

Experimente online!

Simplesmente faz o que foi solicitado: encontre permutações de entrada, unifique e imprima o comprimento.

Nick Kennedy
fonte
3

Braquilog , 3 bytes

pᶜ¹

Experimente online!

       The output is
 ᶜ¹    the number of unique
p      permutations of
       the input.

pᵘl faz exatamente a mesma coisa.

String não relacionada
fonte
2

Python 2 , 57 bytes

lambda s:len(set(permutations(s)))
from itertools import*

Experimente online!

Auto-documentação: Retorna o comprimento do conjunto de permutações exclusivas da string de entrada.

Python 3 , 55 bytes

O crédito vai para a ArBo neste:

lambda s:len({*permutations(s)})
from itertools import*

Experimente online!

Restabelecer Monica
fonte
2

APL (Dyalog Unicode) , 24 bytes

CY'dfns'
{≢∪↓⍵[pmat≢⍵]}

Experimente online!

Dfn simples, aceita uma string como argumento.

Quão:

CY'dfns'       Copies the 'dfns' namespace.
{≢∪↓⍵[pmat≢⍵]}  Main function
          ≢⍵    Number of elements in the argument (⍵)
      pmat      Permutation Matrix of the range [1..≢⍵]
    ⍵[      ]   Index the argument with that matrix, which generates all permutations of 
               Convert the matrix into a vector of strings
               Keep only the unique elements
               Tally the number of elements
J. Sallé
fonte
2

Ruby , 41 bytes

f=->s{s.chars.permutation.to_a.uniq.size}

Experimente online!

thowawayacc89023489
fonte
1
Eu não acho que você precisato_a
Arbo
1
E funções anônimas / lambdas são aceitáveis, para que você possa remover a f=peça. (Em TIO movê-lo para Header para não ficar contados.)
manatwork
2

Perl 6 , 33 30 caracteres ( 34 31 bytes)

WhateverBloco bastante direto . combdivide a string em letras, permutationsobtém todas as combinações possíveis. Por causa da maneira como a coerção Setprecisa ser joinedificada primeiro ( »aplica join- se a cada elemento da lista).

+*.comb.permutations».join.Set

Experimente online!

(a resposta anterior usada, .uniquemas Sets garante a exclusividade e numerifica a mesma, para salvar 3).

user0721090601
fonte
2

K (oK) , 12 bytes

Solução:

#?x@prm@!#x:

Experimente online!

Explicação:

Usa o oK embutido prm:

{[x]{[x]$[x;,/x ,''o'x ^/:x;,x]}@$[-8>@x;!x;x]}

... que, devido x^/:xbasicamente gera as permutações de "helo"não "hello", portanto, precisamos gerar as permutações de 0 1 2 3 4, usá-las para indexar "hello"e, em seguida, fazer a contagem do único.

#?x@prm@!#x: / the solution
          x: / store input as x
         #   / count (#) length
        !    / range (!) 0..n
    prm@     / apply (@) to function prm
  x@         / apply permutations to input x
 ?           / take the distinct (?)
#            / count (#)
rua
fonte
O prm é um operador específico ok? Eu não acho que baunilha k tem?
Henry Henrinson 18/06/19
Yup - só existe em oK acordo com o manual de
streetster
@HenryHenrinson afaik não está no k4. no início do k5 era !-n. no final do k5 e k6 tornou-seprm . k7 (shakti) prmtambém.
ngn 20/06/19
2

Java 8, 103 102 bytes

s->{int r=1,i=s.length();for(;i>0;)r=r*i/~-s.substring(--i).split(s.charAt(i)+"",-1).length;return r;}

Porta da resposta Python 2 do @ArBo .
-1 byte agradece a @ OlivierGrégoire , tornando-o iterativo em vez de recursivo.

Experimente online.

Na verdade, gerar todas as permutações exclusivas em um conjunto e obter seu tamanho seria 221 bytes :

import java.util.*;s->{Set S=new HashSet();p(s,S,0,s.length()-1);return S.size();}void p(String s,Set S,int l,int r){for(int i=l;i<=r;p(s.replaceAll("(.{"+l+"})(.)(.{"+(i++-l)+"})(.)(.*)","$1$4$3$2$5"),S,l+1,r))S.add(s);}

Experimente online.

Kevin Cruijssen
fonte
Ok, eu poderia golf um byte, tornando-iterativo em vez de recursiva: s->{int r=1,i=s.length();for(;i>0;)r=r*i/~-s.substring(--i).split(s.charAt(i)+"",-1).length;return r;}.
Olivier Grégoire
@ OlivierGrégoire Obrigado! Btw, você vê algo para tornar a segunda abordagem (gerando todas as permutações únicas em um conjunto) mais curta? Eu tenho a sensação de que alguns bytes podem ser salvos, mas tentei algumas coisas e a maioria era um pouco mais longa em vez de mais curta .. Mas ainda parece muito longo tbh.
Kevin Cruijssen
Eu tenho trabalhado nisso, tentando usar fluxos e contar, assim: s->{long r=1,i=s.length();for(;i>0;)r=r*i/(s.chars().skip(--i).filter(c -> c==s.charAt(i)).count()+1);return r;}mas sem sucesso até agora ...
Olivier Grégoire
1

MATL , 9 bytes

jY@XuZy1)

Experimente online!

Explicação:

j input as string
Y@ get permutations
Xu unique members
Zy size matrix
1) first member of size matrix
OrangeCherries
fonte
2
Você pode usar a entrada entre aspas, assim jtorna - se i, que pode ser deixada implícita. Além disso, &nxsalva um byte sobre Zy1) tio.run/##y00syfn/P9IholQtr@L/f/WM1JycfHUA
Luis Mendo
1

Oitava / MATLAB, 35 bytes

@(s)size(unique(perms(s),'rows'),1)

Função anônima que pega um vetor de caractere e produz um número.

No MATLAB, isso pode ser reduzido para size(unique(perms(s),'ro'),1)(33 bytes).

Experimente online!

Explicação

@(s)                                  % Anonymous function with input s
                perms(s)              % Permutations. Gives a char matrix
         unique(        ,'rows')      % Deduplicate rows
    size(                       ,1)   % Number of rows
Luis Mendo
fonte
1
Eu pensei que uniquejá retornou linhas únicas? Ou isso é apenas para tables?
Giuseppe
@ Giuseppe Para matrizes 2D numéricas / caracteres unique, linearizariam primeiro. Para as mesas, acho que você está certo; Eu não sabia disso!
Luis Mendo
1
Ah, eu sei de onde eu tirei a idéia - uniqueno MATLAB leva linhas para tables; R uniquerecebe linhas exclusivas de matrizes ou quadros de dados. Muitas línguas matriz com os mesmos comandos que fazem as coisas um pouco diferentes ...
Giuseppe
1

Retina 0.8.2 , 73 bytes

(.)(?=(.*?\1)*)
/1$#2$*1x1$.'$*
^
1
+`1(?=1*/(1+)x(\1)+$)|/1+x1+$
$#2$*
1

Experimente online! Usa a fórmula do @ ArBo, mas avalia da direita para a esquerda, pois isso pode ser feito na aritmética inteira, minimizando o tamanho dos valores unários envolvidos. Explicação:

(.)(?=(.*?\1)*)
/1$#2$*1x1$.'$*

Para cada caractere, conte quantas duplicatas restantes existem e quantos caracteres adicionais existem, adicione um a cada um para levar em consideração o caractere atual e separe os valores para que saibamos quais devem ser divididos e quais devem ser multiplicados .

^
1

Prefixe um 1 para produzir uma expressão completa.

+`1(?=1*/(1+)x(\1)+$)|/1+x1+$
$#2$*

Multiplique repetidamente o último e o terceiro últimos números, dividindo pelo segundo último número. Isso substitui os três últimos números.

1

Converta para decimal.

Neil
fonte
1

K, 27 bytes

*/[1+!#:x]%*/{*/1+!x}'#:'x:

K, 16 bytes - não é uma resposta real

#?(999999#0N)?\:

Faça 999999 permutações aleatórias da sequência de entrada, pegue o conjunto exclusivo delas e conte o comprimento. Na maioria das vezes, ele fornece a resposta certa, para seqüências curtas.

Melhorado graças a @Sriotchilism O'Zaic, @Selcuk

Henry Henrinson
fonte
2
Bem vindo ao site! Realmente não importa, pois é inválido, mas você poderia tornar sua resposta inválida mais precisa usando em 999999vez de 100000?
Post Rock Garf Hunter
Sim, boa ideia, obrigado.
Henry Henrinson 19/06/19
1
E talvez edite a explicação para refletir essa mudança também?
Selcuk
1

Wolfram Language (Mathematica) , 32 bytes

Characters/*Permutations/*Length

Experimente online!

Explicação: A composição da direita com /*aplica esses três operadores um após o outro ao argumento da função, da esquerda para a direita:

  • Characters converte a sequência de entrada em uma lista de caracteres.

  • Permutations faz uma lista de todas as permutações exclusivas dessa lista de caracteres.

  • Length retorna o comprimento desta lista de permutações exclusivas.

Esse método é muito inútil para seqüências longas: as permutações únicas são realmente listadas e contadas, em vez de usar a Multinomialpara calcular seu número sem listar.

romano
fonte
1

F # (Mono) , 105 bytes

let rec f s=if s=""then 1 else s.Length*(f(s.Substring 1))/(s|>Seq.sumBy(fun c->if c=s.[0]then 1 else 0))

Experimente online!

Henrik Hansen
fonte
1

Pitão , 5 4 bytes

l{.p

Experimente online!

Isso pressupõe que a entrada é uma literal de string python. Se a entrada precisar ser texto bruto, esta versão de 5 bytes funcionará:

l{.pz

De qualquer maneira, ele apenas calcula todas as permutações da entrada como uma lista, a deduplica e obtém o número de elementos nela e imprime implicitamente esse número.

-1 byte graças a @ hakr14

randomdude999
fonte
{deduplica uma lista para um byte menor que .{.
precisa saber é
1

J , 14  13 bytes

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

Experimente online!

1 byte graças a milhas

#                  length
         #/.~      counts of each unique character
 (%*/)             divide left by the product of right
      &:!          after applying ! to both
FrownyFrog
fonte
1
#(%*/)&:!#/.~deve salvar outro byte
milhas
0

Ohm v2 , 4 bytes

ψD∩l

Experimente online!

Explicação

   l    output the lenght of
  ∩     the set intersection between
ψD      two copies of all possible permutation of input
Cinaski
fonte