Compter toutes les combinaisons uniques possibles de lettres dans un mot

12

Vous recevez une chaîne qui contiendra des caractères az ordinaires. (Vous pouvez supposer que ce sera toujours le cas dans tous les tests et supposer que toutes les lettres seront également en minuscules). Vous devez déterminer combien de combinaisons uniques peuvent être faites des caractères individuels dans la chaîne et imprimer ce nombre.

Cependant, les lettres en double peuvent être ignorées lors du comptage des combinaisons possibles. En d'autres termes, si la chaîne donnée est "bonjour", alors simplement changer les positions des deux ls ne compte pas comme une phrase unique, et ne peut donc pas être compté dans le total.

Le nombre d'octets le plus court gagne, avec impatience de voir des solutions créatives dans des langues autres que le golf!

Exemples:

hello -> 60
aaaaa -> 1
abcde -> 120
SimpleGeek
la source
4
@ Giuseppe Je ne pense pas que ce soit une dupe de cela; les spécificités de cette question permettent des implémentations beaucoup plus courtes
ArBo
4
L'ajout de quelques tests peut aider.
tsh
1
@JonathanAllan Bonne suggestion! Le titre a changé en conséquence.
SimpleGeek

Réponses:

29

Python 2 , 50 48 octets

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

Essayez-le en ligne!

Aucun ennuyeux intégré! À ma grande surprise, c'est encore plus court que l'approche par force brute, calculant toutes les permutations avec itertoolset prenant la longueur.

Cette fonction utilise la formule

# of unique permutations=(# of elements)!unique elements(# of occurences of that element)!

et le calcule à la volée. La factorielle dans le numérateur est calculée en multipliant par len(s)dans chaque appel de fonction. Le dénominateur est un peu plus subtil; dans chaque appel, nous divisons par le nombre d'occurrences de cet élément dans ce qui reste de la chaîne, garantissant que pour chaque caractère c, tous les nombres entre 1 et la quantité d'occurrences de c(inclus) seront divisés par une seule fois. Étant donné que nous ne divisons qu'à la toute fin, nous sommes garantis de ne pas avoir de problèmes avec la division par défaut du plancher de Python 2.

ArBo
la source
itertools est très verbeux dans ses noms de fonctions
qwr
16

05AB1E , 3 octets

œÙg

Essayez-le en ligne!

Explication

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

CJam , 4 octets

le!,

Essayez-le en ligne!

Explication

Lire la ligne sous forme de chaîne ( l), les permutations uniques sous forme de tableau de chaînes ( e!), la longueur ( ,), l'affichage implicite.

Luis Mendo
la source
4
Ressemble à "lel", +1! : D
KeyWeeUsr
5

R , 69 65 octets

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

Essayez-le en ligne!

4 octets enregistrés grâce à Zahiro Mor dans les deux réponses.

Calcule directement le coefficient multinomial.

R , 72 68 octets

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

Essayez-le en ligne!

Utilise la fonction de distribution multinomiale fournie par dmultinompour extraire le coefficient multinomial.

Notez que l'habituel (golfeur) x<-table(strsplit(s,""))ne fonctionne pas dans l' dmultinomappel pour une raison inconnue.

Giuseppe
la source
2
function(s,! =factorial)(!nchar(s))/prod(!table(strsplit(s,""))) marchera. le el () est redondant - la table sait rechercher les éléments ....
Zahiro Mor
1
@ZahiroMor ah, bien sûr. J'avais l'intention de tester cela, mais je n'y suis jamais parvenu.
Giuseppe
5

JavaScript (Node.js) , 49 octets

