요세푸스 문제 (계산)


29

도전

두 개의 양의 정수 nk 를 인수로 사용하고 각 k 번째 사람을 계산 한 후 n에서 남은 마지막 사람의 수를 반환 하는 함수를 작성하십시오 .

이것은 코드 골프 도전이므로 가장 짧은 코드가 승리합니다.

문제

n 명 ( 1 에서 n 까지의 숫자 )은 원 안에 서 있으며 한 사람이 남을 때까지 각 k 번째가 계산됩니다 (해당 위키 백과 기사 참조 ). 이 마지막 사람의 수를 결정하십시오.

예를 들어 k = 3의 경우 두 사람은 건너 뛰고 세 번째 사람은 계산됩니다. 즉, n = 7 인 경우 숫자는 3 6 2 7 5 1 (세부 사항은 1 2 3 4 5 6 7 1 2 4 5 7 1 4 5 1 4 1 4 ) 순서로 계산되므로 답은 4 입니다.

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

답변:


5

GolfScript, 17 바이트

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

n k스택을 가져 와서 결과를 스택에 남겨 둡니다.

해부

이러한 반복 사용 g(n,k) = (g(n-1,k) + k) % n으로 g(1, k) = 0재귀와 (위키피디아 문서에 기술 된 바와 같이)는 스크롤로 대체.

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

설명을 추가해 주시겠습니까?
Sherlock9

@ Sherlock9, 나는 거의 3.5 년이 지났음에도 불구하고 내가하고있는 일을 알아낼 수있었습니다. GolfScript가 읽기 전용이라고 누가 말합니까? ;)
Peter Taylor

아헴. s / read / write /
Peter Taylor

죄송합니다. 저는 2 ~ 3 일 전에 Golfscript를 배우기 시작했으며 코드를 읽을 때마다 무언가를 놓칠 것이라고 생각했습니다. ... 좋아, 난 아직도 어떻게 접는 않는, 뭔가를 누락 {k block}이상 [0..n-1]당신을 얻을 g(0,k) 0 k로 시작? 죄송합니다. 이러한 질문을 잘못된 장소에 게시하는 경우
Sherlock9

@ Sherlock9, fold는 쌍으로 작동하므로 가장 먼저하는 것은 evaluation 0 1 block입니다. 매우 편리합니다 g(1, k) (2-1) block. 따라서 시작 g(1,k) 1하기보다는 시작 g(0,k) 0합니다. 그런 다음 블록을 실행 한 후 배열 ( 2) 에서 다음 항목을 푸시 하고 블록 등을 다시 실행합니다.
Peter Taylor

14

Minsky Register Machine (비 정지 상태 25 개)

기술적으로 함수는 아니지만 함수 자체가없는 컴퓨팅 패러다임에 있습니다 ...

이것은 첫 번째 MRM 해석 과제 의 주요 테스트 사례에서 약간의 변형입니다 . Josephus problem as Minsky register machine

레지스터에 입력 n하고 k; 레지스터 출력 r; r=i=t=0입국시에 있다고 가정합니다 . 처음 두 중지 명령은 오류 사례입니다.


기계를 약간 조정해야한다고 생각합니다. 올바르게 읽으면 출력이 0으로 색인화되지 않습니까?
Howard Howard

나는 다른 방법을 생각했다 : 경우 k=1다음 r=0. 흠, 나는 이것에 대해 다시 생각해야한다 ...
Howard

내가 당신의 다이어그램을 읽을 때, i단순히 계산 2하는 n동안 r결과를 누적하는 레지스터입니다.
Howard

@Howard, 나는 이것을 처음 쓸 때 내가 작성한 의견을 찾았으며 당신이 옳습니다. 으악. 이제 수정되었습니다 (나중에 더 철저하게 테스트 할 것입니다).
피터 테일러

7

파이썬, 36

나는 또한 wikipedia의 공식을 사용했습니다.

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

예 :

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


5

C, 40 자

이것은 위의 위키 백과 기사가 제공하는 공식과 거의 같습니다.

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

다양성을 위해 실제로 시뮬레이션을 실행하는 구현이 있습니다 (99 자).

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
문자를 저장하십시오 : j(n,k){return--n?(j(n,k)+k-1)%-~n+1:1;}.
ugoren

5

dc, 27 바이트

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

Wikipedia 기사의 반복을 사용합니다. 설명:

# 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 자

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

시뮬레이션을 실행합니다.

또는 공식 (31 자)을 사용하십시오.

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

Howard가 J의 Dyadic 동사에 맞게 입력 형식을 약간 조정했다고 생각하지 않기를 바랍니다.

용법:

   7 j 3
4
   123 j 12
21

4

GolfScript, 32 24 바이트

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

