Üç girdili Josephus problemi


22

Bu sitede , bu soruya benzer bir soru var, ancak bir twist ekledim.

Sen üç girişe sahiptir, çevrede bulunan kişi sayısı n , k -inci kişi her adımda dışarı sayılır ve q -inci kişi yaşayıp yaşamayacağını söyledi. Çemberdeki insanlar 1 ile n arasında numaralandırılmıştır .

Örneğin, 20 kişiden oluşan bir dairede, hayatta kalan 20. kişi, ilk çıkarılan kişi, 19. kişi ise ikinci çıkarılan kişi vb. Normal olarak, Josephus sorunu , burada ilk kurtulan olarak adlandırılan en son çıkan kişiyi belirlemektir .

Bu üç girişli, sayısını verir, kısa programı veya fonksiyon Yazın q, hayatta kalmak için inci kişi.

Netlikle ilgili herhangi bir sorun varsa, lütfen bana bildirin.

Bazı örnekler:

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

Düzenleme: Tüm girişlerin geçerli olduğunu varsayalım. Bu, hiç kimse 0 veya herhangi bir negatif sayı talep etmeyecek ve hiç kimse, 20 kişinin hayatta kalanını 5 kişilik bir çevrede istemeyecek (yani, ≤ q ≤ n)

Düzenleme: 2 Aralık başında UTC + 7 gece yarısı bir cevap kabul edeceğim.


1
Lütfen kendi çözümlerinizi soruya dahil etmek yerine cevaplar olarak gönderin.
Doorknob

Anladım. Bunun için üzgünüm
Sherlock9

1
Açıklama için, eğer q=1bu bağlantılı Josephus sorusuyla tamamen aynıysa, değil mi?
AdmBorkBork

Tam olarak @TimmyD
Sherlock9

Yanıtlar:


5

Pyth, 16 bayt

eu.<PGvzh-QvwShQ

Çevrimiçi deneyin: Gösteri veya Test Paketi

Giriş formundadır k<newline>n<newline>q.

Açıklama:

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 kod çözücü

enter image description here

Düzenleme: Bunu biraz daha aşağıya düşürdüm ve sanırım daha da aşağıya golf oynayabiliyorum, ama bu hala gelmek üzere. Şimdilik, işe yaradığı ve sol alt köşede imzalayacak yerim olmasına sevindim. Daha fazla kodlayıcı kaydetmem gereken iki fikir: a) son talimatları değiştirmek için pop, push 1, add, out num(pop n, çıkış r + 1) ve b) kodları daha sonraki döngüde yığın manipülasyonunda kaydetmek için sol alt köşede tekrar kopyalamak.

Yukarıdaki resim kodumda 8 piksel başına bir sayıdır. Genel olarak, Python cevabım ile aynı algoritma, ancak girişleri k , q , n . Uygulamada, büyük miktarda yığın manipülasyonu da var. Sen edebilirsiniz burada deneyin orada açılış resmi ve onunla kod çalıştırarak.

açıklama

Bu, çözümün adım adım çözülmesidir.

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

Boş alanı saymıyor musun? Piet'in nasıl skorlanabileceği konusunda bir meta yazı var mı? Muhtemelen olmalı.
Sparr

@ Papr, ben boş alanı sayıyorum. Bu 13 codel imge tarafından 21 codel, yani skor 273 codels.
Sherlock9

Ahh, yanlış saydım. Üzgünüm.
Sparr

4

CJam, 22 20 19 bayt

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

Bu girdiyi okur q k n. Çevrimiçi deneyinCJam tercümanında .

Nasıl çalışır

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 Betiği, 58 56 55 35 31 30 bayt

Üç girişin zaten yığında, n , k sıralarında olduğunu varsayarsak , q

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

Bu çözüm, son cevaptan başka her şeyden kurtulmam gerektiğini varsayar.

Nasıl çalışır

Daha j(n,k,q)fazla ayrıntı için Python 3 çözümüme bakın .

~                                   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

Düzenleme 1: @ Doorknob'un önerisini kullandı (tüm girdileri diziye almak için bir + eklendi)

eskiden

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

Düzenleme 2: Viki'nin kurallarına göre ~ eklendi ve kodu kısaltın. Teşekkürler @Dennis

eskiden

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

Düzenleme 3: Daha kısa bir algoritma uygulandı.

eskiden

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

4'ü Düzenle: Kullanabileceğimi düşündüm% Harita olarak .

eskiden

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

Düzenleme 5: Küçük düzenleme. Değişti 2$için @marka için [0..q-1]ve 3$hiç2$ almak için k. Bir ısırık kaydedildi

eskiden

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

1
\;\;\;\;ile değiştirilebilir ])\;(dizi sar, sağ uncons, takas ve pop).
Doorknob

