順列の楽しみ


17

順列を絶対に好きではない人はいますか?私は知っています、彼らは驚くべきことです。とても楽しいです!

さて、なぜこの楽しさを取ると、それにしないfunner

これが課題です。

正確な形式で入力所与:nPrnプールから採取されるとr、そのプールからの選択の数である(そしてnそしてr整数である)、出力/順列の正確な数を返します。用語で少し錆びているあなたのために:順列、定義。2a

ただし、これが課題の出番です(簡単ではありません):

置換関数に組み込みのライブラリ、フレームワーク、またはメソッドを使用することはできません。階乗法、順列法、またはそのようなものは使用できません。すべてを自分で書く必要があります。

さらに説明が必要な場合は、コメントで私に話すことをheしないでください、私はすぐにそれに応じて行動します。


I / Oの例を次に示します。

サンプル関数は permute(String) -> int

入力:

permute("3P2")

出力:

6

これはコードゴルフなので、最短のコードが勝ちです!


2
ああ この挑戦は順列グループにあると思いました。クール。これもクールで、順列グループと密接に関連しています。チャレンジが大好きです。
ジャスティン

組み込みメソッドやライブラリメソッドがないと言うとき、順列の意味ですか?組み込みを使用しsplitて入力をで分割できますPか?文字列を数値に変換する関数はどうですか?
-xnor

3
答えはそれを前提としてい0 <= r <= nますか?
ピーターテイラー

1
@Dopapp r nより大きくないということですか?
デニス

1
@RetoKoradi-ほとんどのポスターに答えをやり直させないようにするために、階乗法または順列の方法/関数を使用することは許可されていないと思います。
ダニエル

回答:


4

CJam、15 14バイト

r~\;~\),>UXt:*

CJamインタープリターでオンラインで試してください。

使い方

r              e# Read a token ("nPr") from STDIN.
 ~             e# Evaluate. This pushes the numbers n, Pi and r on the stack.
  \;           e# Discard Pi.
    ~          e# Take the bitwise NOT of r. Pushes -(r+1).
     \)        e# Increment n.    
       ,       e# Turn n+1 into [0 ... n].
        >      e# Keep only the last r+1 elements.
         UXt   e# Replace the first element with 1.
               e# This avoid dealing with the egde case nP0 separately.
            :* e# Compute their product.

4

Perl、27バイト

