3つの入力を持つジョセフス問題


22

このサイトにはこの質問に似た質問がありますが、私はひねりを加えました。

あなたは3つの入力を持ち、円の中の人の数は、NK番目の人は、各ステップでアウトカウント、およびQ番目の人存続します。円の中の人には1からnまでの番号が付けられています。

たとえば、20人のサークルでは、生存する20番目の人が最初に削除され、19番目の生存者が2番目に削除されます。通常、ジョセフスの問題は、ここで最初の生存者と呼ばれる最後に削除された人を決定することです。

これらの3つの入力で、生き残るためにq番目の人の数を返す最短のプログラムまたは関数を記述します。

明確な問題がある場合は、お知らせください。

いくつかの例:

>>> josephus(20, 3, 9)
4
>>> josephus(4, 3, 1)
1
>>> josephus(100, 9, 12)
46

編集:すべての入力が有効であると仮定します。つまり、誰も0または負の数を要求せず、5人のサークル内の20番目の生存者を要求しません(つまり、1≤q≤n)。

編集: 12月2日の開始時のUTC + 7の深夜に回答を受け入れます。


1
独自のソリューションを質問に含めるのではなく、回答として投稿してください。
ドアノブ

とった。申し訳程度その
Sherlock9

1
明確化のために、q=1これがリンクされたジョセフスの質問とまったく同じである場合、そうですか?
AdmBorkBork

ちょうど@TimmyD
Sherlock9

回答:


5

Pyth、16バイト

eu.<PGvzh-QvwShQ

オンラインで試す:デモンストレーションまたはテストスイート

入力の形式はk<newline>n<newline>qです。

説明:

eu.<PGvzh-QvwShQ   implicit: z = first input line (string)
                             Q = second input line (integer)
              hQ   Q + 1
             S     the range [1, 2, ..., Q+1]
 u      h-Qvw      apply the following statement (Q-input()+1) times to G=^
    PG                remove the last number of G
  .<  vz              and rotate eval(z) to the left
e                  print the last number of the resulting list  

7

Piet、280 273コーデル

ここに画像の説明を入力してください

編集:私はこれをもう少し下にゴルフしました、そして、私はさらにそれを下にゴルフすることができると思います、それはまだ来ています。今のところ、私はそれが機能していることを嬉しく思っており、左下隅に署名する余地がありました。より多くのコーデルを保存する必要がある2つのアイデアは、a)終了命令を変更するpop, push 1, add, out num(ポップn、出力r + 1)およびb)ループの後半でスタック操作でコーデルを保存するために左下隅で再度複製することです。

上の写真は、コーデルあたり8ピクセルのコードです。一般的に、Pythonの答えと同じアルゴリズムですが、入力はkqnの順です。実際には、大量のスタック操作もあります。ここで画像を開き、それを使用してコードを実行することでここで試すことができます。

説明

これは、ソリューションの段階的なアンゴルフです。

in num    get k
dup       Stack: k k
push 1
subtract  Stack: k k-1
in num    get q
dup       Stack: k k-1 q q
dup       Stack: k k-1 q q q
push 4
push 2
roll      Stack: k q q k-1 q
mod       Stack: k q q r
in num    get n
# note: the loop will return to the following codel
dup       Stack: k q q r n n
push 4
push 3
roll      Stack: k q r n n q
greater   1 or 0
pointer   Here the loop begins. If q>n, the pointer moves clockwise.
          Else, it points straight ahead

LOOP:     Stack: k i r n (i=q at the start of the loop)
push 4
push 2
roll      Stack: r n k i
push 1
add       Stack: r n k i=i+1
push 2
push 1
roll      Stack: r n i k
dup       Stack: r n i k k
push 5
push 4
roll      Stack: n i k k r
add       Stack: n i k m=r+k
push 3
push 2
roll      Stack: n k m i
dup       Stack: n k m i i
push 3
# here it turns the corner
push 1
roll      Stack: n k i m i
mod       Stack: n k i r=m%i
push 4
# here it turns the corner and avoids the black codels
push 1
roll      Stack: r n k i
dup       Stack: r n k i i
push 5
push 3
roll      Stack: k i i r n
dup       Stack: k i i r n n
# and we meet up with the dark green codel once more
push 4
push 3
roll      Stack: k i r n n i
greater   Stack: k i r n (0 or 1)
pointer   if else again

# else    Stack: k i r n
push 2    
push 1
roll      Stack: k i n r
# and turn the corner
push 1
add       Stack: k i n r+1
out num   print r+1
# turn the corner into the end pattern (the shape with the black edges)
END

空きスペースをカウントしていませんか?Pietの得点方法に関するメタ投稿はどこかにありますか?おそらくあるはずです。
スパー

@Sparr、私は空のスペースを数えています。これは21コーデルx 13コーデル画像なので、スコアは273コーデルです。
シャーロック9

ああ、私は誤算しました。ごめんなさい。
スパー

4

CJam、22 20 19バイト

q~_,@a@*{m<)\}%\~=)

これは、入力をとして読み取りますq k nCJamインタープリターでオンラインで試してください。

使い方

