鸭,鸭,约瑟夫斯


49

给定一个整数数组:

  1. 从第一个数字开始
  2. 向前跳转n个位置,其中n是当前位置的值
  3. 删除当前位置,使下一个位置成为当前位置。
  4. 转到第2步,直到剩下一个数字为止
  5. 打印该号码

规则

数组环绕(数组中最后一个数字之后的下一个数字是第一个数字)。

零将自身删除(很明显)。

不允许输入负数。

测试用例

[1] => 1
[1,2] => 1
[1,2,3] => 3
[1,2,2] => 1
[1,2,3,4] => 1
[6,2,3,4] => 4
[1,2,3,4,5] => 5
[0,1] => 1
[0,0,2,0,0] => 0

分步示例

[1,4,2,3,5]
 ^          start from the first position
   ^        jump 1 position (value of the position)
[1,  2,3,5] remove number in that position
     ^      take next position of the removed number (the 'new' 'current' position)
         ^  jump 2 positions
[1,  2,3  ] remove number in that position
 ^          take next position (looping on the end of the array)
     ^      jump 1 position
[1,    3  ] remove number in that position
       ^    take next position (looping)
 ^          jump 3 positions (looping on the end of the array)
[      3  ] remove number in that position
print 3

范例#2

[4,3,2,1,6,3]
 ^            start from the first position
         ^    jump 4 positions
[4,3,2,1,  3] remove number in that position    
           ^  take next position
     ^        jump 3 positions
[4,3,  1,  3] remove number in that position    
       ^      take next position
           ^  jump 1 positions
[4,3,  1    ] remove number in that position    
 ^            take next position
   ^          jump 4 positions
[4,    1    ] remove number in that position    
       ^      take next position
 ^            jump 1 position
[      1    ] remove number in that position
print 1

这是,最短的答案以字节为单位!


14
不错的第一个挑战!
路易斯·门多

2
@LuisMendo是的。“像...一样跳过”挑战
J42161217

2
@Jenny_mathy我认为不会有类似的产品,但是正如路易斯说的那样,环绕式阵列对于打高尔夫球是一个有趣的挑战。我认为:/
workoverflow

3
@EriktheOutgolfer并不是真正的骗子。那里的元素是无法区分的,步长是固定的。路易斯的距离更近,但我认为仍然足够不同。
马丁·恩德

3
它是否需要实际打印最终号码,还是可以返回它?它是否需要实际返回数字,还是可以就地对数组进行操作,以便在函数运行后,数组仅包含数字?
iamnotmaynard

Answers:


9

外壳,7个字节

这将结果作为单例列表返回

ΩεSotṙ←

在线尝试!

说明

Ω               Until
 ε              the result is a singleton list
     ṙ          Rotate left by
  S   ←         the first element
   ot           Then remove the first element  

7

Haskell54 50 48字节

f[x]=x
f(x:r)=f$snd<$>zip r(drop(x+1)$cycle$x:r)

在线尝试!

说明:

  • f[x]=x:如果给定列表是单例列表,则返回其元素。
  • f(x:r)=f$ ...:否则,递归地应用于f以下列表:
    • 当前列表的元素无限循环(cycle$x:r),
    • x+1删除第一个元素(drop(x+1)$),
    • 并被截断为的长度r。(snd<$>zip r是的更短替代take(length r))。

先前的54字节版本:

f=(%)=<<head
_%[x]=x
n%(x:r)|n<1=f r|s<-r++[x]=(n-1)%s

在线尝试!



6

MATL,21字节

