単語内の文字のすべての可能な一意の組み合わせを数える


11

通常のaz文字を含む文字列が与えられます。(これはどのテストでも常に当てはまると想定でき、すべての文字も小文字であると想定できます)。文字列内の個々の文字の一意の組み合わせの数を決定し、その数を印刷する必要があります。

ただし、可能な組み合わせを数える際に、重複した文字は無視できます。つまり、指定された文字列が「hello」の場合、2つlのsの位置を単純に切り替えても一意のフレーズとしてカウントされないため、合計にカウントすることはできません。

最短バイト数が勝ち、非ゴルフ言語でのクリエイティブなソリューションを楽しみにしています!

例:

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


4
@ジュゼッペこれはだましだとは思わない。この質問の詳細により、はるかに短い実装が可能になります
-ArBo

4
いくつかのテストケースを追加すると役立つ場合があります。
tsh

1
@JonathanAllan良い提案!それに応じてタイトルが変更されました。
I_P_Edwards

回答:


29

パイソン250の 48バイト

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

オンラインでお試しください!

退屈なビルトインはありません!驚いたことに、これはブルートフォースアプローチよりもさらに短く、すべての順列を計算しitertools、長さを取得します。

この関数は式を使用します

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

その場で計算します。分子の階乗は、len(s)各関数呼び出しで乗算することにより計算されます。分母はもう少し微妙です。各呼び出しで、文字列の左側にあるその要素の出現回数で除算しc、すべての文字について、1からc(出現範囲を含む)の出現数までのすべての数値が1 回だけ分割されるようにします。最後にのみ分割するため、Python 2のデフォルトのフロア分割に問題がないことが保証されています。


itertoolsの関数名は非常に冗長です
-qwr



5

R69 65バイト

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

オンラインでお試しください!

両方の回答でMor Zairoのおかげで4バイト節約されました。

多項係数を直接計算します。

R72 68バイト

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

オンラインでお試しください!

によって提供される多項分布関数を使用してdmultinom、多項係数を抽出します。

通常の(ゴルファ)x<-table(strsplit(s,""))dmultinom、不明な理由でコール内では機能しないことに注意してください。


2
function(s,=factorial)(!nchar(s))/prod(!table(strsplit(s,""))) 働くでしょう。テーブルが要素を探すために知っている.... - ELは()reduntantある
Zahiro Morの

1
@ZahiroMorああ、もちろん。私はそれをテストするつもりでしたが、それを回避することはありませんでした。
ジュゼッペ

5

JavaScript(Node.js)、49バイト

t=t*代わりに、すべての中間(演算子ごとの)結果が整数であることを保証t*=するために、丸め誤差(|t数値の切り捨て)を回避するために使用されt=t*ます。

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

オンラインでお試しください!

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
(潜在的な浮動小数点の丸めエラー。t=t*それを避けたい場合に使用してください。)
ニール

そう@Neilそれが入力されたときに失敗aaadegfbbbcccによる浮動小数点丸め誤差に正確
Shieru Asakoto

ええと、どうやってそのテストケースを見つけましたか?
ニール

@Neilこのような丸めエラーが発生するまで、文字列に文字を追加し続けますlol
浅本シエル

@ShieruAsakotoタイトルが変更されました。カウントははるかに優れています。ありがとう、いい答えです!
I_P_Edwards








2

APL(Dyalog Unicode)、24バイト

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

オンラインでお試しください!

単純なDfnは、引数として文字列を取ります。

どうやって:

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文字(34 31バイト)

かなり単純なWhateverブロック。 comb文字列を文字に分割し、permutations可能なすべての組み合わせを取得します。強制を最初に行うSet必要があるためjoin(リストの各要素に»適用join)。

+*.comb.permutations».join.Set

オンラインでお試しください!

(以前の回答が使用されました.uniqueが、Setsは一意性を保証し、同じものを数えるため、3を節約します)。


2

K(oK)、12バイト

解決:

#?x@prm@!#x:

オンラインでお試しください!

説明:

oKビルトインを使用しprmます:

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

...これはx^/:x基本的に"helo"not の順列"hello"を生成するため、の順列を生成する必要があり0 1 2 3 4、それらを使用してインデックスを作成し"hello"、一意のカウントを取得します。

#?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は大丈夫な演算子ですか?私はバニラkがそれを持っているとは思わない?
ヘンリーヘンリンソン

うん

