Josephus problemi (sayma)


29

Meydan okuma

İki pozitif tamsayılar alan bir fonksiyon yazın n ve k bağımsız değişkenleri olarak ve dışarı kalan son kişi sayısını döndürür n her dışarı sayma sonra k -inci kişi.

Bu bir kod golf mücadelesidir, bu yüzden en kısa kod kazanır.

Sorun

N (numaralandırılmış insan 1 için n ) bir daire içinde duran ve her k, tek bir kişi kadar dışarı sayılır inci (Aranılan kaldığını Ara makale ). Bu son kişinin sayısını belirleyin.

Örneğin, k = 3 için iki kişi atlanacak ve üçüncüsü sayılacaktır. İçin Yani , n = 7 numaraları (ayrıntılı olarak sırayla 3 6 2 7 5 1'de sayılır 2 1 3 5 4 6 7 1 2 4 5 7 1 ila 4 5 1 4 1 4 ) ve bu nedenle cevap 4 .

Örnekler

J(7,1) = 7      // people are counted out in order 1 2 3 4 5 6 [7]
J(7,2) = 7      // people are counted out in order 2 4 6 1 5 3 [7]
J(7,3) = 4      // see above
J(7,11) = 1
J(77,8) = 1
J(123,12) = 21

Yanıtlar:


5

GolfScript, 17 bayt

{{@+\)%}+\,*)}:f;

Alır n kyığın ve yığın sonucu bırakır.

teşrih

Bu kullanımlar tekrarlama g(n,k) = (g(n-1,k) + k) % nile g(1, k) = 0yineleme ile (Ara makalesinde tarif edildiği gibi) bir kat ile yer değiştirir.

{          # Function declaration
           # Stack: n k
  {        # Stack: g(i-1,k) i-1 k
    @+\)%  # Stack: g(i,k)
  }+       # Add, giving stack: n {k block}
  \,*      # Fold {k block} over [0 1 ... n-1]
  )        # Increment to move from 0-based to 1-based indexing
}:f;

Bir açıklama ekler misiniz lütfen?
Sherlock9

@ Sherlock9, neredeyse 3,5 yıl geçmiş olmasına rağmen ne yaptığımı bulmayı başardım. GolfScript'in salt okunur olduğunu kim söylüyor? ;)
Peter Taylor

Ahem. s / read / write /
Peter Taylor

Üzgünüm. Golfscript'i sadece iki ya da üç gün önce öğrenmeye başladım ve kodunuzu her okuduğumda bir şeyleri özleyeceğimi düşündüm. ... Tamam, ben hala nasıl katlanır gelmez, bir şey eksik {k block}üzerinde [0..n-1]almak g(0,k) 0 kbaşlamak? Üzgünüm, bu soruları yanlış yere gönderiyorsam.
Sherlock9

@ Sherlock9, katlama ikili çalışır, bu yüzden yaptığı ilk şey değerlendirmektir 0 1 block. Çok uygun, bu olur g(1, k) (2-1) block. Bu yüzden de başlıyor g(1,k) 1ziyade g(0,k) 0. Sonra bloğu yürüttükten sonra, bir sonraki öğeyi diziden ( 2) iter ve bloğu tekrar yürütür, vs.
Peter Taylor

14

Minsky Kayıt Makinesi (25 duraksız devlet)

Teknik olarak bir işlev değil, ancak kendi başına işlevi olmayan bir hesaplama paradigmasında var ...

Bu benim ilk MRM yorumlama zorluğumun ana test durumundaki küçük bir değişiklik. : Josephus problem as Minsky register machine

Kayıtlardaki girdiler nve k; sicilde çıktı r; r=i=t=0girişte olduğu varsayılmaktadır . İlk iki durma talimatı hata durumlarıdır.


Bence makineni biraz ayarlamalısın. Doğru okuduysanız, çıktı sıfır dizinli değil mi?
Howard

Diğer yolu düşünüyordum: eğer k=1öyleyse r=0. Hmm, bunu tekrar düşünmek zorundayım ...
Howard,

Ben senin diyagramı okurken, isadece saymaya olduğu 2için nise rsonuç biriken kayıt olduğunu.
Howard

