Cuente todas las combinaciones únicas posibles de letras en una palabra

12

Se le da una cadena, que contendrá caracteres az ordinarios. (Puede suponer que este será siempre el caso en cualquier prueba, y asumir que todas las letras también estarán en minúsculas). Debe determinar cuántas combinaciones únicas se pueden hacer de los caracteres individuales en la cadena e imprimir ese número.

Sin embargo, las letras duplicadas pueden ignorarse al contar las combinaciones posibles. En otras palabras, si la cadena dada es "hola", simplemente cambiar las posiciones de los dos ls no cuenta como una frase única y, por lo tanto, no puede contarse hacia el total.

¡El conteo de bytes más cortos gana, esperando ver algunas soluciones creativas en idiomas que no sean de golf!

Ejemplos:

hello -> 60
aaaaa -> 1
abcde -> 120
SimpleGeek
fuente
44
@Giuseppe No creo que esto sea un engaño de eso; Los detalles de esta pregunta permiten implementaciones mucho más cortas
ArBo
44
Agregar algunos casos de prueba puede ayudar.
tsh
1
@JonathanAllan ¡Buena sugerencia! El título cambió en consecuencia.
SimpleGeek

Respuestas:

29

Python 2 , 50 48 bytes

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

Pruébalo en línea!

No hay complementos aburridos! Para mi sorpresa, esto es incluso más corto que el enfoque de fuerza bruta, calculando todas las permutaciones con itertoolsy tomando la longitud.

Esta función usa la fórmula

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

y lo calcula sobre la marcha. El factorial en el numerador se calcula multiplicando por len(s)en cada llamada a la función. El denominador es un poco más sutil; en cada llamada, dividimos por el número de ocurrencias de ese elemento en lo que queda de la cadena, asegurando que para cada carácter c, todos los números entre 1 y la cantidad de ocurrencias de c(inclusive) se dividirán por exactamente una vez. Como nos dividimos solo al final, tenemos la garantía de no tener ningún problema con la división de piso predeterminada de Python 2.

ArBo
fuente
itertools es muy detallado en sus nombres de funciones
qwr
7

CJam , 4 bytes

le!,

Pruébalo en línea!

Explicación

Lea la línea como una cadena ( l), permutaciones únicas como una matriz de cadenas ( e!), longitud ( ,), visualización implícita.

Luis Mendo
fuente
44
Parece "lel", +1! : D
KeyWeeUsr
5

R , 69 65 bytes

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

Pruébalo en línea!

4 bytes guardados gracias a Zahiro Mor en ambas respuestas.

Calcula el coeficiente multinomial directamente.

R , 72 68 bytes

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

Pruébalo en línea!

Utiliza la función de distribución multinomial proporcionada por dmultinompara extraer el coeficiente multinomial.

Tenga en cuenta que lo habitual (golfista) x<-table(strsplit(s,""))no funciona dentro de la dmultinomllamada por un motivo desconocido.

Giuseppe
fuente
2
function(s,! =factorial)(!nchar(s))/prod(!table(strsplit(s,""))) trabajará. el () es redundante - la tabla sabe buscar los elementos ...
Zahiro Mor
1
@ZahiroMor ah, por supuesto. Tenía la intención de probar eso, pero nunca lo logré.
Giuseppe
5

JavaScript (Node.js) , 49 bytes

t=t*se usa en lugar de t*=evitar el error de redondeo ( |tredondea el número hacia abajo) como t=t*garantía de que todos los resultados intermedios (a nivel del operador) son números enteros.

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

Pruébalo en línea!

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
fuente
2
(Posible error de redondeo de punto flotante; úselo t=t*si desea evitarlo.)
Neil
@Neil Sí, falló cuando la entrada se aaadegfbbbcccdebe exactamente al error de redondeo de punto flotante
Shieru Asakoto
¿Cómo encontraste ese caso de prueba?
Neil
@Neil Sigue agregando caracteres a la cadena hasta que ocurra ese error de redondeo jajaja
Shieru Asakoto
@ShieruAsakoto El título ha cambiado; contar es mucho mejor. Gracias y buena respuesta!
SimpleGeek
4

Japt , 5 3 bytes

-2 bytes gracias a @Shaggy

á l

Pruébalo en línea!

