Bir Word'deki Olası Tüm Harf Kombinasyonlarını Sayın


12

Size, normal az karakterleri içeren bir dize verilir. (Bunun herhangi bir testte her zaman geçerli olacağını ve tüm harflerin de küçük harf olacağını varsayabilirsiniz). Dizedeki tek tek karakterlerden kaç tane benzersiz kombinasyon yapılabileceğini belirlemeli ve bu sayıyı yazdırmalısınız.

Ancak, olası kombinasyonlar sayılırken yinelenen harfler yok sayılabilir. Başka bir deyişle, verilen dize "merhaba" ise, iki ls'nin konumlarını değiştirmek benzersiz bir ifade olarak sayılmaz ve bu nedenle toplama sayılmaz.

En kısa bayt sayısı kazanır, golf dışı dillerde yaratıcı çözümler görmeyi dört gözle bekler!

Örnekler:

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


4
@Giuseppe Bunun bir çift olduğunu sanmıyorum; Bu sorunun ayrıntıları çok daha kısa uygulamalara izin verir
ArBo

4
Bazı testcasları eklemek yardımcı olabilir.
tsh

1
@JonathanAllan İyi öneri! Başlık buna göre değişti.
SimpleGeek

Yanıtlar:


29

Python 2 , 50 48 bayt

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

Çevrimiçi deneyin!

Sıkıcı yerleşik yok! Şaşırtıcı bir şekilde, bu kaba kuvvet yaklaşımından bile daha kısadır, tüm permütasyonları hesaplar itertoolsve uzunluğu alır.

Bu işlev formülü kullanır

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

ve anında hesaplar. Paydaki faktöryel, len(s)her fonksiyon çağrısında çarpılarak hesaplanır . Payda biraz daha incedir; her çağrıda, dizenin solundaki öğenin oluşum sayısına böleriz ve her karakter için c1 arasındaki tüm sayıların ve c(dahil) oluşumlarının tam olarak bir kez bölünmesini sağlarız. Yalnızca en sonunda böldüğümüz için, Python 2'nin varsayılan kat bölümü ile ilgili herhangi bir sorun yaşamamamız garanti edilir.


itertools işlev adlarında çok ayrıntılı
qwr



5

R , 69 65 bayt

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

Çevrimiçi deneyin!

Her iki cevapta da Zahiro Mor sayesinde 4 bayt tasarruf etti .

Multinom katsayısını doğrudan hesaplar.

R , 72 68 bayt

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

Çevrimiçi deneyin!

Çok dmultinomterimli katsayıyı çıkarmak için sağlanan çok terimli dağıtım işlevini kullanır .

Her zamanki (golfçü) bilinmeyen bir nedenden ötürü çağrı x<-table(strsplit(s,""))içinde çalışmaz dmultinom.


2
function(s,! =factorial)(!nchar(s))/prod(!table(strsplit(s,""))) çalışacak. el () reduntant - tablo öğeleri aramak için bilir ....
Zahiro Mor

1
@ZahiroMor ah, elbette. Bunu test etmeyi amaçlamıştım ama hiç uğraşmadım.
Giuseppe

5

JavaScript (Node.js) , 49 bayt

t=t*tüm ara (operatör açısından) sonuçların tam sayı olmasını garanti ettiği t*=için yuvarlama hatasını ( |tsayı aşağı yuvarlar) önlemek için kullanılır t=t*.

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

Çevrimiçi deneyin!

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
(Potansiyel kayan nokta yuvarlama hatası; t=t*bundan kaçınmak istiyorsanız kullanın.)
Neil

@Neil Evet, giriş aaadegfbbbccctam olarak kayan nokta yuvarlama hatası nedeniyle başarısız oldu
Shieru Asakoto

Ha, bu test durumunu nasıl buldun?
Neil

@Neil Böyle bir yuvarlama hatası oluşana kadar dizeye karakter eklemeye devam edin lol
Shieru Asakoto

@ShieruAsakoto Başlık değiştirildi; sayısı çok daha iyi. Teşekkürler ve güzel cevap!
SimpleGeek








2

APL (Dyalog Unicode) , 24 bayt

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

Çevrimiçi deneyin!

Basit Dfn, bir dizgeyi bağımsız değişken olarak alır.

Nasıl:

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 karakter ( 34 31 bayt)

Oldukça düz ileri Whateverblok. combdizgiyi harflere böler, permutationstüm olası kombinasyonları alır. Önce zorlamanın düzenlenmesi Setgerektiği için join( listedeki her bir öğe için »geçerlidir join).

+*.comb.permutations».join.Set

Çevrimiçi deneyin!

(önceki yanıt kullanıldı, .uniqueancak Setbenzersizliği garanti ediyor ve aynısını sayısallaştırıyor, böylece 3 kaydediyor).


2

K (ok) , 12 bayt

Çözüm:

#?x@prm@!#x:

Çevrimiçi deneyin!

Açıklama:

Dahili OK kullanır prm:

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

... x^/:xtemelde "helo"değil "hello", sadece permütasyonları üretir , bu yüzden permütasyonları üretmemiz 0 1 2 3 4, bunları endekslemek için kullanmamız "hello"ve benzersiz olanın sayısını almamız gerekir.

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

Prm iyi bir operatör müdür? Vanilya k'da olduğunu sanmıyorum?
Henry Henrinson

Evet - her elkitabında
streetster

