Policz wszystkie możliwe unikalne kombinacje liter w jednym słowie


12

Otrzymasz ciąg znaków, który będzie zawierał zwykłe znaki az. (Możesz założyć, że tak będzie zawsze w każdym teście, i załóż, że wszystkie litery również będą pisane małymi literami). Musisz określić, ile unikalnych kombinacji można utworzyć z poszczególnych znaków w ciągu, i wydrukować tę liczbę.

Jednak zduplikowane litery można zignorować, licząc możliwe kombinacje. Innymi słowy, jeśli podany ciąg to „hello”, to po prostu zmiana pozycji dwóch ls nie jest liczona jako unikalna fraza i dlatego nie może być liczona do sumy.

Zwycięża najkrótsza liczba bajtów, czekamy na kreatywne rozwiązania w językach innych niż golf!

Przykłady:

hello -> 60
aaaaa -> 1
abcde -> 120


4
@Giuseppe Nie sądzę, że jest to duplikat tego; specyfika tego pytania pozwala na znacznie krótsze wdrożenia
ArBo

4
Dodanie niektórych przypadków testowych może pomóc.
tsh

1
@JathanathanAllan Dobra sugestia! Tytuł odpowiednio się zmienił.
SimpleGeek

Odpowiedzi:


29

Python 2 , 50 48 bajtów

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

Wypróbuj online!

Żadnych nudnych wbudowanych funkcji! Ku mojemu zdziwieniu jest to nawet krótsze niż podejście z użyciem brutalnej siły, obliczając wszystkie permutacje itertoolsi biorąc pod uwagę długość.

Ta funkcja korzysta ze wzoru

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

i oblicza go w locie. Silnia w liczniku jest obliczana przez pomnożenie przez len(s)w każdym wywołaniu funkcji. Mianownik jest nieco bardziej subtelny; w każdym wywołaniu dzielimy przez liczbę wystąpień tego elementu w pozostałej części łańcucha, zapewniając, że dla każdego znaku cwszystkie liczby od 1 do liczby wystąpień c(włącznie) zostaną podzielone przez dokładnie jeden raz. Ponieważ dzielimy tylko na samym końcu, gwarantujemy, że nie będziemy mieć problemów z domyślnym podziałem podłogi w Python 2.


itertools jest bardzo gadatliwy w nazwach swoich funkcji
qwr


7

CJam , 4 bajty

le!,

Wypróbuj online!

Wyjaśnienie

Czytaj linię jako ciąg znaków ( l), unikalne permutacje jako tablicę ciągów znaków ( e!), długości ( ,), niejawne wyświetlanie.


4
Wygląda jak „lel”, +1! : D
KeyWeeUsr

5

R , 69 65 bajtów

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

Wypróbuj online!

4 bajty zapisane dzięki Zahiro Morowi w obu odpowiedziach.

Oblicza bezpośrednio współczynnik wielomianowy.

R , 72 68 bajtów

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

Wypróbuj online!

Korzysta z funkcji rozkładu wielomianowego podanej w dmultinomcelu wyodrębnienia współczynnika wielomianowego.

Pamiętaj, że zwykły (golfista) x<-table(strsplit(s,""))nie działa w dmultinompołączeniu z nieznanego powodu.


2
function(s,! =factorial)(!nchar(s))/prod(!table(strsplit(s,""))) będzie działać. el () jest reduntant - tabela wie, jak szukać elementów ....
Zahiro Mor

1
@ZahiroMor ah, oczywiście. Zamierzałem to przetestować, ale nigdy do tego nie doszło.
Giuseppe

5

JavaScript (Node.js) , 49 bajtów

t=t*służy t*=do uniknięcia błędu zaokrąglania ( |tzaokrągla liczbę w dół), ponieważ t=t*gwarantuje, że wszystkie wyniki pośrednie ( z punktu widzenia operatora) są liczbami całkowitymi.

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

Wypróbuj 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