q~                   Read and evaluate all input. This pushes q, k, and n.
  _,                 Push A := [0 ... n-1].
    @a               Rotate on top of the stack and wrap it in an array.
      @*             Rotate the original n on top and repeat [k] n times.
        {    }%      For each of the n k's:
         m<            Rotate A k units to the left.
           )\          Pop the last element and swap it with A.
               \~    Swap the resulting array with q and apply bitwise NOT.
                 =)  Select the corresponding element and add 1 to it.

3

Golfscript、58 56 55 35 31 30バイト

3つの入力が既にnkqの順にスタックにあると仮定します

~1$(1$%3$),@),-{\2$+\%}%\)])\;

その解決策は、最終的な答え以外のすべてを取り除く必要があることを前提としています。

使い方

詳細についてj(n,k,q)は、私のPython 3ソリューションをご覧ください。

~                                   Read the inputs n, k, q
 1$(                                Duplicate k, decrement
    1$                              Duplicate q
      %                             (k-1)%q
       3$),                         Create array [0..n+1]
           @),                      Create array [0..q+1]
              -                     Subtract the second array from the first,
                                        leaving only [q+1..n+1]
               {      }%            Map the following statement onto [q+1..n+1].
                                        The numbers from this array will be denoted i.
                \                   Swap i and r
                 2$+                Duplicate k, add to r
                    \               Swap r and i
                     %              r mod i
                        \)          Swap the leftover array from map with r, increment
                          ]         Put the whole stack into an array
                           )        Remove the last member of the array, r
                            \;      Pop the array, leaving only the result

編集1: @Doorknobの提案を使用(すべての入力を配列に取得するために+を追加)

以前は、

\.(2$2$*1$4$%-{.5$3$*>!}{~)2$*1$/~)}while 4$3$*\-)\;\;\;\;

編集2:ウィキのルールに従って〜を追加し、コードを短縮しました。ありがとう@デニス

以前は、

[\.(2$2$*1$4$%-{.5$3$*>!}{~)2$*1$/~)}while 4$3$*\-)]+)\;

編集3:短いアルゴリズムを実装しました。

以前は、

~\.(2$2$*1$4$%-{.5$3$*>!}{~)2$*1$/~)}while 4$3$*\-)]-1=

編集4:%マップとして使用できることがわかりました。

以前は、

~1$(1$%{1$4$<}{\)\2$+1$%}while)])\;

編集5:マイナー編集。変更2$@作ること[0..q-1]3$して2$取得することk。一口を保存しました

以前は、

~1$(1$%3$),2$),-{\3$+\%}%\)])\;

1
\;\;\;\;に置き換えることができます])\;(配列でラップ、右アンコン、スワップ、ポップ)。
ドアノブ

@Dennisを明確にするためにコードを編集しました。
Sherlock9

わかりました@デニス。〜を追加し、質問を編集して、プログラムと機能のみを許可しました。他に提案はありますか?
Sherlock9

いいえ、すべて良いです。:)
デニス

2

JavaScript(ES6)、56バイト

(n,k,q)=>{r=(k-1)%q;for(i=q;i<n;r=(r+k)%++i);return r+1}

非ゴルフ

基本的に@ Sherlock9のPythonの回答をJavaScriptに適合させたものです。

(n,k,q)=>{
  r=(k-1)%q;
  for(i=q;i<n;r=(r+k)%++i);
  return r+1
}

テスト

n = <input type="number" id="N" value="100" /><br />
k = <input type="number" id="K" value="9" /><br />
q = <input type="number" id="Q" value="12" /><br />
<button onclick="result.innerHTML=(

(n,k,q)=>{r=(k-1)%q;for(i=q;i<n;r=(r+k)%++i);return r+1}

)(+N.value,+K.value,+Q.value)">Go</button><br />
<pre id="result"></pre>


ungolfedのバージョンをungolfedとは呼びません:P
Fund Monicaの訴訟

1

Mathematica、50バイト

