Vấn đề Josephus với ba đầu vào


22

Có một câu hỏi trên trang web này tương tự như câu hỏi này, nhưng tôi đã thêm một nút thắt.

Bạn có ba đầu vào, số người trong vòng tròn n , người thứ k được tính ở mỗi bước và người thứ q sống sót. Những người trong vòng tròn được đánh số từ 1 đến n .

Ví dụ, trong một vòng tròn gồm 20 người, người thứ 20 sống sót là người đầu tiên bị loại bỏ, người sống sót thứ 19 là người thứ hai bị loại bỏ và cứ thế. Thông thường, vấn đề Josephus là xác định người cuối cùng bị loại bỏ, ở đây được gọi là người sống sót đầu tiên .

Viết chương trình hoặc hàm ngắn nhất, với ba đầu vào đó, trả về số người thứ q để tồn tại.

Nếu có bất kỳ vấn đề với sự rõ ràng, xin vui lòng cho tôi biết.

Vài ví dụ:

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

Chỉnh sửa: Giả sử tất cả các đầu vào là hợp lệ. Đó là không ai sẽ yêu cầu 0 hoặc bất kỳ số âm nào và sẽ không ai yêu cầu người sống sót thứ 20 trong một vòng tròn gồm 5 người (nghĩa là 1 ≤ q n)

Chỉnh sửa: Tôi sẽ chấp nhận câu trả lời vào nửa đêm UTC + 7 vào đầu ngày 2 tháng 12.


1
Vui lòng gửi giải pháp của riêng bạn dưới dạng câu trả lời thay vì đưa chúng vào câu hỏi.
Doorknob

Hiểu rồi. Xin lỗi về điều đó
Sherlock9

1
Để làm rõ, nếu q=1điều này hoàn toàn giống với câu hỏi Josephus được liên kết, phải không?
admBorkBork

@TimmyD Chính xác
Sherlock9

Câu trả lời:


5

Bình thường, 16 byte

eu.<PGvzh-QvwShQ

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Đầu vào có dạng k<newline>n<newline>q.

Giải trình:

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 codel

nhập mô tả hình ảnh ở đây

Chỉnh sửa: Tôi đã đánh gôn này thêm một số nữa, và tôi nghĩ rằng tôi có thể đánh gôn xuống hơn nữa, nhưng điều đó vẫn sẽ đến. Hiện tại, tôi chỉ vui mừng vì nó hoạt động và tôi có chỗ để ký tên ở góc dưới bên trái. Hai ý tưởng tôi phải lưu nhiều codel hơn là a) để thay đổi các hướng dẫn kết thúc là pop, push 1, add, out num(pop n, output r + 1) và b) để sao chép lại ở góc dưới bên trái để lưu codel trong thao tác ngăn xếp sau này trong vòng lặp.

Hình trên là mã của tôi ở mức 8 pixel mỗi codel. Nói chung, đó là thuật toán tương tự như câu trả lời Python của tôi, nhưng với các đầu vào theo thứ tự k , q , n . Trong thực tế, cũng có rất nhiều thao tác ngăn xếp. Bạn có thể thử nó ở đây bằng cách mở hình ảnh ở đó và chạy mã với nó.

Giải trình

Đây là một bước vô căn cứ của giải pháp.

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

Bạn không đếm không gian trống? Có một bài viết meta ở đâu đó về làm thế nào để ghi điểm Piet? Có lẽ nên có.
Sparr

@Sparr, tôi đang đếm không gian trống. Đó là một codel 21 bởi 13 codel, vì vậy điểm số là 273 codel.
Sherlock9

Ahh, tôi đã nhầm lẫn. Lấy làm tiếc.
Sparr

4

CJam, 22 20 19 byte

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

Điều này đọc đầu vào là q k n. Hãy thử trực tuyến trong trình thông dịch CJam .

Làm thế nào nó hoạt động

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

Golf, 58 56 55 35 31 30 byte

Giả sử ba đầu vào đã có trong ngăn xếp, theo thứ tự n , k , q

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

Giải pháp đó cho rằng tôi cần phải loại bỏ mọi thứ trừ câu trả lời cuối cùng.

Làm thế nào nó hoạt động

Xem j(n,k,q)trong giải pháp Python 3 của tôi để biết thêm chi tiết.

~                                   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

Chỉnh sửa 1: Đã sử dụng đề xuất của @ Doorknob (Đã thêm dấu + để nhận tất cả các đầu vào vào mảng)

Trước kia,

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

Chỉnh sửa 2: Đã thêm ~, theo các quy tắc của wiki và rút ngắn mã. Cảm ơn @Dennis

Trước kia,

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

Chỉnh sửa 3: Thực hiện một thuật toán ngắn hơn.

Trước kia,

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

Chỉnh sửa 4: Tìm hiểu rằng tôi có thể sử dụng %như bản đồ.

Trước kia,

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

Chỉnh sửa 5: Chỉnh sửa nhỏ. Thay đổi 2$để @làm [0..q-1]3$để 2$lấy k. Cứu một vết cắn

Trước kia,

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

1
\;\;\;\;có thể được thay thế bằng ])\;(bọc trong mảng, vô thức, trao đổi và pop).
Doorknob