@HenryHenrinson afaik k4'te değil. k5'in başlarındaydı !-n. k5 ve k6'nın sonlarında olduprm . k7 (shakti) prmde var.
ngn

2

Java 8, 103102 bayt

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

Bağlantı Noktası @ArBo 's Python 2 cevap . @ OlivierGrégoire'a özyinelemeli yerine yinelemeli olarak
-1 bayt .

Çevrimiçi deneyin.

Aslında bir Sette tüm benzersiz permütasyonları üretmek ve boyutunu elde etmek 221 bayt olacaktır :

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

Çevrimiçi deneyin.



@ OlivierGrégoire Teşekkürler! Btw, ikinci yaklaşımı (bir kümede tüm benzersiz permütasyonları üreten) daha kısa hale getirecek bir şey görüyor musunuz? Bazı baytların kaydedilebileceğini hissediyorum, ama bazı şeyleri denedim ve çoğu daha kısa yerine biraz daha uzundu .. Ama yine de aşırı uzun tbh görünüyor.
Kevin Cruijssen

Bunun üzerinde çalışıyordum, akarsu kullanmaya ve saymaya çalışıyorum, şu şekilde: 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;}ama şimdiye kadar başarı olmadan ...
Olivier Grégoire


1

Oktav / MATLAB, 35 bayt

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

Bir karakter vektörü alan ve bir sayı üreten anonim işlev.

MATLAB'de bu size(unique(perms(s),'ro'),1)(33 bayt) kısaltılabilir .

Çevrimiçi deneyin!

açıklama

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

1
uniqueZaten benzersiz satırlar döndürdüğünü düşündüm ? Yoksa bu sadece tables için mi?
Giuseppe

@Giuseppe Önce sayısal / karakter 2B diziler uniquedoğrusallaştırılır. Tablolar için haklı olduğunu düşünüyorum; Bunu bilmiyordum!
Luis Mendo

1
Ah, fikri nereden bulduğumu biliyorum - uniqueMATLAB'da satırlar alıyor tables; R'ler unique, benzersiz matris satırları veya veri çerçeveleri alır. Aynı komutlarla biraz farklı şeyler yapan çok fazla dizi dili ...
Giuseppe

1

Retina 0.8.2 , 73 bayt

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

Çevrimiçi deneyin! @ ArBo formülünü kullanır, ancak sağdan sola doğru değerlendirir, çünkü bu, tamsayı aritmetiğinde yapılabilirken, ilgili tek değerlerin boyutunu en aza indirir. Açıklama:

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

Her karakter için, kalan kopyaların sayısını ve kaç tane daha karakter olduğunu sayın, mevcut karakteri dikkate almak için her birine bir tane ekleyin ve değerleri ayırın, böylece hangilerinin bölüneceğini ve hangilerinin çarpılacağını biliyoruz .

^
1

Tam bir ifade üretmek için a 1 önekini ekleyin.

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

Son ikinci sayıya bölünürken son ve üçüncü son sayıları tekrar tekrar çarpın. Bu, son üç sayının yerini alır.

1

Ondalık biçime dönüştür.


1

K, 27 bayt

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

K, 16 bayt - gerçek bir cevap değil

#?(999999#0N)?\:

Giriş dizesinin 999999 rasgele permütasyonunu alın, benzersiz kümesini alın ve uzunluğu sayın. Çoğu zaman kısa devre dizeleri için doğru cevabı verecektir.

@Sriotchilism O'Zaic, @Selcuk sayesinde geliştirildi


2
Siteye Hoşgeldiniz! Geçersiz olduğu için gerçekten önemli değil ama geçersiz cevabınızı 999999yerine kullanarak daha doğru hale getirebilir misiniz 100000?
Ad Hoc Garf Hunter

Evet, iyi fikir, teşekkürler.
Henry Henrinson

1
Ve belki de bu değişikliği yansıtmak için açıklamayı düzenleyin?
Selçuk

1

Wolfram Dili (Mathematica) , 32 bayt

Characters/*Permutations/*Length

Çevrimiçi deneyin!

Açıklama: Sağ kompozisyon, /*bu üç operatörü birbiri ardına fonksiyon argümanına soldan sağa uygular:

  • Characters giriş dizesini bir karakter listesine dönüştürür.

  • Permutations bu karakter listesinin tüm benzersiz permütasyonlarının bir listesini yapar.

  • Length bu benzersiz permütasyonlar listesinin uzunluğunu döndürür.

Bu yöntem uzun dizeler için çok israftır: benzersiz permütasyonlar, Multinomialnumaralarını listeleme olmadan hesaplamak için a kullanmak yerine, aslında listelenir ve sayılır .



1

Pyth , 5 4 bayt

l{.p

Çevrimiçi deneyin!

Bu, girdinin bir python dizesi değişmezi olduğunu varsayar. Girişin ham metin olması gerekiyorsa, bu 5 baytlık sürüm çalışır:

l{.pz

Her iki şekilde de, girdinin tüm permütasyonlarını bir liste olarak hesaplar, tekilleştirir ve içindeki eleman sayısını alır ve bu sayıyı dolaylı olarak yazdırır.

@ Hakr14 sayesinde -1 bayt


{daha küçük bir bayt için bir listeyi tekilleştirir .{.
hakr14

1

J , 14  13 bayt

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

Çevrimiçi deneyin!

Mil sayesinde 1 bayt

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

1
#(%*/)&:!#/.~başka bir bayt kurtarmalı
mil



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.