사용법 : 두 매개 변수 nk 가 스택에있을 것으로 예상하고 출력 값을 그대로 둡니다.

(반복적 인 접근법과 다른 많은 팁을 제안 해 주신 Peter Taylor에게 감사드립니다)

32 문자의 오래된 (재귀 적) 접근 방식 :

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

이것이 나의 첫 GolfScript이므로 귀하의 비판을 알려주십시오.


1
1-특별한 opcode가 (있습니다. 마찬가지로 1+입니다 ). 저장을 위해 알파벳 문자를 사용할 필요가 없으므로 ^대신에 J공백을 사용할 필요없이 대신 사용할 수 있습니다 . 당신은 $잘 골프 프로그램에서 평소보다 훨씬 더 있습니다 :의 조합을 사용하여 줄일 수 있는지 고려하십시오 \@..
피터 테일러

@PeterTaylor이 훌륭한 팁에 감사드립니다! 모든 Golfscript 운영자를 파악하는 것은 매우 어렵고이 두 가지를 매우 간단하게 간과했습니다. 처음 두 가지 제안 만 적용하면 코드를 5 자로 줄일 수 있습니다. 또한 $참조 를 제거하려고합니다 .
Cristian Lupascu 8:21에

1
또한 재귀는 실제로 GolfScript의 것이 아닙니다. 둥글게 돌리고 반복하십시오. 그런 식으로 19 문자 (테스트되지 않은 코드 임)로 줄일 수 있습니다. 힌트 : 함수 풀다 g위키 피 디아 기사에서, 사용 ,하고 /.
피터 테일러

1
{,{\2$+\)%}*)\;}:f; 작동 하는지 이해하십시오 .)
Peter Taylor

1
하나의 마지막 트릭 : k루프 내부 에 액세스하기 위해 2 문자를 사용하고 마지막에 2 문자를 사용하여 폐기하는 대신 +17 문자까지 사용하여 내부를 끌어 올 {{@+\)%}+\,*)}:f;수 있습니다.
피터 테일러



2

하스켈, 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

실제 시뮬레이션을 수행합니다. 데모:

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



1

C, 88 자

시뮬레이션을 수행하고 수식을 계산하지 않습니다.
공식보다 훨씬 길지만 다른 C 시뮬레이션보다 짧습니다.

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

주 :
1. 메모리를 할당하고 해제하지 마십시오.
2.를 사용하기 때문에 n*8대신에 할당 n*4합니다 p[n]. 할당 할 수 (n+1)*4는 있지만 더 많은 문자입니다.


1

C ++, 166 바이트

골프 :

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

언 골프 드 :

#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삼항 연산자를 사용하여 함수의 바이트를 절약 할 수 있습니다.
Yytsi 2016 년

intn당신의 골프 버전에서 컴파일되지 않습니다
Felipe Nardi Batista

스페이스를 제거 할 수 있습니다#include <list>
Felipe Nardi Batista

1

J, 8 바이트

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
두 개의 입력을 받아야합니까?
Outgolfer Erik


1

Q, 34 바이트

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

용법:

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



0

JavaScript (ECMAScript 5), 48 바이트

ECMAScript 5를 사용한 이유는이 질문이있을 당시 최신 버전의 JavaScript였습니다.

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

ES6 버전 (비경쟁), 33 바이트

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

설명

말할 것도 많지 않습니다. Wikipedia 기사에서 제공하는 기능을 구현하고 있습니다.



0

8 번째 , 82 바이트

암호

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

SED (스택 효과 다이어그램)는 다음과 같습니다.n k -- m

사용법과 설명

이 알고리즘은 다음과 같은 정수 배열을 사용합니다. people 값이 5이면 배열은 [1,2,3,4,5]입니다.

: 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 바이트

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

온라인으로 사용해보십시오!

동적 프로그래밍 솔루션을 기반으로하는 반복적 인 접근 방식입니다.

설명

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 바이트

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

온라인으로 사용해보십시오!

작동 원리

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 바이트

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

온라인으로 사용해보십시오!

0 인덱싱 k로 바이트를 저장할 수 있습니다. 있지만 실제로는 인덱스가 아니므로 이에 대해 결정했습니다.

설명:

         [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

파워 쉘, 56 바이트

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

중대한! 스크립트는 재귀 적으로 호출됩니다. 스크립트를f.ps1 현재 디렉토리에 파일 . 또한 스크립트 파일 대신 스크립트 블록 변수를 호출 할 수 있습니다 (아래 테스트 스크립트 참조). 통화 길이는 같습니다.

테스트 스크립트 :

$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"
}

산출:

True: 7
True: 7
True: 4
True: 1
True: 1
True: 21
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.