t=t*est utilisé au lieu de t*=pour éviter une erreur d'arrondi (l'arrondi |tvers le bas du nombre) car il t=t*garantit que tous les résultats intermédiaires (selon l'opérateur) sont des nombres entiers.

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

Essayez-le en ligne!

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
la source
2
(Erreur potentielle d'arrondi en virgule flottante; à utiliser t=t*si vous voulez éviter cela.)
Neil
@Neil Oui, il a échoué lorsque l'entrée est aaadegfbbbcccexactement due à l'erreur d'arrondi à virgule flottante
Shieru Asakoto
Huh, comment avez-vous trouvé ce cas de test?
Neil
@Neil Continuez à ajouter des caractères à la chaîne jusqu'à ce
qu'une
@ShieruAsakoto Le titre a été modifié; compter est beaucoup mieux. Merci et bonne réponse!
SimpleGeek
4

APL (Dyalog Unicode) , 14 octets

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

Essayez-le en ligne!

Renvoie le résultat sous forme de singleton.

Erik le Outgolfer
la source
-> pour lui faire retourner des scalaires simples, ÷⍨/g⌸,g←!⊢∘≢pour -2
ngn
4

Japt , 5 3 octets

-2 octets grâce à @Shaggy

á l

Essayez-le en ligne!

Luis felipe De jesus Munoz
la source
TIO semble utiliser une ancienne version de Japt, ce qui vous permet d'abandonner le â.
Shaggy
@Shaggy Lol, je ne l'ai pas remarqué. Merci!
Luis felipe De jesus Munoz
4

J , 15 , 14 octets

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

Essayez-le en ligne!

-1 octet grâce à FrownyFrog

Jonas
la source
~.peut être=
FrownyFrog
Agréable. Merci, @FrownyFrog
Jonah
3

Gelée , 4 octets

Œ!QL

Essayez-le en ligne!

Fait simplement ce qui a été demandé: trouver les permutations d'entrée, unifier et imprimer la longueur.

Nick Kennedy
la source
3

Brachylog , 3 octets

pᶜ¹

Essayez-le en ligne!

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

pᵘl fait à peu près exactement la même chose.

Chaîne indépendante
la source
2

Python 2 , 57 octets

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

Essayez-le en ligne!

Auto-documentation: renvoie la longueur de l'ensemble des permutations uniques de la chaîne d'entrée.

Python 3 , 55 octets

Le crédit va à Arbo sur celui - ci:

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

Essayez-le en ligne!

calamar
la source
2

APL (Dyalog Unicode) , 24 octets

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

Essayez-le en ligne!

Dfn simple, prend une chaîne comme argument.

Comment:

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é
la source
2

Rubis , 41 octets

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

Essayez-le en ligne!

thowawayacc89023489
la source
1
Je ne pense pas que tu aies besoin to_a
ArBo
1
Et les fonctions / lambdas anonymes sont acceptables, vous pouvez donc supprimer la f=pièce. (Dans TIO, déplacez-le vers Header pour ne pas être compté.)
manatwork
2

Perl 6 , 33 30 caractères ( 34 31 octets)

WhateverBloc assez simple . combdivise la chaîne en lettres, permutationsobtient toutes les combinaisons possibles. En raison de la façon dont la contrainte Setdoit être joinéditée en premier ( »s'applique joinà chaque élément de la liste).

+*.comb.permutations».join.Set

Essayez-le en ligne!

(la réponse précédente est utilisée .uniquemais Setgarantit l'unicité et la numérise de la même manière, cela économise 3).

user0721090601
la source
2

K (oK) , 12 octets

Solution:

#?x@prm@!#x:

Essayez-le en ligne!

Explication:

Utilise le oK intégré prm:

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

... qui, en raison de x^/:xgénère essentiellement les permutations de "helo"non "hello", nous devons donc générer les permutations de 0 1 2 3 4, les utiliser pour indexer "hello"puis prendre le compte de l'unique.

#?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 (#)
streetster
la source
Prm est-il un opérateur spécifique ok? Je ne pense pas que la vanille l'ait?
Henry Henrinson
Ouaip - n'existe qu'en OK selon le manuel
streetster
@HenryHenrinson afaik ce n'est pas en k4. c'était au début du k5 !-n. à la fin de k5 et k6, il est devenuprm . k7 (shakti) prmaussi.
ngn
2

Java 8, 103 102 octets

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

Port de la réponse Python 2 de @ArBo .
-1 octet grâce à @ OlivierGrégoire en le rendant itératif au lieu de récursif.

Essayez-le en ligne.

En fait, générer toutes les permutations uniques dans un ensemble et obtenir sa taille serait de 221 octets :

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);}

Essayez-le en ligne.

Kevin Cruijssen
la source
D' accord, je pourrais le golf un octet en rendant itératif au lieu de récursive: 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 Merci! Btw, voyez-vous quelque chose pour raccourcir la seconde approche (générer toutes les permutations uniques dans un ensemble)? J'ai l'impression que certains octets peuvent être sauvegardés, mais j'ai essayé certaines choses et la plupart étaient légèrement plus longues au lieu de plus courtes .. Mais cela semble toujours trop long tbh.
Kevin Cruijssen
J'y ai travaillé, j'essaie d'utiliser des flux et de compter, comme ceci: 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;}mais sans succès jusqu'à présent ...
Olivier Grégoire
1

MATL , 9 octets

jY@XuZy1)

Essayez-le en ligne!

Explication:

j input as string
Y@ get permutations
Xu unique members
Zy size matrix
1) first member of size matrix
OrangeCherries
la source
2
Vous pouvez prendre l'entrée avec des guillemets, jdevient ainsi i, qui peut être laissé implicite. En outre, &nxenregistre un octet sur Zy1) tio.run/##y00syfn/P9IholQtr@L/f/WM1JycfHUA
Luis Mendo
1

