Masalah Josephus dengan tiga input

22

Ada pertanyaan di situs ini yang mirip dengan pertanyaan ini, tetapi saya telah menambahkan twist.

Anda memiliki tiga input, jumlah orang dalam lingkaran n , orang ke- k yang dihitung pada setiap langkah, dan orang ke- q yang bertahan. Orang-orang di lingkaran diberi nomor 1 hingga n .

Sebagai contoh, dalam lingkaran 20 orang, orang ke 20 yang bertahan adalah orang pertama yang dipindahkan, orang yang selamat ke 19 adalah orang kedua yang dipindahkan dan seterusnya. Biasanya, masalah Yosefus adalah menentukan orang terakhir yang dipindahkan, di sini disebut korban pertama .

Tuliskan program atau fungsi terpendek yang, dengan tiga input itu, mengembalikan jumlah orang ke - q untuk bertahan hidup.

Jika ada masalah dengan kejelasan, harap beri tahu saya.

Beberapa contoh:

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

Sunting: Asumsikan semua input valid. Itu tidak ada yang akan meminta 0 atau angka negatif dan tidak ada yang akan meminta 20 orang yang selamat dalam lingkaran 5 orang (yaitu, 1 ≤ q ≤ n)

Sunting: Saya akan menerima jawaban pada tengah malam UTC + 7 pada awal 2 Desember.

Sherlock9
sumber
1
Silakan posting solusi Anda sendiri sebagai jawaban daripada memasukkannya dalam pertanyaan.
Gagang Pintu
Oke. Maaf tentang itu
Sherlock9
1
Untuk klarifikasi, jika q=1ini persis sama dengan pertanyaan Josephus yang terhubung, kan?
AdmBorkBork
@TimmyD Persis
Sherlock9

Jawaban:

5

Pyth, 16 byte

eu.<PGvzh-QvwShQ

Cobalah online: Demonstrasi atau Test Suite

Input berupa formulir k<newline>n<newline>q.

Penjelasan:

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  
Jakube
sumber
7

Piet, 280 273 kode

masukkan deskripsi gambar di sini

Sunting: Saya telah menurunkan ini lagi, dan saya pikir saya bisa menurunkannya lebih jauh, tetapi itu masih akan datang. Untuk saat ini, saya senang kerjanya, dan saya punya ruang untuk menandatanganinya di sudut kiri bawah. Dua ide saya harus menyimpan lebih banyak kode adalah a) untuk mengubah instruksi akhir menjadi pop, push 1, add, out num(pop n, output r +1) dan b) untuk menggandakan lagi di sudut kiri bawah untuk menyimpan kode dalam manipulasi tumpukan nanti di dalam loop.

Gambar di atas adalah kode saya pada 8 piksel per codel. Secara umum, ini adalah algoritma yang sama dengan jawaban Python saya, tetapi dengan input dalam urutan k , q , n . Dalam praktiknya, ada juga banyak manipulasi tumpukan. Anda dapat mencobanya di sini dengan membuka gambar di sana dan menjalankan kodenya.

Penjelasan

Ini adalah ungolfing solusi langkah demi langkah.

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
Sherlock9
sumber
Anda tidak menghitung ruang kosong? Apakah ada meta pos di suatu tempat tentang bagaimana cara mencetak Piet? Mungkin harus ada.
Sparr
@Parr, saya menghitung ruang kosong. Itu adalah 21 codel dengan 13 codel image, jadi nilainya 273 codel.
Sherlock9
Ahh, saya salah hitung. Maaf.
Sparr
4

CJam, 22 20 19 byte

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

Ini membaca input sebagai q k n. Cobalah online di juru bahasa CJam .

Bagaimana itu bekerja

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.
Dennis
sumber
3

Golfscript, 58 56 55 35 31 30 byte

Dengan asumsi ketiga input sudah ada di stack, dalam urutan n , k , q

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

Solusi itu mengasumsikan saya harus menyingkirkan semuanya kecuali jawaban terakhir.

Bagaimana itu bekerja

Lihat j(n,k,q)dalam solusi Python 3 saya untuk lebih detail.

~                                   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

Sunting 1: Digunakan @ saran Doorknob (Menambahkan + untuk mendapatkan semua input ke dalam array)

Dahulu,

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

Sunting 2: Ditambahkan ~, sesuai aturan wiki, dan disingkat kodenya. Terima kasih @Dennis

Dahulu,

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

Sunting 3: Menerapkan algoritma yang lebih pendek.

Dahulu,

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

Sunting 4: Memahami bahwa saya dapat digunakan %sebagai peta.

Dahulu,

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

Sunting 5: Suntingan kecil. Berubah 2$untuk @membuat [0..q-1]dan 3$untuk 2$untuk mengambil k. Menyimpan gigitan

Dahulu,