Luis felipe De jesus Munoz
fuente
TIO parece estar ejecutando una versión antigua de Japt, lo que le permite deshacerse de él â.
Shaggy
@ Shaggy Lol, no me di cuenta de eso. ¡Gracias!
Luis felipe De jesus Munoz
4

J , 15 , 14 bytes

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

Pruébalo en línea!

-1 byte gracias a FrownyFrog

Jonás
fuente
~.puede ser=
FrownyFrog
Agradable. Gracias, @FrownyFrog
Jonah
3

Jalea , 4 bytes

Œ!QL

Pruébalo en línea!

Simplemente hace lo que se le pidió: encontrar permutaciones de entrada, uniquificar e imprimir la longitud.

Nick Kennedy
fuente
3

Brachylog , 3 bytes

pᶜ¹

Pruébalo en línea!

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

pᵘl hace casi exactamente lo mismo.

Cadena no relacionada
fuente
2

Python 2 , 57 bytes

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

Pruébalo en línea!

Autodocumentado: devuelve la longitud del conjunto de permutaciones únicas de la cadena de entrada.

Python 3 , 55 bytes

El crédito va a ArBo en este caso:

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

Pruébalo en línea!

calamar
fuente
2

APL (Dyalog Unicode) , 24 bytes

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

Pruébalo en línea!

Dfn simple, toma una cadena como argumento.

Cómo:

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é
fuente
2

Ruby , 41 bytes

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

Pruébalo en línea!

thowawayacc89023489
fuente
1
No creo que necesitesto_a
ArBo
1
Y las funciones anónimas / lambdas son aceptables, por lo que puede eliminar la f=parte. (En TIO
muévelo
2

Perl 6 , 33 30 caracteres ( 34 31 bytes)

WhateverBloque bastante sencillo . combdivide la cadena en letras, permutationsobtiene todas las combinaciones posibles. Debido a la forma en que la coerción Setdebe ser joineditada primero (se »aplica joina cada elemento de la lista)

+*.comb.permutations».join.Set

Pruébalo en línea!

(se utilizó la respuesta anterior .uniquepero Sets garantiza la unicidad y numera la misma, por lo que ahorra 3).

usuario0721090601
fuente
2

K (oK) , 12 bytes

Solución:

#?x@prm@!#x:

Pruébalo en línea!

Explicación:

Utiliza el oK incorporado prm:

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

... que, debido a que x^/:xbásicamente genera las permutaciones de "helo"no "hello", por lo tanto, necesitamos generar las permutaciones de 0 1 2 3 4, usarlas para indexar "hello"y luego tomar la cuenta de lo ú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 (#)
callejero
fuente
¿Es prm un operador específico correcto? No creo que vainilla k lo tenga?
Henry Henrinson
Sí, solo existe en oK según el manual
streetster
@HenryHenrinson afaik no está en k4. a principios de k5 fue !-n. a finales de k5 y k6 se convirtióprm . k7 (shakti) prmtambién lo ha hecho .
ngn
2

Java 8, 103102 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;}

Puerto de la respuesta Python 2 de @ArBo .
-1 byte gracias a @ OlivierGrégoire haciéndolo iterativo en lugar de recursivo.

Pruébalo en línea.

En realidad, generar todas las permutaciones únicas en un conjunto y obtener su tamaño sería de 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);}

Pruébalo en línea.

Kevin Cruijssen
fuente
Está bien, pude campo de un byte por lo que es iterativo en lugar de recursivo: 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 Gracias! Por cierto, ¿ves algo para acortar el segundo enfoque (generar todas las permutaciones únicas en un conjunto)? Tengo la sensación de que se pueden guardar algunos bytes, pero probé algunas cosas y la mayoría fueron un poco más largas en lugar de más cortas ... Pero todavía parece demasiado largo.
Kevin Cruijssen
He estado trabajando en ello, tratando de usar transmisiones y contar, así: 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;}pero sin éxito hasta ahora ...
Olivier Grégoire
1

MATL , 9 bytes

jY@XuZy1)

Pruébalo en línea!

Explicación:

j input as string
Y@ get permutations
Xu unique members
Zy size matrix
1) first member of size matrix
Cerezas Naranjas
fuente
2
Puede tomar la entrada con comillas, por lo que se jconvierte en i, que puede dejarse implícito. Además, &nxguarda un byte sobre Zy1) tio.run/##y00syfn/P9IholQtr@L/f/WM1JycfHUA
Luis Mendo
1

