具有三个输入的约瑟夫斯问题


22

这个站点上有一个与此问题类似的问题,但是我添加了一个错误。

你有三个输入,人在圆圈中的数字ñ,该ķ个人在每一步算出来,和q个人能承受住。圈子中的人编号为1到n

例如,在一个由20个人组成的圈子中,要生存的第20个人是被移除的第一个人,第19个幸存者是被移除的第二个人,依此类推。通常,约瑟夫斯问题是确定最后一个被移走的人,这里称为第一个幸存者。

用这三个输入编写最短的程序或函数,该程序或函数返回第q个要生存的人的数量。

如果有任何明确的问题,请告诉我。

一些例子:

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

编辑:假设所有输入均有效。那就是没有人会要求0或任何负数,也没有人会要求在5个人(即1≤q≤n)的圈子中排名第20的幸存者

编辑:我将在12月2日午夜UTC + 7接受答案。


1
请发布您自己的解决方案作为答案,而不是将其包含在问题中。
门把手

得到它了。抱歉
Sherlock9

1
为了澄清,q=1这是否与链接的约瑟夫斯问题完全相同,对吗?
AdmBorkBork 2015年

@TimmyD确实是
Sherlock9

Answers:


5

Pyth,16个字节

eu.<PGvzh-QvwShQ

在线尝试:演示测试套件

输入为形式k<newline>n<newline>q

说明:

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个编码

在此处输入图片说明

编辑:我已经打了更多的高尔夫球,我想我可以再打更多的高尔夫球,但这仍然会发生。现在,我很高兴它能正常工作,并且我有空间在左下角进行签名。我必须保存更多编码的两个想法是:a)更改结束指令be pop, push 1, add, out num(pop n,输出r + 1)和b)在左下角再次复制以将编码保存在稍后的循环中。

上面的图片是我的代码,每个代码为8像素。通常,它与我的Python答案使用相同的算法,但输入顺序为kqn。在实践中,还有大量的堆栈操作。您可以在此处打开图像并运行代码来在此处尝试

说明

这是解决方案的分步实施。

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

您不是在计算空白空间吗?是否有关于如何对Piet进行评分的元文章?应该有。
Sparr

@Sparr,我正在计算空白处。那是21码乘13码的图像,所以分数是273码。
Sherlock16年

啊,我算错了。抱歉。
Sparr

4

CJam,22 20 19字节

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

这会将输入读取为q k n。在CJam解释器中在线尝试。

怎么运行的

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

Golfscript 58 56 55 35 31 30字节

假设三个输入已经在堆栈中,顺序为nkq

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

该解决方案假定我需要摆脱最终答案之外的所有问题。

怎么运行的

有关j(n,k,q)更多详细信息,请参见我的Python 3解决方案。

~                                   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

编辑1:使用@Doorknob的建议(添加了+,以将所有输入输入数组)

以前,

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

编辑2:根据Wiki的规则,添加了〜,并缩短了代码。谢谢@丹尼斯

以前,

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

编辑3:实施了较短的算法。

以前,

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

编辑4:弄清楚我可以%用作地图。

以前,

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

编辑5:次要编辑。改变2$@使[0..q-1]3$2$取回k。咬了一口

以前,

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

1
\;\;\;\;可以替换为])\;(包装在数组中,右uncons,交换和弹出)。
门把手

为了清晰起见,我编辑了我的代码@Dennis。
Sherlock15年

好吧@丹尼斯 添加了〜,并编辑了问题,仅允许使用程序和函数。你有什么其他的建议?
Sherlock15年

不,一切都很好。:)
丹尼斯

2

JavaScript(ES6),56个字节

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

不打高尔夫球

基本上是@ Sherlock9的Python答案的JavaScript改编。

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

测试

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>


我不会将您的非高尔夫版本称为非高尔夫版本:P
Fund Monica的诉讼

1

Mathematica,50个字节

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

匿名函数。按顺序接受输入q,n,k


1

C,81 73字节

基于我的Python答案的@ user81655的Javascript实现。

编辑:删除了我

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

测试

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

在某些C版本中,可以int在参数名称之前删除。
基金莫妮卡的诉讼

1

Python 3,72 66 62字节

62字节的动态编程功能。改编自Wikipedia上的算法。当页面上的q = 1(即i = 1,r = 0)时,曾经有一种直接实现该算法的方法,但是我发现现在已经删除了该算法。

编辑1:我删除i以保存4个字节。解释保持不变。

编辑2:字节数计算错误。我当时\r\n用于EOL,但没有注意到何时添加了3个字节。我相应地降低了字节数。

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

如何运作

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提醒我,我应该解释我的代码(如果只是隐式的,因为他在回答中包括了一个)。如果有任何不清楚的地方,请告诉我。

编辑:

以前,

迭代函数根据Graham,Knuth和Patashnik的具体数学进行了改编。尽管该算法较长,但对于较大的n和较小的k来说速度更快。

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
好像您在复制粘贴中剪了一些东西,有一个悬挂+
xnor 2015年

1

PHP,71字节

基于@ Sherlock9的答案。有关算法,请参见他的Python答案。

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

或者,这是我最初没有算法的天真方法。这使用数组来标记找到的人。

91个字节

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字节

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

基于约瑟夫斯函数的Rosetta代码页上的Haskell算法,带有两个输入。欢迎打高尔夫球。

编辑:我要感谢NIMI用于通过提示有pointfree版本第一算法高尔夫的帮助,并通过让我打高尔夫球的第二算法的帮助知道until关键字存在。

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

我的Python答案结尾处的一种算法版本,改编自Graham,Knuth和Patashnik的《混凝土数学》。虽然这种算法是在长62个字节,并没有得到golfed下跌了第一,它是大快n和小k

取消高尔夫:

第一种算法

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

第二算法

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) 

您是否选择了这个问题来学习新语言?6/10的答案是您的:P
Mego 2016年

@Mego我在聊天室中提到了这个问题:DI问我是否应该张贴它,他们说继续吧。还可以 我的朋友告诉我,这是我的“你好,世界!” 对于新语言:D
Sherlock9

我并不是说这是一件坏事。我很开心,仅此而已。
Mego

@ Sherlock9:您可以until(或多或少)直接翻译第二种算法的Python版本:(n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q)
nimi

上帝保佑你,@ nimi:DI多年来,我一直在努力解决这个问题,尝试了foldl无穷无尽的清单和各种各样的东西。谢谢你的帮助!
Sherlock16年

1

GameMaker语言(GML),88字节

基于@ 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

果冻14 13 字节

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

TryItOnline!

怎么样?

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字节

一个lambda。

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

怎么运行的

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.