2
(Potencjalny błąd zaokrąglania zmiennoprzecinkowego; użyj, t=t*jeśli chcesz tego uniknąć.)
Neil

@Neil Tak, nie udało się, gdy dane wejściowe są aaadegfbbbcccdokładnie spowodowane błędem zaokrąglenia zmiennoprzecinkowego
Shieru Asakoto

Huh, jak znalazłeś ten przypadek testowy?
Neil

@Neil Dodawaj znaki do łańcucha, dopóki nie wystąpi taki błąd zaokrąglania lol
Shieru Asakoto

@ShieruAsakoto Tytuł został zmieniony; liczba jest znacznie lepsza. Dzięki i miła odpowiedź!
SimpleGeek








2

APL (Dyalog Unicode) , 24 bajty

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

Wypróbuj online!

Prosty Dfn, przyjmuje ciąg znaków jako argument.

W jaki sposób:

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



2

Perl 6 , 33 30 znaków ( 34 31 bajtów)

Dość prosty Whateverblok. combdzieli ciąg na litery, permutationsuzyskuje wszystkie możliwe kombinacje. Ze względu na sposób, w jaki Setnależy joinnajpierw »zastosować przymus ( dotyczy joinkażdego elementu na liście).

+*.comb.permutations».join.Set

Wypróbuj online!

(poprzednia użyta odpowiedź, .uniqueale Sets gwarantuje unikatowość i numeruje to samo, więc oszczędza 3).


2

K (oK) , 12 bajtów

Rozwiązanie:

#?x@prm@!#x:

Wypróbuj online!

Wyjaśnienie:

Wykorzystuje wbudowane OK prm:

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

... który w x^/:xzasadzie generuje permutacje "helo"nie "hello", dlatego musimy wygenerować permutacje 0 1 2 3 4, użyć ich do indeksowania, "hello"a następnie policzyć unikalność.

#?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 (#)

Czy prm jest ok konkretnym operatorem? Nie sądzę, że ma waniliowy k?
Henry Henrinson

Tak - istnieje tylko w ok według instrukcji
streetster

@HenryHenrinson afaik nie ma go w k4. na początku k5 było !-n. pod koniec k5 i k6 stało sięprm . K7 (Shakti) prmteż ma .
ngn

2

Java 8, 103 102 bajtów

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 odpowiedzi @ArBo na Python 2 .
-1 bajt dzięki @ OlivierGrégoire poprzez iterację zamiast rekurencji.

Wypróbuj online.

W rzeczywistości wygenerowanie wszystkich unikalnych permutacji w zestawie i uzyskanie jego rozmiaru wynosi 221 bajtów :

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

Wypróbuj online.



@ OlivierGrégoire Thanks! Przy okazji, widzisz coś, co skraca drugie podejście (generowanie wszystkich unikalnych permutacji w zestawie)? Mam wrażenie, że niektóre bajty można zapisać, ale próbowałem pewnych rzeczy, a większość z nich była nieco dłuższa, a nie krótsza. Ale wciąż wygląda na zbyt długo.
Kevin Cruijssen

Pracowałem nad tym, próbując używać strumieni i liczyć, w ten sposób: 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;}ale jak dotąd bez powodzenia ...
Olivier Grégoire,


1

Octave / MATLAB, 35 bajtów

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

Anonimowa funkcja, która pobiera wektor znaków i tworzy liczbę.

W MATLAB można to skrócić do size(unique(perms(s),'ro'),1)(33 bajtów).

Wypróbuj online!

Wyjaśnienie

@(s)                                  % Anonymous function with input s
                perms(s)              % Permutations. Gives a char matrix
         unique(        ,'rows')      % Deduplicate rows
    size(                       ,1)   % Number of rows

1
Myślałem, że zwróciłem uniquejuż unikalne wiersze? Czy to tylko dla tables?
Giuseppe