@HenryHenrinson afaikそれはk4ではありません。初期のk5ではそうでした!-n後半のk5とk6では、になりましたprm。k7(shakti)も持っていprmます。
ngn

2

ジャワ8、103の 102バイト

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

@ArBoのPython 2回答のポート。@OlivierGrégoireの
おかげで、再帰的ではなく反復的になった-1バイト。

オンラインでお試しください。

Setですべての一意の順列を実際に生成し、そのサイズを取得すると221バイトになります

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

オンラインでお試しください。


さて、再帰的ではなく反復的にすることで1バイトゴルフすることができます:s->{int r=1,i=s.length();for(;i>0;)r=r*i/~-s.substring(--i).split(s.charAt(i)+"",-1).length;return r;}
オリビエグレゴワール

@OlivierGrégoireありがとう!ところで、2番目のアプローチ(セット内のすべての一意の順列を生成する)を短くする何かを見ますか?私はいくつかのバイトを節約できると感じていますが、いくつかのことを試してみましたが、ほとんどは短くなるのではなくわずかに長くなりました。
ケビンCruijssen

私はこのように、ストリームを使用してカウントしようとし、それに取り組んできました。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;}しかし、成功せず、これまで...
オリヴィエ・グレゴワール


1

オクターブ / MATLAB、35バイト

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

文字ベクトルを受け取り、数値を生成する匿名関数。

MATLABでは、これをsize(unique(perms(s),'ro'),1)(33バイト)に短縮できます。

オンラインでお試しください!

説明

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

1
unique一意の行がすでに返されていると思いましたか?それともtables だけですか?
ジュゼッペ

@Giuseppe数値/文字2D配列のunique場合、最初に線形化されます。テーブルについては、あなたが正しいと思います。知らなかった!
ルイス・Mendo

1
ああ、私はどこでアイデアを得たかを知ってuniqueいます-MATLABではtables; R uniqueは、行列またはデータフレームの一意の行を取ります。同じコマンドでわずかに異なることを行う配列言語が多すぎる
ジュゼッペ

1

Retina 0.8.2、73バイト

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

オンラインでお試しください!@ArBoの式を使用しますが、関連する単項値のサイズを最小化しながら整数演算で実行できるため、右から左に評価します。説明:

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

各キャラクターについて、残りの重複の数とさらにキャラクターの数をカウントし、それぞれに1を追加して現在のキャラクターを考慮し、値を分離して、どのキャラクターを分割し、どのキャラクターを乗算するかを把握します。

^
1

完全な式を生成するには、1をプレフィックスします。

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

最後から2番目の数字で除算しながら、最後と3番目の最後の数字を繰り返し乗算します。これにより、最後の3つの数字が置き換えられます。

1

10進数に変換します。


1

K、27バイト

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

K、16バイト-実際の答えではない

#?(999999#0N)?\:

入力文字列のランダムな順列999999を取得し、それらの一意のセットを取得して長さをカウントします。ほとんどの場合、短い文字列に対して正しい答えが得られます。

@Sriotchilism O'Zaic、@ Selcukのおかげで改善


2
サイトへようこそ!それは無効なので本当に問題ではありませんが、999999代わりにを使用して無効な回答をより正確にすることができます100000か?
ポストロックガーフハンター

うん、いいアイデア、ありがとう。
ヘンリーヘンリンソン

1
そして、おそらくその変更を反映するように説明を編集しますか?
セルチュク

1

Wolfram言語(Mathematica)、32バイト

Characters/*Permutations/*Length

オンラインでお試しください!

説明:との右構成/*は、これらの3つの演算子を関数引数に左から右に次々に適用します。

  • Characters 入力文字列を文字のリストに変換します。

  • Permutations この文字リストのすべての一意の順列のリストを作成します。

  • Length 一意の順列のこのリストの長さを返します。

この方法は、長い文字列に対して非常に無駄があります。一意の順列は、リストを使用Multinomialせずに番号を計算するためにa を使用する代わりに、実際にリストおよびカウントされます。



1

Pyth5 4バイト

l{.p

オンラインでお試しください!

これは、入力がpython文字列リテラルであることを前提としています。入力が生のテキストでなければならない場合、この5バイトバージョンは動作します。

l{.pz

いずれにしても、入力のすべての順列をリストとして計算し、重複を排除してその中の要素の数を取得し、その数を暗黙的に出力します。

@ hakr14のおかげで-1バイト


{未満のバイトのリストを重複排除します.{
hakr14




弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.