<<Combinatorica`
Tr@Position[Josephus@##2,1+#2-#]&

匿名関数。入力を順番に受け取りますq,n,k


1

C、81 73バイト

Pythonの答えの@ user81655のJavascript実装に基づいています。

編集: iを削除

int j(int n,int k,int q){int r=(k-1)%q;for(;q<n;r=(r+k)%++q);return r+1;}

テスト

#include <stdio.h>
int j(int n,int k,int q){int r=(k-1)%q;for(;q<n;r=(r+k)%++q);return r+1;}
int main()
{
    printf("%d\n", j(20,3,9));
    return 0;
}

Cの一部のバージョンではint、パラメーター名の前にドロップできます。
基金モニカの訴訟

1

Python 3、72 66 62バイト

62バイトの動的プログラミング関数。ウィキペディアのアルゴリズムから適応そのページでq = 1(つまりi = 1、r = 0)の場合、このアルゴリズムの直接実装が使用されていましたが、現在は削除されています。

編集1:i 4バイトを節約するために削除しました。説明は変更されていません。

編集2:バイトカウントの誤算。\r\nEOL に使用していましたが、3バイトが追加されたことに気付きませんでした。それに応じてバイト数を減らしました。

def j(n,k,q):
 r=(k-1)%q
 while q<n:q+=1;r=(r+k)%q
 return r+1

仕組み

def j(n,k,q):
 i=q;r=(k-1)%q              We start with the smallest possible circle to have a q-th
                                survivor, a circle of q people.
 while i<n:i+=1;            Iterate from q to n
                r=(r+k)%i   Every time you add people to the circle, r increases by k, 
                                modulo the current size of the circle i.
 return r+1                 Return the result.

私のコードを説明する必要があることを思い出させてくれた@Dennisに感謝します(暗黙のうちにのみ、彼が答えにコードを含めたからです)。不明な点がある場合はお知らせください。

編集:

以前は、

Graham、Knuth、Patashnikによるコンクリート数学から適応された反復関数。このアルゴリズムは長くなりますが、nが大きくkが小さい場合は高速です。

def t(n,k,q):
 m=k-1;z=q*k-m%q
 while z<=n*m:z=-(-z*k//m)
 return n*k-z+1

1
コピーペーストで何かを切り取ったように見えますが、ぶら下がりがあり+ます。
xnor

1

PHP、71バイト

@ Sherlock9の回答に基づいています。アルゴリズムについては、Pythonの回答をご覧ください。

function a($n,$k,$q){for($r=($k-1)%$q;$q<$n;$r=($r+$k)%++$q);echo$r+1;}

あるいは、アルゴリズムを使用しない私の最初の単純なアプローチもあります。これは、配列を使用して、見つかった人をマークします。

91バイト

function a($n,$k,$q){for($r=--$i;$q<=$n;++$i%$k||$c[$r]=$q++)while($c[$r=++$r%$n]);echo$r;}

1

Haskell、48 47 43バイト

(n!k)q=1+foldl(mod.(k+))(mod(k-1)q)[q+1..n]

2つの入力を持つJosephus関数のRosetta CodeページのHaskellアルゴリズムに基づいています。ゴルフの提案は大歓迎です。

編集:への私の感謝nimi pointfreeバージョンを示唆介して第一のアルゴリズムをゴルフとの助けのため、そして私がいることを知らせることにより、第2のアルゴリズムをゴルフとの助けのためのuntilキーワードが存在します。

(n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q)

Pythonの答えの最後にあるアルゴリズムのバージョンは、Graham、Knuth、PatashnikによるConcrete Mathematicsから採用されています。このアルゴリズムは62バイトでより長く、最初のアルゴリズムほどは学習されていませんがn、大小の場合は高速ですk

ゴルフをしていない:

最初のアルゴリズム

jos_g num step q = 1 + foldl (\x -> mod (x + step) ) (mod (step-1) q) [q+1..num]

2番目のアルゴリズム

jos_gkp num step q
    -- ceiling throws a type-related fit with ceiling(z*k/(k-1))
    -- better to use - div (-z * k) (k - 1)
    | m <- step-1 = 1 + num*step - until (>num*m)(\z-> -div (-z*k) m) (q*step - mod m q) 

この質問を選んで新しい言語を学びましたか?回答の6/10はあなた次第です:P
Mego

@Megoチャットでこれについて言及しました:DIはとにかくそれを投稿するかどうか尋ね、彼らは先に行くと言いました。また、はい。私の友人は、これが私の「Hello、World!」だと言っています。新しい言語の場合:D
Sherlock9

これが悪いことだと言っているのではない。私はただ面白がっています、それがすべてです。
メゴ

@ Sherlock9:untilPythonバージョンの第2アルゴリズムの(多かれ少なかれ)直接変換に使用できます(n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q)
nimi

@nimi:DIが長年foldl、無限のリストやあらゆる種類の問題についてその問題に頭を打ちました。ご協力いただきありがとうございます!
Sherlock9

1

GameMaker Language(GML)、88バイト

@ user81655の回答に基づく

r=argument0
k=argument1
q=argument2
r=(k-1)mod q;for(i=q;i<n;r=(r+k)mod ++i){}return r+1

1

ゼリー14 13 バイト

Rµṙ⁴ṖµL>⁵µ¿⁴ị

TryItOnline!

どうやって?

Rµṙ⁴ṖµL>⁵µ¿⁴ị - Main link: n, k, q
 µ            - monadic chain separation
R             - range(n): [1,2,3,...,n] - the circle of people
     µ   µ¿   - while
      L       -     length
       >      -     greater than
        ⁵     -     5th program argument (3rd input), i.e. q
  ṙ           -         rotate left by
   ⁴          -         4th program argument (2nd input) i.e. k
    Ṗ         -         pop - remove the rightmost person
            ị - get index
           ⁴  - 4th program argument (2nd input), i.e. k

0

ルビー、53 48バイト

ラムダ。

->n,k,q{r=(k-1)%q;(q+=1;r=(r+k)%q)while q<n;r+1}

使い方

def j(n,k,q)
  r=(k-1)%q   # r starts at j[q,k,q]
  while q<n
    q+=1
    r=(r+k)%q # Every time you add people to the circle, r increases by k, 
              # modulo the current size of the circle q.
  end
  r+1         # Return the result.
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.