#!perl -pl61
$\*=$`-$%++for/P/..$'}{

シバンを4としてカウントすると、入力は標準入力から取得されます。


サンプルの使用法

$ echo 3P2 | perl npr.pl
6

$ echo 7P4 | perl npr.pl
840

どのようなオプションがありl61ますか?
feersum

それが設定@feersum $\1(CHAR 49進61)。
プリモ

3

ハスケル、 71 66バイト

p s|(u,_:x)<-span(/='P')s,(n,k)<-(read u,read x)=product[n-k+1..n]

非常に簡単なもの:「P」で分割し、(n-k + 1)とnの間の積を取ります。

where節ではなくパターンガードを使用するというアイデアを提供してくれたnimiのおかげで、5バイト削減されました。


2

Minkolang 0.1113の 25 19バイト

これを提案してくれたSp3000に感謝します!

1nnd3&1N.[d1-]x$*N.

ここで試してみてください。

説明

1        Push 1
n        Take integer from input (say, n)
n        Take integer from input (say, k); ignores non-numeric characters in the way
d3&1N.   Output 1 if k is 0
[   ]    Loop k times
 d1-     Duplicate top of stack and subtract 1
x        Dump top of stack
$*       Multiply all of it together
N.       Output as integer

これは、Alexのと同じアルゴリズムを使用します:n P k= n(n-1)(n-2)...(n-k+1)


2

ジュリア、63 58 48バイト

s->((n,r)=map(parse,split(s,"P"));prod(n-r+1:n))

これにより、文字列を受け入れて整数を返す名前のない関数が作成されます。呼び出すには、名前を付けf=s->...ます。

ゴルフをしていない:

function f(s::AbstractString)
    # Get the pool and number of selections as integers
    n, r = map(parse, split(s, "P"))

    # Return the product of each number between n-r+1 and n
    return prod(n-r+1:n)
end

これは、順列の数がnn -1)(n -2)...(n - k +1)であるという事実を使用しています。

グレンOのおかげで10バイト節約できました!


必要はありませんのでInt、あなただけを使用することができますmap(parse,...)
グレンO

@GlenO私の心は吹き飛ばされました。Intその状況では必要だとは思いませんでした。本当にありがとう!
アレックスA.

2

Bash + Linuxユーティリティ、33

jot -s\* ${1#*P} $[${1/P/-}+1]|bc

jotr始まる整数のシーケンスを生成しn-r+1、で区切ります*。この式はbc算術評価のためにパイプされます。


1

MATLAB、54バイト

[n,r]=strread(input(''),'%dP%d');disp(prod((n-r+1):n))

小さくしようとしましたが、MATLABが本当に苦手なことの1つは入力の取得です。入力文字列から2つの数字を取得するだけで32文字かかります!

かなり自明なコード。%dP%d%dが整数である形式で入力を取得します。それをnとに分割しrます。次に、範囲内のすべての整数の積を表示n-r+1nます。興味深いことに、これはでものために働くxP01.本の正しい答えを与えるため、MATLABであるprod()あなたは空の配列の製品を試してみてください場合、関数が戻る1。たびrゼロで、範囲は、我々は1を取得するので、ビンゴ、空の配列になります。


これはOctaveでも同様に機能します。こちらからオンライン試すことができます



1

Java(594-バイト)

import java.util.*;import java.lang.*;public class Perm {private String a;private static int[] nr=new int[2];private static int sum=1;Scanner in=new Scanner(System.in);public String input(){a=in.nextLine();return a;}public void converter(String a){this.a=a;String b=a.substring(0,1);String c=a.substring(2);nr[0]=Integer.parseInt(b);nr[1]=Integer.parseInt(c);}public int param(){for(int counter=0; counter < nr[1]; counter++){sum=sum*nr[0]--;}return sum;}public static void main(String args[]){Perm a;a=new Perm();String k=a.input();a.converter(k);int ans=a.param();System.out.println(ans);}}

1

J、23バイト

^!._1/@(".;._1)@('P'&,)

匿名関数。例:

   f =. ^!._1/@(".;._1)@('P'&,)
   f '10P4'
5040

説明:

       (  ;._1)@('P'&,)   Split over 'P', and on each slice,
        ".                read a number.
      @                   Then,
^!._1/                    fold (/) with the built-in "stope function" (^!.k) for k=1.

STOPE機能を内蔵し...それは乗算演算子の一般性と階乗演算子の特異性との間にどこかにかかっているように私は、計数上かもしれないの境界線を使用。


1

APL、23

{{×/⍵↑⍳-⍺}/-⍎¨⍵⊂⍨⍵≠'P'}

引数として文字列を取ります。説明:

              ⍵⊂⍨⍵≠'P'  ⍝ Split by 'P'.
           -⍎¨          ⍝ Convert to numbers and negate making a vector (−n −r)
 {       }/             ⍝ Reduce it by a defined function, which
      ⍳-⍺               ⍝ makes a vector of numbers from 1 to n (⍺)
    ⍵↑                  ⍝ takes r last elements (⍵←−r)
  ×/                    ⍝ and multiplies them together.

これはどのAPLですか?Dyalogのコピーでエラーが発生します。
リトシアスト

1
@ThomasKwa ⎕ML←3Dyalogで使用します。
-user46915

1

Python 2、66

def f(s):a,b=map(int,s.split('P'));P=1;exec"P*=a;a-=1;"*b;print P

とても簡単です。入力された数値をとして処理しますa,b。実行中の製品をとして保持しP、これにの最初のb項を掛けa, a-1, a-2, ...ます。


2
どうしてinput()エラーにならないのかわかりません。
feersum

@feersum私はそれを試してみましたが、実際には構文エラーがスローされます。
アレックスA.

"3P2"は通常許可されていると思われる引用符で入力を取りましたが、ここでは「正確な形式の入力」という課題があるので、文字列を受け取る関数に変更します。
xnor

1

TI-BASIC、52バイト

Ans→Str1
expr(sub(Ans,1,⁻1+inString(Ans,"P→P        ;n
1
If expr(Str1                               ;If n^2*r ≠ 0
prod(randIntNoRep(P,P+1-expr(Str1)/P²
Ans

TI-BASICには「リストの積」機能があるため、組み込みの制限を回避するのはそれほど難しくありません。ただし、TI-BASICは空のリストをサポートしていません。そのため、

2つの数値を抽出するには、最初の数値を部分文字列として抽出します。これは高価です。2行目全体を占めます。2番目の数値についてこれを再度行う必要がないように、変数Pをその数値に設定し、を使用して文字列全体を評価してからexpr(、P²で除算します。

最後に、2つの数値間のリストのランダムな順列を取り(2番目の数値に1を加算するように注意して)、製品を取得します。


1

ウロボロス47 45バイト

これのいくつかは非常にいです-私はそれがさらにゴルフされるかもしれないと想像します。

Sr.r-1(
)s.!+S1+.@@.@\<!@@*Ys.!+*S.!!4*.(sn1(

ウロボロスの各コード行は、尾を食べるヘビを表しています。

ヘビ1

S共有スタックに切り替えます。r.r1つの番号を読み取り、それを複製し、別の番号を読み取ります。(のような非数値文字Pはスキップされます。)-2つを引きます。入力された場合は7P2、我々は今持っている75共有スタック上に。最後1(に、ヘビの最後のキャラクターを食べます。これは命令ポインターが置かれているキャラクターなので、ヘビは死にます。

ヘビ2

)s最初は何もしません。.!+snake 2のスタックの最上部を複製し、ゼロかどうかをチェックし、ゼロの場合は1を追加します。最初の反復では、スタックは空であり、無限のゼロを含んでいるかのように扱われ1ます。後の反復では、スタックにゼロ以外の値が含まれ、これは効果がありません。

次に、積を計算するためのS番号nとカウンターがある共有スタックに切り替えます。1+カウンターをインクリメントします。.@@.@\<!両方の数値を複製nし、カウンタ以上の場合は1をプッシュし、そうでない場合は0 をプッシュします。@@*Y次に、カウンターにこの量を掛けて、コピーをsnake 2のスタックにヤンクします。

s.!+snake 2のスタックに戻り、以前と同じコードを使用して、先頭の数値が0の場合は1に変換し、それ以外の場合は同じままにします。次に*、このスタックにあった部分積で結果を乗算します。

共有スタックに戻り(S)、カウンターまたはゼロを複製し(.)、それを2回否定(!!)してゼロ以外のカウンターを1に変えます。4*.(これに4を掛け、複製し、ヘビの終わり。

  • 停止状態に到達していない場合、スタックに4があります。の後の4文字(が食べられ、制御はコードの先頭までループします。ここでは)、4文字を逆流し、ssnake 2のスタックに切り替えて、実行を継続します。
  • カウンターが過ぎたら、nスタックに0があり、何も食べられません。snsnake 2のスタックに切り替え、数値として最上位の値を出力します。その後1(、最後のキャラクターを食べて死にます。

その結果、製品(r+1)*(r+2)*...*nが計算されて出力されます。

やってみよう

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