~1$(1$%3$),2$),-{\3$+\%}%\)])\;
Sherlock9
sumber
1
\;\;\;\;dapat diganti dengan ])\;(wrap in array, right-uncons, swap, dan pop).
Gagang Pintu
Mengedit kode saya untuk kejelasan @ Dennis.
Sherlock9
Baiklah @ Dennis. Menambahkan ~ dan mengedit pertanyaan untuk mengizinkan hanya program dan fungsi. Apakah Anda punya saran lain?
Sherlock9
Tidak, semuanya baik-baik saja. :)
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}

Tidak disatukan

Pada dasarnya sebuah adaptasi JavaScript dari jawaban Python @ Sherlock9 .

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

Uji

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>

pengguna81655
sumber
Saya tidak akan menyebut versi tanpa ungolfed Anda ungolfed: P
Fund Monica's Lawsuit
1

Mathematica, 50 byte

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

Fungsi anonim. Mengambil input dalam urutan q,n,k.

alephalpha
sumber
1

C, 81 73 byte

Didasarkan pada implementasi Javascript @ user81655 dari jawaban Python saya.

Edit: Dihapus i

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

Uji

#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;
}
Sherlock9
sumber
Di beberapa versi C, Anda dapat menjatuhkan intsebelum nama parameter.
Dana Gugatan Monica
1

Python 3, 72 66 62 byte

Fungsi pemrograman dinamis dalam 62 byte. Diadaptasi dari algoritma di Wikipedia. Dulu ada implementasi langsung dari algoritma ini ketika q = 1 (yaitu i = 1, r = 0) pada halaman itu, tetapi saya melihat bahwa telah dihapus sekarang.

Sunting 1: Saya menghapus iuntuk menyimpan 4 byte. Penjelasan tetap tidak berubah.

Sunting 2: Kesalahan perhitungan dalam jumlah byte. Saya menggunakan \r\nuntuk EOL dan tidak memperhatikan ketika itu menambahkan 3 byte. Saya telah menurunkan jumlah byte saya sesuai.

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

Bagaimana ini bekerja?

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.

Terima kasih kepada @Dennis untuk mengingatkan saya bahwa saya harus menjelaskan kode saya (jika hanya secara implisit, karena ia memasukkan satu dalam jawabannya). Jika ada sesuatu yang tidak jelas, tolong beritahu saya.

Edit:

Dahulu,

Fungsi berulang yang diadaptasi dari Matematika Beton oleh Graham, Knuth dan Patashnik. Meskipun algoritma ini lebih panjang, lebih cepat untuk n besar dan k kecil .

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
Sherlock9
sumber
1
Sepertinya Anda memotong sesuatu dalam menyalin-menempel, ada yang menggantung +.
xnor
1

PHP, 71 byte

Didasarkan atas jawaban @ Sherlock9. Lihat jawaban Python-nya untuk algoritme.

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

Atau, inilah pendekatan naif asli saya tanpa algoritma. Ini menggunakan array untuk menandai orang mana yang ditemukan.

91 byte

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

Haskell, 48 47 43 byte

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

Berdasarkan algoritma Haskell pada halaman Kode Rosetta dari fungsi Josephus dengan dua input. Saran bermain golf dipersilakan.

Sunting: Terima kasih kepada nimi untuk bantuan golf algoritma pertama melalui menyarankan versi pointfree, dan untuk bantuan golf golf algoritma kedua dengan memberi tahu saya bahwa untilkata kunci itu ada.

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

Versi algoritma di akhir jawaban Python saya diadaptasi dari Matematika Beton oleh Graham, Knuth dan Patashnik. Meskipun algoritma ini lebih panjang pada 62 byte, dan belum diturunkan sebanyak yang pertama, itu lebih cepat untuk besar ndan kecil k.

Tidak Disatukan:

Algoritma pertama

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

Algoritma kedua

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) 
Sherlock9
sumber
Jadi, apakah Anda memilih pertanyaan ini untuk belajar bahasa baru? 6/10 dari jawaban ada di tangan Anda: P
Mego
@Mego Saya menyebutkan ini dalam obrolan: DI bertanya apakah saya harus mempostingnya dan mereka berkata silakan. Juga ya. Teman-teman saya memberi tahu saya bahwa ini adalah "Halo, Dunia!" untuk bahasa baru: D
Sherlock9
Saya tidak mengatakan ini adalah hal yang buruk. Aku hanya geli, itu saja.
Mego
@ Sherlock9: Anda dapat menggunakan untiluntuk terjemahan (kurang lebih) langsung dari versi Python-2 algoritma: (n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q).
nimi
Tuhan memberkatimu, @nimi: DI aku membenturkan kepalaku pada masalah itu selama bertahun-tahun, mencoba foldldan daftar yang tak terbatas dan segala macam hal. Terima kasih atas bantuan Anda!
Sherlock9
1

Bahasa GameMaker (GML), 88 byte

Berdasarkan jawaban @ 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
Timtech
sumber
1

Jelly , 14 13 byte

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

TryItOnline!

Bagaimana?

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
Jonathan Allan
sumber
0

Ruby, 53 48 byte

Lambda

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

Bagaimana itu bekerja

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
Sherlock9
sumber