Octave / MATLAB, 35 octets

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

Fonction anonyme qui prend un vecteur de caractères et produit un nombre.

Dans MATLAB, cela peut être raccourci à size(unique(perms(s),'ro'),1)(33 octets).

Essayez-le en ligne!

Explication

@(s)                                  % Anonymous function with input s
                perms(s)              % Permutations. Gives a char matrix
         unique(        ,'rows')      % Deduplicate rows
    size(                       ,1)   % Number of rows
Luis Mendo
la source
1
Je pensais uniquedéjà retourné des lignes uniques? Ou est-ce seulement pour tables?
Giuseppe
@Giuseppe Pour les tableaux 2D numériques / char unique, la linéarisation serait la première. Pour les tableaux, je pense que vous avez raison; Je ne savais pas ça!
Luis Mendo
1
Ah, je sais d'où vient l'idée - uniquedans MATLAB, il faut des lignes pour tables; R uniqueprend des lignes uniques de matrices ou de trames de données. Trop de langages de tableau avec les mêmes commandes qui font des choses légèrement différentes ...
Giuseppe
1

Retina 0.8.2 , 73 octets

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

Essayez-le en ligne! Utilise la formule de @ ArBo, mais évalue de droite à gauche car cela peut être fait en arithmétique entière tout en minimisant la taille des valeurs unaires impliquées. Explication:

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

Pour chaque caractère, comptez le nombre de doublons restants et le nombre de caractères supplémentaires, ajoutez-en un pour prendre en compte le caractère actuel et séparez les valeurs afin de savoir lesquels doivent être divisés et lesquels doivent être multipliés. .

^
1

Préfixez un 1 pour produire une expression complète.

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

Multipliez de façon répétée le dernier et l'avant-dernier nombre en divisant par l'avant-dernier numéro. Cela remplace les trois derniers chiffres.

1

Convertissez en décimal.

Neil
la source
1

K, 27 octets

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

K, 16 octets - pas une vraie réponse

#?(999999#0N)?\:

Prenez 999999 permutations aléatoires de la chaîne d'entrée, prenez l'ensemble unique d'entre elles et comptez la longueur. La plupart du temps, il donnera la bonne réponse, pour les chaînes plus courtes.

Amélioré grâce à @Sriotchilism O'Zaic, @Selcuk

Henry Henrinson
la source
2
Bienvenue sur le site! Cela n'a pas vraiment d'importance car elle n'est pas valide, mais pourriez-vous rendre votre réponse invalide plus précise en utilisant à la 999999place de 100000?
Ad Hoc Garf Hunter
Ouais, bonne idée, merci.
Henry Henrinson
1
Et peut-être modifier l'explication pour refléter ce changement aussi?
Selcuk
1

Wolfram Language (Mathematica) , 32 octets

Characters/*Permutations/*Length

Essayez-le en ligne!

Explication: La composition à droite avec /*applique ces trois opérateurs l'un après l'autre à l'argument de fonction, de gauche à droite:

  • Characters convertit la chaîne d'entrée en une liste de caractères.

  • Permutations fait une liste de toutes les permutations uniques de cette liste de caractères.

  • Length renvoie la longueur de cette liste de permutations uniques.

Cette méthode est très inutile pour les chaînes longues: les permutations uniques sont en fait répertoriées et comptées, au lieu d'utiliser a Multinomialpour calculer leur nombre sans les répertorier.

romain
la source
1

Pyth , 5 4 octets

l{.p

Essayez-le en ligne!

Cela suppose que l'entrée est un littéral de chaîne python. Si l'entrée doit être du texte brut, cette version à 5 octets fonctionnera:

l{.pz

Dans les deux cas, il calcule simplement toutes les permutations de l'entrée sous forme de liste, la déduplique et obtient le nombre d'éléments qu'elle contient, et imprime implicitement ce nombre.

-1 octet grâce à @ hakr14

randomdude999
la source
{déduplique une liste pour un octet inférieur à .{.
hakr14
1

J , 14  13 octets

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

Essayez-le en ligne!

1 octet grâce aux miles

#                  length
         #/.~      counts of each unique character
 (%*/)             divide left by the product of right
      &:!          after applying ! to both
FrownyFrog
la source
1
#(%*/)&:!#/.~devrait sauver un autre octet
miles
0

Ohm v2 , 4 octets

ψD∩l

Essayez-le en ligne!

Explication

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