Đã chỉnh sửa mã của tôi cho rõ ràng @Dennis.
Sherlock9

Được rồi @Dennis. Đã thêm ~ và chỉnh sửa câu hỏi để chỉ cho phép các chương trình và chức năng. Bạn có bất cứ lời đề nghị khác?
Sherlock9

Không, tất cả đều tốt. :)
Dennis

2

JavaScript (ES6), 56 byte

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

Bị đánh cắp

Về cơ bản là một bản phóng tác JavaScript của câu trả lời Python của @ Sherlock9 .

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

Kiểm tra

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>


Tôi sẽ không gọi phiên bản vô danh của bạn là vô danh: P
Vụ kiện của Quỹ Monica

1

Toán học, 50 byte

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

Một chức năng ẩn danh. Đưa đầu vào theo thứ tự q,n,k.


1

C, 81 73 byte

Dựa trên triển khai Javascript của @ user81655 cho câu trả lời Python của tôi.

Chỉnh sửa: Đã xóa tôi

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

Kiểm tra

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

Trong một số phiên bản của C, bạn có thể bỏ inttrước tên tham số.
Vụ kiện của Quỹ Monica

1

Python 3, 72 66 62 byte

Một hàm lập trình động trong 62 byte. Chuyển thể từ thuật toán trên Wikipedia. Đã từng có một triển khai trực tiếp thuật toán này khi q = 1 (tức là i = 1, r = 0) trên trang đó, nhưng tôi thấy điều đó đã bị xóa ngay bây giờ.

Chỉnh sửa 1: Tôi đã xóa iđể lưu 4 byte. Giải thích vẫn không thay đổi.

Chỉnh sửa 2: Tính toán sai trong số byte. Tôi đã sử dụng \r\ncho EOL và không nhận thấy khi thêm 3 byte. Tôi đã giảm số byte của tôi cho phù hợp.

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

Làm thế nào điều này hoạt động

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.

Cảm ơn @Dennis đã nhắc nhở tôi rằng tôi nên giải thích mã của mình (nếu chỉ ngầm hiểu, vì anh ấy đã bao gồm một trong câu trả lời của mình). Nếu bất cứ điều gì chưa rõ, xin vui lòng cho tôi biết.

Chỉnh sửa:

Trước kia,

Một hàm lặp được điều chỉnh từ Toán học cụ thể của Graham, Knuth và Patashnik. Mặc dù thuật toán này dài hơn, nhưng nó nhanh hơn đối với n lớn và k nhỏ .

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
Có vẻ như bạn cắt một cái gì đó trong sao chép - dán, có một treo +.
xnor

1

PHP, 71 byte

Dựa trên câu trả lời của @ Sherlock9. Xem câu trả lời Python của anh ấy cho thuật toán.

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

Ngoài ra, đây là cách tiếp cận ngây thơ ban đầu của tôi mà không có thuật toán. Điều này sử dụng một mảng để đánh dấu những người được tìm thấy.

91 byte

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 byte

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

Dựa trên thuật toán Haskell trên trang Mã Rosetta của hàm Josephus với hai đầu vào. Đề nghị chơi golf được chào đón.

Chỉnh sửa: Tôi cảm ơn nimi vì đã giúp chơi golf thuật toán đầu tiên thông qua đề xuất một phiên bản miễn phí và giúp đỡ về việc đánh gôn thuật toán thứ hai bằng cách cho tôi biết rằng untiltừ khóa tồn tại.

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

Một phiên bản của thuật toán ở cuối câu trả lời Python của tôi được điều chỉnh từ Concrete Math của Graham, Knuth và Patashnik. Mặc dù thuật toán này dài hơn ở mức 62 byte và chưa được đánh golf nhiều như lần đầu tiên, nhưng nó nhanh hơn cho lớn nvà nhỏ k.

Ung dung:

Thuật toán đầu tiên

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

Thuật toán thứ hai

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) 

Vì vậy, bạn đã chọn câu hỏi này để học ngôn ngữ mới với? 6/10 câu trả lời là của bạn: P
Mego

@Mego Tôi đã đề cập đến vấn đề này trong trò chuyện: DI hỏi tôi có nên đăng nó không và họ nói hãy tiếp tục. Ngoài ra, có. Bạn bè của tôi đã nói với tôi rằng đây là "Xin chào, Thế giới!" cho các ngôn ngữ mới: D
Sherlock9

Tôi không nói rằng đây là một điều xấu. Tôi chỉ thích thú, thế thôi.
Mego

@ Sherlock9: bạn có thể sử dụng untilbản dịch trực tiếp (nhiều hơn hoặc ít hơn) phiên bản Python của thuật toán thứ 2 : (n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q).
nimi

Chúa phù hộ bạn, @nimi: DI đã đập đầu vào vấn đề đó từ lâu, foldldanh sách cố gắng và vô hạn và đủ thứ. Cảm ơn bạn đã giúp đỡ!
Sherlock9

1

Ngôn ngữ GameMaker (GML), 88 byte

Dựa trên câu trả lời của @ 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

Thạch , 14 13 byte

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

Dùng thử trực tuyến!

Làm sao?

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

Ruby, 53 48 byte

Một lambda.

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

Làm thế nào nó hoạt động

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.