1`yy)+ynX\[]w(5Mynq]x

在线尝试!验证所有测试用例

说明

1        % Push 1: current position in the array
`        % Do...while
  yy     %   Duplicate top two elements in the stack. Takes input implicitly
         %   in the first iteration.
         %   STACK: array, position, array, position
  )      %   Get specified entry in the array
         %   STACK: array, position, selected entry
  +      %   Add
         %   STACK: array, position (updated)
  y      %   Duplicate from below
         %   STACK: array, position, array
  n      %   Number of elements of array
         %   STACK: array, position, number of elements or array
  X\     %   1-based modulus
         %   STACK: array, position (wrapped around)
  []     %   Push empty array
         %   STACK: array, position, []
  w      %   Swap
         %   STACK: array, [], position
  (      %   Write value into specified entry in array. Writing [] removes
         %   the entry
         %   STACK: array (with one entry removed)
  5M     %   Push latest used position. Because of the removal, this now
         %   points to the entry that was after the removed one
         %   STACK: array, position
  y      %   Duplicate from below
         %   STACK: array, position, array
  n      %   Number of elements of array
         %   STACK: array, position, number of elements of array
  q      %   Subtract 1
         %   STACK: array, position, number of elements of array minus 1
]        % End. If top of the stack is nonzero, proceed with next iteration
         % STACK: array (containing 1 entry), position
x        % Delete. Implicitly display
         % STACK: array (containing 1 entry)

1
注意:使用列表旋转而不是保留指针可能会使此操作更短。
Erik the Outgolfer '17

1
@Erik谢谢。但是,现在我添加了解释,我想我会这样保留
Luis Mendo

好吧,您可以随时删除解释,它将保留在历史记录中:)
Erik the Outgolfer


5

CJam,15个字节