@Howard, bunu ilk yazdığımda yaptığım yorumlara baktım ve haklısın. Whoops. Şimdi düzeltildi (inanıyorum - daha sonra daha ayrıntılı olarak test edecek).
Peter Taylor

7

Python, 36

Ayrıca wikipedia'dan gelen formülü de kullandım:

J=lambda n,k:n<2or(J(n-1,k)+k-1)%n+1

Örnekler:

>>> J(7,3)
4
>>> J(77,8)
1
>>> J(123,12)
21

6

Mathematica, 38 36 bayt

Aynı Vikipedi formül:

1~f~_=1
n_~f~k_:=Mod[f[n-1,k]+k,n,1]

1
If[#<2,1,Mod[#0[#-1,#2]+#2,#,1]]&
alephalpha

5

C, 40 karakter

Bu hemen hemen sadece bağlantılı wikipedia makalesinin verdiği formüldür:

j(n,k){return n>1?(j(n-1,k)+k-1)%n+1:1;}

Çeşitlilik için, işte aslında simülasyonu çalıştıran bir uygulama (99 karakter):

j(n,k,c,i,r){char o[999];memset(o,1,n);for(c=k,i=0;r;++i)(c-=o[i%=n])||(o[i]=!r--,c=k);
return i;}

4
Bir karakteri Kaydet: j(n,k){return--n?(j(n,k)+k-1)%-~n+1:1;}.
06'da

5

dc, 27 bayt

[d1-d1<glk+r%1+]dsg?1-skrxp

Vikipedi makalesinde tekrarı kullanır. Açıklama:

# comment shows what is on the stack and any other effect the instructions have
[   # n
d   # n, n
1-  # n-1, n
d   # n-1, n-1, n
1<g # g(n-1), n ; g is executed only if n > 1, conveniently g(1) = 1
lk+ # g(n-1)+(k-1), n; remember, k register holds k-1
r%  # g(n-1)+(k-1) mod n
1+  # (g(n-1)+(k-1) mod n)+1
]
dsg # code for g; code also stored in g
?   # read user input => k, n, code for g
1-  # k-1, n, code for g
sk  # n, code for g; k-1 stored in register k
r   # code for g, n
x   # g(n)
p   # prints g(n)

4

J, 45 karakter

j=.[:{.@{:]([:}.]|.~<:@[|~#@])^:(<:@#)>:@i.@[

Simülasyonu çalıştırır.

Alternatif olarak, formülü kullanarak (31 karakter):

j=.1:`(1+[|1-~]+<:@[$:])@.(1<[)

Umarım Howard, giriş biçimini J'deki ikili bir fiile uyacak şekilde biraz ayarladığımı umursamıyor.

Kullanımı:

   7 j 3
4
   123 j 12
21

4

GolfScript, 32 24 bayt

:k;0:^;(,{))^k+\%:^;}/^)

Kullanım: n ve k'nin iki parametresini bekler yığında olmasını ve çıkış değerini bırakır.

(yinelemeli bir yaklaşım ve diğer birçok ipucu önerdiği için Peter Taylor'a teşekkürler)

32 karakterin eski (özyinelemeli) yaklaşımı:

{1$1>{1$(1$^1$(+2$%)}1if@@;;}:^;

Bu benim ilk GolfScript, bu yüzden lütfen eleştirilerini bana bildir.


1
1-özel bir opcode var (. Benzer şekilde 1+olduğunu ). Depolama için alfabetik karakterler kullanmak zorunda değilsiniz, bu nedenle örneğin ^yerine Jbir boşluk kullanmaya gerek kalmadan kullanabilirsiniz . İyi $golf programında normalden çok daha fazlası var : bir kombinasyonunu kullanarak bunları azaltabileceğinizi düşünün \@..
Peter Taylor

@PeterTaylor Bu harika ipucu için çok teşekkürler! Tüm Golfscript operatörlerini kavramak oldukça zor ve bu ikisini çok basit bir şekilde görmezden geldim. Sadece ilk iki öneriyi uygulayarak kodu 5 karakter kısaltmayı başardım. Ayrıca $referansları kaldırmaya çalışacağım .
Cristian Lupascu

1
Ayrıca, özyineleme gerçekten GolfScript'in meselesi değil. Döndürmeyi ve bir döngü yapmayı deneyin. Bu şekilde 19 karaktere (denenmemiş kod da olsa) alabilirim. İpucu: işlevi göz önüne sermek gVikipedi makalesinden ve kullanım ,ve /.
Peter Taylor

1
{,{\2$+\)%}*)\;}:f;Neden işe yaradığını anladığınızdan emin olun ;)
Peter Taylor

1
Son bir püf noktası: kdöngünün içine erişmek için 2 karakter kullanmak ve sonra sonunda atmak için 2 karakter kullanmak yerine +, 17 karaktere kadar inmek için onu kullanarak çekebiliriz : {{@+\)%}+\,*)}:f;Geliştirilebileceğinden şüpheliyim.
Peter Taylor



2

Haskell, 68

j n=q$cycle[0..n]
q l@(i:h:_)k|h/=i=q(drop(k-1)$filter(/=i)l)k|1>0=i

Gerçek simülasyon yapar. gösteri:

GHCi> j 7 1
7
GHCi> j 7 2
7
GHCi> j 7 3
4
GHCi> j 7 11
1
GHCi> j 77 8
1
GHCi> j 123 12
21



1

C, 88 karakter

Simülasyon yapar, formülü hesaplamaz.
Formülden çok daha uzun, ancak diğer C simülasyonundan daha kısa.

j(n,k){
    int i=0,c=k,r=n,*p=calloc(n,8);
    for(;p[i=i%n+1]||--c?1:--r?p[i]=c=k:0;);
    return i;
}

Notlar:
1. Belleği ayırır ve asla serbest bırakmaz.
2. n*8Bunun yerine tahsis n*4ederim, çünkü kullanıyorum p[n]. Tahsis edebilir (n+1)*4, ancak daha fazla karakter var.


1

C ++, 166 bayt

golfed:

#include<iostream>
#include <list>
int j(int n,int k){if(n>1){return(j(n-1,k)+k-1)%n+1;}else{return 1;}}
int main(){intn,k;std::cin>>n>>k;std::cout<<j(n,k);return 0;}

Ungolfed:

#include<iostream>
#include <list>
int j(int n,int k){
    if (n > 1){
        return (j(n-1,k)+k-1)%n+1;
    } else {
        return 1;
    }
}
int main()
{
    int n, k;
    std::cin>>n>>k;
    std::cout<<j(n,k);
    return 0;
}

2
JÜçlü işlecini kullanarak işlevdeki baytları kaydedebilirsiniz .
Yytsi

intngolf versiyonunuzda derlenmeyecek
Felipe Nardi Batista

boşlukları kaldırabilirsiniz#include <list>
Felipe Nardi Batista

1

J, 8 bayt

1&|.&.#:

       1&|.&.#: 10
    5

       1&|.&.#: 69
    11

        1&|.&.#: 123456
    115841

        1&|.&.#: 123245678901234567890x NB. x keeps input integral
    98917405212792722853

All credit to Roger Hui, co-inventor of J and all-round uber-genius
www.jsoftware.com for free j software across many platforms

Explanation
    (J works right-to-left)
     #:       convert input to binary
     &.       a&.b <=> perform b, perform a, perform reverse of b
     1&|.     rotate bitwise one bit left

So
    1&|.&.#: 10

    a. #:            convert input (10) TO binary -> 1 0 1 0
    b. 1&|.          rotate result 1 bit left -> 0 1 0 1
    c. due to the &. perform convert FROM binary -> 5 (answer)

1
İki giriş alması gerekmiyor mu?
Outgolfer Erik


1

Q, 34 bayt

f:{$[x=1;1;1+mod[;x]f[x-1;y]+y-1]}

Kullanımı:

q)f .'(7 1;7 2;7 3;7 11;77 8;123 12)
7 7 4 1 1 21


0

Haskell, 29

Wikipedia'dan gelen formülü kullanarak.

1#_=1
n#k=mod((n-1)#k+k-1)n+1

0

JavaScript (ECMAScript 5), 48 bayt

Bu soruyu sorduğunda JavaScript'in en son sürümüydü, çünkü ECMAScript 5 kullanarak.

function f(a,b){return a<2?1:(f(a-1,b)+b-1)%a+1}

ES6 sürümü (rekabet etmeyen), 33 bayt

f=(a,b)=>a<2?1:(f(a-1,b)+b-1)%a+1

açıklama

Burada söylenecek fazla bir şey yok. Sadece Wikipedia makalesinin bana verdiği fonksiyonu uyguluyorum.


0

05AB1E , 11 bayt

L[Dg#²<FÀ}¦

Çevrimiçi deneyin!

L           # Range 1 .. n
 [Dg#       # Until the array has a length of 1:
     ²<F }  #   k - 1 times do:
        À   #     Rotate the array
          ¦ #   remove the first element

0

8 , 82 bayt

kod

: j >r >r a:new ( a:push ) 1 r> loop ( r@ n:+ swap n:mod ) 0 a:reduce n:1+ rdrop ;

SED (Yığın Etkisi Şeması):n k -- m

Kullanım ve açıklama

Algoritma, bunun gibi bir tamsayı dizisi kullanır: eğer insanlar değeri 5 ise, dizi [1,2,3,4,5] olacaktır.

: j \ n k -- m
    >r                               \ save k
    >r a:new ( a:push ) 1 r> loop    \ make array[1:n]
    ( r@ n:+ swap n:mod ) 0 a:reduce \ translation of recursive formula with folding using an array with values ranging from 1 to n
    n:1+                             \ increment to move from 0-based to 1-based indexing
    rdrop                            \ clean r-stack
;

ok> 7 1 j . cr
7
ok> 7 2 j . cr
7
ok> 7 3 j . cr
4
ok> 7 11 j . cr
1
ok> 77 8 j . cr
1
ok> 123 12 j . cr
21

0

J , 24 bayt

1+1{1([:|/\+)/@,.1|.!.0#

Çevrimiçi deneyin!

Dinamik programlama çözümüne dayalı yinelemeli bir yaklaşım.

açıklama

1+1{1([:|/\+)/@,.1|.!.0#  Input: n (LHS), k (RHS)
                       #  Make n copies of k
                 1|.!.0   Shift left by 1 and fill with zero
    1          ,.         Interleave with 1
             /@           Reduce using
           +                Addition
        |/\                 Cumulative reduce using modulo
  1{                      Select value at index 1
1+                        Add 1

0

J , 19 bayt

1+(}:@|.^:({:@])i.)

Çevrimiçi deneyin!

Nasıl çalışır

1+(}:@|.^:({:@])i.)   Left: k, Right: n
                i.    Generate [0..n-1]
        ^:            Repeat:
   }:@|.                Rotate left k items, and remove the last item
          ({:@])        n-1 (tail of [0..n-1]) times
1+                    Add one to make the result one-based


0

Japt , 15 bayt

_é1-V Å}h[Uõ] Ì

Çevrimiçi deneyin!

0 baytlama k ile bir bayt kaydedilebilir , ama aslında bir indeks değil bu yüzden buna karşı karar verdim.

Açıklama:

         [Uõ]      :Starting with the array [1...n]
_      }h          :Repeat n-1 times:
 é1-V              : Rotate the array right 1-k times (i.e. rotate left k-1 times)
      Å            : Remove the new first element
              Ì    :Get the last value remaining


0

Powershell, 56 bayt

param($n,$k)if($n-lt2){1}else{((.\f($n-1)$k)+$k-1)%$n+1}

Önemli! Senaryo kendisini tekrar tekrar çağırır. Yani betiği farklı kaydetf.ps1 dosyasını geçerli dizine dosya . Ayrıca komut dosyası yerine komut dosyası blok değişkeni de çağırabilirsiniz (aşağıdaki test komut dosyasına bakın). Bu çağrıların uzunluğu aynı.

Test komut dosyası:

$f = {

param($n,$k)if($n-lt2){1}else{((&$f($n-1)$k)+$k-1)%$n+1}

}

@(
    ,(7, 1, 7)
    ,(7, 2, 7)
    ,(7, 3, 4)
    ,(7, 11, 1)
    ,(77, 8, 1)
    ,(123,12, 21)
) | % {
    $n,$k,$expected = $_
    $result = &$f $n $k
    "$($result-eq$expected): $result"
}

Çıktı:

True: 7
True: 7
True: 4
True: 1
True: 1
True: 21
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.