@Giuseppe Dla tablic numerycznych / char 2D uniquenajpierw ulegałyby linearyzacji. W przypadku stolików myślę, że masz rację; Nie wiedziałem tego!
Luis Mendo

1
Ach, wiem skąd mam pomysł - uniquew MATLAB bierze wierszetables ; R uniquepobiera unikalne rzędy macierzy lub ramek danych. Zbyt wiele języków tablic z tymi samymi poleceniami, które robią nieco inne rzeczy ...
Giuseppe,

1

Retina 0.8.2 , 73 bajty

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

Wypróbuj online! Wykorzystuje formułę @ ArBo, ale ocenia od prawej do lewej, ponieważ można tego dokonać w arytmetyce liczb całkowitych, jednocześnie minimalizując wielkość zaangażowanych wartości jednostkowych. Wyjaśnienie:

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

Dla każdego znaku policz, ile pozostało duplikatów i ile jest kolejnych znaków, dodaj po jednym do każdego z nich, aby uwzględnić bieżący znak, i rozdziel wartości, abyśmy wiedzieli, które z nich mają zostać podzielone, a które należy pomnożyć .

^
1

Przedrostek 1, aby uzyskać pełne wyrażenie.

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

Kilkakrotnie pomnóż ostatnią i trzecią ostatnią liczbę, dzieląc ją przez drugą ostatnią liczbę. Zastępuje to ostatnie trzy liczby.

1

Konwertuj na dziesiętny.


1

K, 27 bajtów

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

K, 16 bajtów - nie jest to prawdziwa odpowiedź

#?(999999#0N)?\:

Weź 999999 losowych kombinacji łańcucha wejściowego, weź ich unikalny zestaw i policz długość. Przez większość czasu daje właściwą odpowiedź, w przypadku krótkich łańcuchów.

Poprawiono dzięki @Sriotchilism O'Zaic, @Selcuk


2
Witamy na stronie! To naprawdę nie ma znaczenia, ponieważ jest nieważne, ale czy możesz poprawić swoją nieprawidłową odpowiedź, używając 999999zamiast niej 100000?
Ad Hoc Garf Hunter,

Tak, dobry pomysł, dzięki.
Henry Henrinson

1
A może edytować wyjaśnienie, aby odzwierciedlić tę zmianę?
Selcuk

1

Wolfram Language (Mathematica) , 32 bajty

Characters/*Permutations/*Length

Wypróbuj online!

Objaśnienie: Kompozycja po prawej stronie /*stosuje te trzy operatory jeden po drugim do argumentu funkcji, od lewej do prawej:

  • Characters konwertuje wejściowy ciąg znaków na listę znaków.

  • Permutations tworzy listę wszystkich unikalnych kombinacji tej listy znaków.

  • Length zwraca długość tej listy unikalnych permutacji.

Ta metoda jest bardzo marnotrawna w przypadku długich ciągów: unikatowe permutacje są faktycznie wyświetlane i liczone, zamiast używać a Multinomialdo obliczania ich liczby bez wyświetlania.



1

Pyt , 5 4 bajtów

l{.p

Wypróbuj online!

Zakłada się, że dane wejściowe to literał ciągu znaków w języku Python. Jeśli dane wejściowe muszą być surowym tekstem, ta 5-bajtowa wersja będzie działać:

l{.pz

Tak czy inaczej, po prostu oblicza wszystkie permutacje danych wejściowych jako listę, deduplikuje je, pobiera liczbę elementów i domyślnie drukuje tę liczbę.

-1 bajt dzięki @ hakr14


{deduplikuje listę dla bajtu mniejszego niż .{.
hakr14

1

J , 14  13 bajtów

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

Wypróbuj online!

1 bajt dzięki milom

#                  length
         #/.~      counts of each unique character
 (%*/)             divide left by the product of right
      &:!          after applying ! to both

1
#(%*/)&:!#/.~powinien oszczędzić kolejny bajt
mile



Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.