ปัญหาของ Josephus กับสามอินพุต


22

มีคำถามในไซต์นี้ที่คล้ายกับคำถามนี้ แต่ฉันได้เพิ่มการบิด

คุณมีสามอินพุตจำนวนคนในแวดวงnคนk -th นับในแต่ละขั้นตอนและบุคคลq -th ที่รอดชีวิต คนที่อยู่ในวงกลมที่มีเลข 1 ถึงn

ตัวอย่างเช่นในแวดวงที่มี 20 คนบุคคลที่ 20 เพื่อความอยู่รอดเป็นบุคคลแรกที่ถูกนำออกผู้รอดชีวิตที่ 19 คือคนที่สองที่ถูกนำออกและอื่น ๆ โดยปกติแล้วปัญหาของ Josephus คือการกำหนดคนสุดท้ายที่ถูกนำออกซึ่งเรียกว่าผู้รอดชีวิตคนแรก

เขียนโปรแกรมหรือฟังก์ชั่นที่สั้นที่สุดซึ่งอินพุตทั้งสามนั้นคืนค่าจำนวนบุคคลq -th เพื่อเอาชีวิตรอด

หากมีปัญหาใด ๆ ที่มีความชัดเจนโปรดแจ้งให้เราทราบ

ตัวอย่างบางส่วน:

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

แก้ไข:สมมติว่าอินพุตทั้งหมดถูกต้อง นั่นคือไม่มีใครจะถาม 0 หรือตัวเลขลบใด ๆ และไม่มีใครจะขอผู้รอดชีวิตคนที่ 20 ในวงกลม 5 คน (นั่นคือ 1 ≤ q ≤ n)

แก้ไข:ฉันจะยอมรับคำตอบตอนเที่ยงคืน UTC + 7 เมื่อเริ่มต้นวันที่ 2 ธันวาคม


1
โปรดโพสต์โซลูชันของคุณเองเป็นคำตอบแทนที่จะรวมไว้ในคำถาม
Doorknob

เข้าใจแล้ว ขออภัยเกี่ยวกับสิ่งนั้น
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 codels

ป้อนคำอธิบายรูปภาพที่นี่

แก้ไข:ฉันตีมันลงไปมากกว่านี้และฉันคิดว่าฉันสามารถตีมันลงไปได้อีก แต่นั่นยังคงมา สำหรับตอนนี้ฉันแค่ดีใจที่มันใช้งานได้และฉันมีที่ว่างที่จะเซ็นชื่อที่มุมล่างซ้ายมือ แนวคิดสองข้อที่ฉันต้องบันทึกเพิ่มเติมคือ a) เพื่อเปลี่ยนคำแนะนำสุดท้ายpop, push 1, add, out num(ป๊อป n, เอาต์พุต r + 1) และ b) เพื่อทำซ้ำอีกครั้งที่มุมล่างซ้ายเพื่อบันทึกโคเดกส์ในการจัดการกองซ้อนในภายหลัง

ภาพด้านบนเป็นรหัสของฉันที่ 8 พิกเซลต่อ codel โดยทั่วไปก็เป็นขั้นตอนวิธีการเช่นเดียวกับคำตอบของงูหลามของฉัน แต่กับปัจจัยในการสั่งซื้อของK , Q , n ในทางปฏิบัติยังมีการจัดการกองซ้อนจำนวนมาก คุณสามารถลองได้ที่นี่โดยเปิดภาพที่นั่นและเรียกใช้รหัสด้วย

คำอธิบาย

นี่เป็นวิธีแก้ปัญหาทีละขั้นตอน

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

@ Sparr ฉันกำลังนับพื้นที่ว่าง นั่นคือ 21 codel โดย 13 codel image ดังนั้นคะแนนคือ 273 codels
Sherlock9

อ่าฉันผิดไป ขอโทษ
Sparr

4

CJam, 22 20 19 ไบต์

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

q k nนี้อ่านอินพุตเป็น ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

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 ไบต์

สมมติว่าสามอินพุตอยู่ในสแต็กแล้วตามลำดับn , k , q

~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:เพิ่ม ~, ตามกฎของ wiki และทำให้รหัสสั้นลง ขอบคุณ @Dennis

แต่ปางก่อน

[\.(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
\;\;\;\;สามารถแทนที่ด้วย])\;(ตัดในอาร์เรย์, ขวา - uncons, สลับและป๊อป)
Doorknob

แก้ไขรหัสของฉันเพื่อความชัดเจน @Dennis
Sherlock9

Alright @Dennis เพิ่ม ~ และแก้ไขคำถามเพื่ออนุญาตเฉพาะโปรแกรมและฟังก์ชั่น คุณมีคำแนะนำอื่น ๆ หรือไม่?
Sherlock9

ไม่ดีทั้งหมด :)
เดนนิส

2

JavaScript (ES6), 56 ไบต์

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

Ungolfed

โดยพื้นฐานแล้วการปรับ JavaScript ของคำตอบ Python ของ@ Sherlock9

(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: P
คดีของกองทุนโมนิกา

1

Mathematica ขนาด 50 ไบต์

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

ฟังก์ชั่นที่ไม่ระบุชื่อ q,n,kนำปัจจัยการผลิตในการสั่งซื้อ


1

C, 81 73 ไบต์

ตามการนำ Javascript ไปใช้ของ@ user81655สำหรับคำตอบ Python ของฉัน

แก้ไข:ลบฉัน

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 ไบต์ ดัดแปลงมาจากอัลกอริทึมบน Wikipedia จะต้องมีการใช้งานโดยตรงของอัลกอริทึมนี้เมื่อ 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 ดูคำตอบของหลามสำหรับอัลกอริทึม

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]

อิงตามอัลกอริทึม Haskell ในหน้ารหัส Rosettaของฟังก์ชั่น Josephus ด้วยสองอินพุต ยินดีให้คำแนะนำการเล่นกอล์ฟ

แก้ไข:ขอบคุณnimiสำหรับความช่วยเหลือในการเล่นกอล์ฟอัลกอริทึมแรกผ่านการแนะนำรุ่นที่ไม่มีจุดหมายและสำหรับความช่วยเหลือเกี่ยวกับการเล่นกอล์ฟอัลกอริทึมที่สองโดยแจ้งให้เราทราบว่ามี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 แม้ว่าขั้นตอนวิธีนี้มีความยาวที่ 62 ไบต์และยังไม่ได้รับการแข็งแรงเล่นกอล์ฟลงมากเป็นครั้งแรกมันจะเร็วขนาดใหญ่และขนาดเล็กnk

Ungolfed:

ขั้นตอนวิธีแรก

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

อัลกอริทึมที่สอง

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 ถามว่าฉันควรโพสต์หรือไม่และพวกเขาบอกว่าไปข้างหน้า นอกจากนี้ใช่ เพื่อนของฉันบอกฉันว่านี่คือ "สวัสดีโลก!" สำหรับภาษาใหม่: D
Sherlock9

ฉันไม่ได้พูดว่านี่เป็นสิ่งที่ไม่ดี ฉันแค่สนุกแค่นั้นแหละ
Mego

@ Sherlock9: คุณสามารถใช้untilสำหรับ (มากหรือน้อย) แปลตรงของรุ่นหลามของขั้นตอนวิธีที่ (n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q)2:
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.