Octava / MATLAB, 35 bytes

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

Función anónima que toma un vector de caracteres y produce un número.

En MATLAB esto se puede acortar a size(unique(perms(s),'ro'),1)(33 bytes).

Pruébalo en línea!

Explicación

@(s)                                  % Anonymous function with input s
                perms(s)              % Permutations. Gives a char matrix
         unique(        ,'rows')      % Deduplicate rows
    size(                       ,1)   % Number of rows
Luis Mendo
fuente
1
¿Pensé que uniqueya había devuelto filas únicas? ¿O es solo para tables?
Giuseppe
@Giuseppe Para las matrices numéricas / char 2D uniquese linealizarían primero. Para las mesas creo que tienes razón; Yo no lo sabia!
Luis Mendo
1
Ah, sé de dónde saqué la idea: uniqueen MATLAB se toman filas para tables; R uniquetoma filas únicas de matrices o marcos de datos. Demasiados idiomas de matriz con los mismos comandos que hacen cosas ligeramente diferentes ...
Giuseppe
1

Retina 0.8.2 , 73 bytes

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

Pruébalo en línea! Utiliza la fórmula de @ ArBo, pero evalúa de derecha a izquierda, ya que esto se puede hacer en aritmética de enteros mientras se minimiza el tamaño de los valores unarios involucrados. Explicación:

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

Para cada carácter, cuente cuántos duplicados restantes hay y cuántos caracteres más hay, agregue uno a cada uno para tener en cuenta el carácter actual y separe los valores para que sepamos cuáles se deben dividir y cuáles se deben multiplicar. .

^
1

Prefije un 1 para producir una expresión completa.

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

Multiplica repetidamente el último y el tercer último número mientras divide por el segundo último número. Esto reemplaza los últimos tres números.

1

Convierte a decimal.

Neil
fuente
1

K, 27 bytes

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

K, 16 bytes: no es una respuesta real

#?(999999#0N)?\:

Tome 999999 permutaciones aleatorias de la cadena de entrada, tome el conjunto único de ellas y cuente la longitud. La mayoría de las veces dará la respuesta correcta, para cadenas cortas.

Mejorado gracias a @Sriotchilism O'Zaic, @Selcuk

Henry Henrinson
fuente
2
Bienvenido al sitio! Realmente no importa, ya que no es válido, pero ¿podría hacer que su respuesta no sea más precisa al usar en 999999lugar de 100000?
Ad Hoc Garf Hunter
Sí, buena idea, gracias.
Henry Henrinson
1
¿Y tal vez editar la explicación para reflejar ese cambio también?
Selcuk
1

Wolfram Language (Mathematica) , 32 bytes

Characters/*Permutations/*Length

Pruébalo en línea!

Explicación: La composición derecha con /*aplica estos tres operadores uno tras otro al argumento de la función, de izquierda a derecha:

  • Characters convierte la cadena de entrada en una lista de caracteres.

  • Permutations hace una lista de todas las permutaciones únicas de esta lista de caracteres.

  • Length devuelve la longitud de esta lista de permutaciones únicas.

Este método es muy derrochador para cadenas largas: las permutaciones únicas se enumeran y cuentan, en lugar de usar a Multinomialpara calcular su número sin enumerar.

romano
fuente
1

Pyth , 5 4 bytes

l{.p

Pruébalo en línea!

Esto supone que la entrada es un literal de cadena de Python. Si la entrada debe ser texto sin formato, esta versión de 5 bytes funcionará:

l{.pz

De cualquier manera, solo calcula todas las permutaciones de la entrada como una lista, la deduplica y obtiene el número de elementos en ella, e imprime ese número implícitamente.

-1 byte gracias a @ hakr14

randomdude999
fuente
{deduplica una lista para un byte menor que .{.
hakr14
1

J , 14  13 bytes

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

Pruébalo en línea!

1 byte gracias a millas

#                  length
         #/.~      counts of each unique character
 (%*/)             divide left by the product of right
      &:!          after applying ! to both
FrownyFrog
fuente
1
#(%*/)&:!#/.~debería guardar otro byte
millas
0

Ohm v2 , 4 bytes

ψD∩l

Pruébalo en línea!

Explicación

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