Netlik @Dennis kodumu düzenledi.
Sherlock9

Tamam, @Dennis. ~ Eklenmiş ve yalnızca programlara ve işlevlere izin vermek için bir soru düzenlenmiştir. Başka bir önerin var mı?
Sherlock9

Hayır, hepsi iyi. :)
Dennis

2

JavaScript (ES6), 56 bayt

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

Ungolfed

Temelde @ Sherlock9'un Python cevabının JavaScript uyarlaması .

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

Ölçek

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>


Senin ungolfed versiyonunu ungolfed diye çağırmazdım: P
Fon Monica'nın Davası

1

Mathematica, 50 bayt

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

Anonim bir işlev. Sırayla girişleri alır q,n,k.


1

C, 81 73 bayt

Kapalı Tabanlı @ user81655 benim Python cevap 'ın JavaScript uygulanması.

Düzenleme: Kaldırıldı i

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

Ölçek

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

Bazı C sürümlerinde int, parametre adlarının önüne düşebilirsiniz .
Fon Monica'nın Davası

1

Python 3, 72 66 62 bayt

62 baytlık dinamik bir programlama fonksiyonu. Vikipedi algoritmasından uyarlanmıştır . O sayfada q = 1 (yani i = 1, r = 0) olduğunda bu algoritmanın doğrudan bir uygulaması vardı, ancak bunun şimdi kaldırıldığını görüyorum.

Düzenleme 1:i 4 bayt kaydetmek için kaldırıldım . Açıklama değişmeden kalır.

Düzenleme 2: Bayt sayısında yanlış hesaplama. \r\nEOL için kullanıyordum ve bu 3 bayt eklediğinde fark etmedim. Bayt sayımı buna göre düşürdüm.

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

Bu nasıl çalışır

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 'e kodumu açıklamam gerektiğini hatırlattığım için teşekkür ederim (ancak dolaylı olarak, cevabına bir tane koyduğu için). Anlaşılmayan bir şey varsa lütfen bana haber verin.

Düzenle:

eskiden

Beton Matematiğinden Graham, Knuth ve Patashnik tarafından uyarlanan yinelemeli bir işlev . Bu algoritma daha uzun olsa da, büyük n ve küçük k için daha hızlıdır .

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
Kopyalama-yapıştırmada bir şeyi kesmiş gibisin, bir asma var +.
xnor

1

PHP, 71 bayt

@ Sherlock9'un cevaplarından alınmıştır. Algoritma için Python cevabına bakınız.

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

Alternatif olarak, işte algoritma olmadan özgün naif yaklaşımım. Bu, hangi kişilerin bulunduğunu işaretlemek için bir dizi kullanır.

91 bayt

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 bayt

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

Josephus fonksiyonunun Rosetta Kodu sayfasındaki bir Haskell algoritmasına dayanarak iki girişli. Golf önerileri açıktır.

Düzenleme: Nimi'ye , ilk algoritmayı puansız bir sürüm önererek golfle ilgili yardımlar için ve ikinci algoritmayı golf için untilanahtar kelimenin var olduğunu bildirerek yardım için teşekkür ederim .

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

Python cevabımın sonunda algoritmanın bir versiyonu, Beton Matematik'ten Graham, Knuth ve Patashnik tarafından uyarlandı. Bu algoritma 62 byte'ta daha uzun olsa da ve birincisi kadar golf oynamamasına rağmen, büyük nve küçükler için daha hızlıdır k.

Ungolfed:

İlk algoritma

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

İkinci algoritma

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) 

Peki bu soruyu yeni diller öğrenmek için mi seçtin? Cevapların 6 /
10'u

@Mego Bu sohbette bahsettim: DI yine de göndermem gerekip gerekmediğini sordular ve devam etsin dediler. Ayrıca, evet. Arkadaşlarım bana bunun "Merhaba, Dünya!" Olduğunu söylediler. yeni diller için: D
Sherlock9

Bunun kötü bir şey olduğunu söylemiyorum. Sadece eğlendim, hepsi bu.
Mego

Sherlock9 @: kullanabileceğiniz until2 algoritmanın Python sürümünün bir (daha fazla veya daha az) doğrudan çeviri için: (n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q).
nimi

Tanrı sizi korusun, nimi: DI başımdan beri bu soruna kafa yoruyor, deniyor foldlve sonsuz listelerde ve her türlü şeyde . Yardımın için teşekkürler!
Sherlock9

1

GameMaker Dili (GML), 88 bayt

@ User81655 kullanıcısının yanıtına göre

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

Jöle , 14 13 bayt

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

TryItOnline!

Nasıl?

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 bayt

Bir lambda.

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

Nasıl çalışır

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.