l~_,({_0=m<1>}*

在线尝试!

说明

我没有跟踪指针,而是循环地移动数组,以便当前元素始终位于最前面。

l~     e# Read and evaluate input.
_,(    e# Get its length L and decrement to L-1.
{      e# Run this block L-1 times...
  _0=  e#   Get the first element X.
  m<   e#   Rotate the array left by X positions.
  1>   e#   Discard the first element.
}*
       e# The final element remains on the stack and gets printed implicitly.

一个有趣的替代方法,不幸的是它不保存任何字节:

l~_{;m<1>_0=}*;

5

脑筋急转弯,88字节

([[]]()){({}<(({})){({}<({}<([]){({}{}<>)<>([])}{}>)<>{({}[<>[]])<>}<>>[()])}{}{}>())}{}

在线尝试!

说明

([[]]())                      Push negative N: the stack height - 1
{({}< … >())}{}               Do N times
     (({}))                     Duplicate M: the top of the stack
     {({}< … >[()])}{}          Do M times 
                                  Rotate the stack by 1:
          ({}< … >)               Pop the top of the stack and put it back down after
          ([]){({}{}<>)<>([])}{}  Pushing the rest of the stack on to the other one, in reverse, with the stack height added to each element (to ensure that all are positive)
          <>{({}[<>[]])<>}<>      Push the rest of the stack back, unreversing, and subtracting the stack height from each element
                      {}        Pop the top of stack

1
一个非常奇怪的高尔夫球,但是这里是88个字节
小麦巫师

1
@WheatWizard很好,令人惊讶的是,我早些时候尝试过类似的方法。
H.PWiz

我永远不知道人们怎么能这样编码!有伪代码翻译器吗?
workoverflow

1
@workoverflow不,说起来真的很容易。在我真正开始之前这是非常艰巨的,但是当命令如此简单时,它很容易学习。
H.PWiz

5

Python 2,55个字节

def f(a):
 while a[1:]:l=a[0]%len(a);a[:]=a[-~l:]+a[:l]

在线尝试!

输出为单例列表,默认情况下允许。提醒我,允许修改函数参数,这使Dennis节省了几个字节。

这个怎么运作

  • def f(a)-用参数定义函数a

  • while a[1:]:-虽然a删除第一个元素是正确的,但请运行下面的代码块。具有一个或多个元素的列表是真实的,而空列表在Python中是虚假的,因此一旦a达到1的长度,它将停止。

  • l=a[0]%len(a)-取第一个元素,然后除以除以的长度a。将结果分配给l

  • a[:]=a[-~l:]+a[:l]- al元素旋转到左侧,并删除第一个,同时将其分配a到位。


Python 2,63个字节

f=lambda a,i=0:a[1:]and f(a,a.pop(((a*-~i)[i]+i)%len(a))+1)or a

在线尝试!

虽然时间更长,但看起来似乎更优雅。也感谢ovs帮助聊天。


1
您不能做类似a,*b=input()(python3)的操作并节省一些字节吗?但是,我不确定这会如何影响l切片
Rod

1
@Rod我不这么认为,我需要评估输入过在Python 3
Xcoder先生


4

果冻,9个字节

ṙḷ/ḊµL’$¡

在线尝试!

-2个字节,感谢user202729

说明

ṙḷ/ḊµL’$¡  Main Link
     L’$¡  Repeat <length - 1> times
ṙ          Rotate left by
 ḷ/        The first element (from JHT; thanks to user202729)
   Ḋ       Take all but the first element



3

Mathematica,36个字节

使用马丁算法

#//.l:{x_,__}:>Rest@RotateLeft[l,x]&

Misha Lavrov和&Martin Ender的-5字节

在线尝试!


1
您可以使用模式选择第一个元素来节省两个字节#//.{x_,y__}:>Rest@RotateLeft[{x,y},x]&。(当仅存在一个元素时,由于{a}不再匹配该模式,此操作将停止{x_,y__}。)
Misha Lavrov

1
@MishaLavrov目前无法测试,但是您可以通过删除y,调用整个列表l然后使用l代替来进一步缩短测试时间{x,y}
马丁·恩德

1
@MartinEnder你的意思是这样- #//.l:{x_,__}:>Rest@RotateLeft[l,x]&吗?
Misha Lavrov

1
@MishaLavrov是的。
马丁·恩德


3

JavaScript(ES6),54 60字节

@Shaggy 固定版本节省了1个字节
(+6个字节)

修改输入数组,将其减少为单例。

f=(a,p=0)=>1/a||f(a,p=(p+a[p%(l=a.length)])%l,a.splice(p,1))

测试用例

怎么样?

我们递归地应用挑战中描述的算法。只有停止条件1/a可能看起来有点怪异。应用算术运算符时:

  • 多于一个的元件的阵列被强制为NaN1/NaNNaN(falsy)。
  • 正好一个整数的数组被强制为该整数,从而导致N> 01/0 = +Infinity1/N = positive floatN> 0(均为真)。
f = (a, p = 0) =>                 // a = input array, p = pointer into this array
  1 / a ||                        // if a is not yet a singleton:
    f(                            //   do a recursive call with:
      a,                          //     a
      p = (                       //     the updated pointer
        p + a[p % (l = a.length)] //
      ) % l,                      //
      a.splice(p, 1)              //     the element at the new position removed
    )                             //   end of recursive call

看到splice修改原始数组后,您可以f=(a,p=0)=>1/a||f(a,p=p+a[p]%a.length,a.splice(p,1))处理52个字节
Shaggy

似乎没有为第二步示例给出正确的结果,f=(a,p=0)=>1/a?a:f(a,p=(p%a.length+a[p%a.length])%a.length,a.splice(p,1))可以,但是可以进行优化
Nahuel Fouilleul

@NahuelFouilleul糟糕。我认为在某些时候p+a[p]可以删除括号。当然不是这种情况。感谢您举报!
Arnauld

看到这个共识,@ Neil 在这里引起了我的注意。
毛茸茸的

@粗野的哦,我明白了。谢谢!(我第一次错过了您的TIO链接...)
Arnauld


3

Java 8,79字节

此lambda接受a Stack<Integer>并返回intor Integer

l->{for(int i=0,s=l.size();s>1;)l.remove(i=(i+l.get(i%s))%s--);return l.pop();}

在线试用

不打高尔夫球

l -> {
    for (
        int i = 0, s = l.size()
        ; s > 1
        ;
    )
        l.remove(
            i = (i + l.get(i % s)) % s--
        );
    return l.pop();
}

致谢

  • -2个字节,感谢Nahuel Fouilleul

1
i%=s如果有l.get(i)更改,可以将其删除l.get(i%s)
Nahuel Fouilleul

2

Pyth,9个字节

.WtHt.<Zh

在这里尝试!

默认情况下,这会将结果输出为单例列表。

这个怎么运作

.WtHt.<Zh ~ Full program.

.W        ~ Functional while. It takes three arguments, two functions: A and B
            and a starting value, which in this case is automatically assigned
            to the input. While A(value) is truthy, value is set to B(value).
            Returns the ending value. A's argument is H and B's is Z.
  tH      ~ A (argument H): Remove the first element of H. A singleton list
            turns into [], which is falsy and thus breaks the loop. Otherwise,
            it is truthy and the loops goes on until the list reaches length 1.
     .<Zh ~ B (argument Z): Cyclically rotate Z by Z[0] places, whereas Z[0]
            represents the first element of Z.
    t     ~ And remove the first element.

注意:如果不想看到这些括号,只需在整个代码前添加he


2

迅捷,87字节

func f(a:inout[Int]){var i=0,c=0;while(c=a.count,c>1).1{i=(i+a[i%c])%c;a.remove(at:i)}}

通过修改input返回为单例列表在线尝试!

说明

func f(a:inout[Int]){
  var i=0,c=0;            // Set the index i to 0
  while(c=a.count,c>1).1{ // While the length of the list > 0:
    i=(i+a[i%c])%c;       //  Add a[i] to i and loop back using modulo
    a.remove(at:i)        //  Remove a[i]
  }
}

2

Perl 6的46个 45字节

(-1字节感谢Brad Gilbert)

{($_,{(|$_ xx*)[.[0]+(1..^$_)]}...1)[*-1][0]}

在线尝试!

($_, { ... } ... 1)生成一个列表序列,从输入列表开始$_,每个连续元素都是由大括号表达式生成的,并在列表智能匹配时1终止,即长度为1。尾随[* - 1]获得最后一个元素,最后一个获得最终元素。[0]从该单例列表中删除唯一的元素。

(|$_ xx *)生成当前元素的平面无限复制副本。用范围索引此列表,.[0] + (1 ..^ $_)以提取系列中的下一个有限列表。


1
令人震惊
阿德里安

[*-1][0]可以合并成[*-1;0]一个字节。也1..$_-1最好写为1..^$_再次保存一个字节。
布拉德·吉尔伯特b2gills '17

我尝试了@ BradGilbertb2gills [*-1;0],但它似乎在某种程度上并不等效。然后该函数返回一个列表而不是一个数字。
肖恩

这并没有停止1..^$_优化
Brad Gilbert b2gills




1

Java 8,325字节

打高尔夫球:

static void n(Integer[]j){Integer[]h;int a=0;h=j;for(int i=0;i<j.length-1;i++){if(h.length==a){a=0;}a=(a+h[a])%h.length;h[a]=null;h=m(h);}System.out.print(h[0]);}static Integer[] m(Integer[]array){Integer[]x=new Integer[array.length-1];int z=0;for(int i=0;i<array.length;i++){if(array[i]!=null){x[z]=array[i];z++;}}return x;}

取消高尔夫:

 interface ArrayLeapFrog {
static void main(String[] z) throws Exception {
    Integer[] j = {6, 2, 3, 4};
    n(j);
}

static void n(Integer[] j) {
    Integer[] h;
    int a = 0;
    h = j;
    for (int i = 0; i < j.length - 1; i++) {
        if (h.length == a) {
            a = 0;
        }
        a = (a + h[a]) % h.length;
        h[a] = null;
        h = m(h);
    }
    System.out.print(h[0]);
}

static Integer[] m(Integer[] array) {
    Integer[] x = new Integer[array.length - 1];
    int z = 0;
    for (int i = 0; i < array.length; i++) {
        if (array[i] != null) {
            x[z] = array[i];
            z++;
        }
    }
    return x;
  }
}

4
欢迎!static几点提示:无需在此处计算关键字。通常,多方法解决方案被实现为类的非静态成员,并main创建用于测试的实例。另外,如果您以这种方式进行操作,则可以支持Java 7,并且可以简单地提交“ Java”解决方案。为了将来参考,这里的输入格式往往非常灵活,因此例如您可以选择将输入作为格式List(这对于解决此问题很有帮助)。
雅各布

1

APL + WIN,36个字节

¯1↑⍎¨(1⌈¯1+⍴v←,⎕)⍴⊂'v←(1<⍴v)↓v[1]⌽v'

说明:

提示屏幕输入。

'v←(1<⍴v)↓v[1]⌽v' Loop logic as a string

 (1<⍴v)↓ only drop the first when number of elements n>1

 (1⌈¯1+⍴v←,⎕)⍴⊂ create a nested vector of logic of length 1 max n-1

 ⍎¨ execute each element of the nested vector in turn

¯1↑ take answer from executing final element

1

Python 2,61字节

def f(x):
 while x[1:]:y=x[0]%len(x);x=x[y+1:]+x[:y]
 print x

1
我知道存在很多python答案,但我想我也可以添加自己的答案。
Rɪᴋᴇʀ

1

JavaScript,58 56 59字节

let f =

a=>{for(i=0,k=a.length;k>1;)i+=a[i%=k],a.splice(i%=k--,1)}
<h2>Test</h2>
Enter or paste a valid array literal within square brackets and click Run.
<blockquote>
   <input id = "array" type="text" length="20">
   <button type="button" onclick="run()">Run</button>
</blockquote>
Result: <pre id="o"></pre>

<script>
    function run() {
       let a = JSON.parse(array.value);
       f(a);
       o.textContent = a;
    }
</script>

返回结果,作为输入数组中剩余的唯一元素,该元素将在适当位置进行更新。

在for循环主体中使用逗号分隔的语句而不是块语句可以节省两个字节!丢失了三个字节以从数组末尾删除的元素中跳过(:

少打高尔夫球:

a => {
    for(i=0,k=a.length;k>1;) // once less than array length
        i+=a[i%=k],          // the new index
        a.splice(            // delete an element
           i%=k--,           // ensuring index is within array,
                             // and post decrement loop count
           1
        )
}

这似乎为给出了错误的答案[3, 5, 7, 9]
尼尔,

错了[3,5,7,9]。期望值5
edc65 '17

该函数不会返回该值,我不确定字节数是否正确,请牢记这一点,因为它不能单独工作...
Brian H.

@ edc65和Neil,谢谢-数组末尾删除的元素的索引未调整为缩短数组的开头。
traktor53

@BrianH。该函数修改其参数,对此codegolf.meta.stackexchange.com/a/4942/21348
edc65 '17

1

脑筋急转弯,104字节

H.PWiz 在这里提供了一个简短的答案,我已经帮忙做出了,您应该检查一下。

([[]]()){({}()<(({})){({}[()]<({}<(([])<{{}({}<>)<>([])}{}<>>)<>>)<>{({}[()]<({}<>)<>>)}{}<>>)}{}{}>)}{}

在线尝试!

说明

([[]]())   #Push 1 minus stackheight
{({}()<    #N times
 (({}))    #Get a copy of the top
 {({}[()]< #N times
  ({}<(([])<{{}({}<>)<>([])}{}<>>)<>>)<>{({}[()]<({}<>)<>>)}{}<>
           #Roll the top to the bottom (From the wiki)
 >)}{}     #End loop
 {}        #Remove one value
>)}{}      #End loop

我以为我会参加比赛。然后我意识到我的几乎和你的完全一样,除了一个不同的“顶峰”
H.PWiz

我看见了 ;)。利用一切都是非负的事实是相当聪明的。
小麦巫师


1

[R,111个117 126字节

感谢@Giuseppe通过更改为while循环来保留11个字节,通过删除该功能并直接读取用户输入又得到了4个字节。

我对到达那里所花的时间感觉不太好-我确信存在一个更优雅的解决方案。

i=scan();m=1;while((l=sum(i|1))-1){j=i[m];p=`if`(j+m>l,j%%l+!m-1,j+m);p=`if`(!p,m,p);i=i[-p];m=`if`(p-l,p,1)};i

在线尝试!

非高尔夫代码

i=scan()
m=1
while((l=sum(i|1))-1){
  j=i[m]
  p=`if`(j+m>l,j%%l+!m-1,j+m)
  p=`if`(!p,m,p)
  i=i[-p]
  m=`if`(p-l,p,1)
}
i

117个字节 -注意,因为这是一个递归函数,名称f=必须包括
朱塞佩·

1
我发现在没有数组旋转的情况下使用基于1的索引语言会遇到相当困难的挑战。while我认为使用循环可能会短1-3个字节。
朱塞佩


我以前的115字节无效,因为我们都忘记f=了递归函数的一部分。:(
Giuseppe

我更新了旧的分数和新的分数以反映递归性:)在“ while”循环中,我使用scan打出了另外4个字节。
标记
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.