弹枪编号


45

猎枪的数字是一个相当简单的定义,但一些有趣的结构序列。从自然数开始:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...

现在,将所有数字除以2整除的索引,将它们分成对,然后交换每对中的数字:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ...
   ^     ^     ^     ^      ^       ^       ^  
    <--->       <--->        <----->         <----
1, 4, 3, 2, 5, 8, 7, 6, 9, 12, 11, 10, 13, 16, ...

现在对可被3整除的索引执行相同的操作:

1, 4, 3, 2, 5, 8, 7, 6, 9, 12, 11, 10, 13, 16, ...
      ^        ^        ^           ^          
       <------>          <--------->           
1, 4, 8, 2, 5, 3, 7, 6, 10, 12, 11, 9, 13, 16, ...

然后对456,依此类推:

1, 4, 8, 2, 5, 3, 7, 6, 10, 12, 11, 9, 13, 16, ...
1, 4, 8, 6, 5, 3, 7, 2, 10, 12, 11, 14, 13, 16, ...
1, 4, 8, 6, 12, 3, 7, 2, 10, 5, 11, 14, 13, 16, ...
1, 4, 8, 6, 12, 14, 7, 2, 10, 5, 11, 3, 13, 16, ...
...

经过k个这样的步骤后,前k + 1个数字将被固定。因此,我们可以将Shot弹枪编号的无限序列定义为让k变为无穷大的极限。前66个数字是:

1, 4, 8, 6, 12, 14, 16, 9, 18, 20, 24, 26, 28, 22, 39, 15, 36, 35, 40, 38, 57, 34, 48, 49, 51, 44,
46, 33, 60, 77, 64, 32, 75, 56, 81, 68, 76, 58, 100, 55, 84, 111, 88, 62, 125, 70, 96, 91, 98, 95,
134, 72, 108, 82, 141, 80, 140, 92, 120, 156, 124, 94, 121, 52, 152, 145, ...

有趣的事实:尽管仅通过置换自然数即可获得此序列,但它不包含任何质数。

挑战

给定一个整数n > 0,找到nth Shotgun号。您可以编写程序或函数,通过STDIN(或最接近的替代方案),命令行自变量或函数自变量获取输入,然后将输出返回或将其打印到STDOUT(或最接近的替代方案)。

这是代码高尔夫球,因此最短的提交(以字节为单位)获胜。

排行榜

得到的答案比我想象的要多,还有几个人在用相同的语言竞争。因此,这里有一个堆栈代码片段,可按语言生成常规排行榜和获胜者概述。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

# Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以将旧分数保留在标题中,方法是将它们打掉。例如:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
有趣的事实是疯狂的,这种算法将所有的质数洗到最后?还是还有其他自然数不会出现?
德文·帕森斯

1
@DevonParsons是的,它会将所有素数“拖到末尾”。但我认为还缺少其他数字。它看起来像102125并且30不会出现任何,例如。
马丁·恩德

3
这听起来像欧拉计画的问题。我不认为这是……但也许应该如此。
Corey Ogburn

9
通常,在第kn次迭代中,k数组中的th个元素会转置至第2kth个位置,直到第2kn次迭代(此后它会转置至第4kn个位置,无穷大)时才会再次被触摸。可以说,素数在转弯出现之前是不会移置的,所以所有素数都会向前移动。但是,只需打印出要在迭代2和每个奇数迭代中转置的第一个元素,我们就可以轻松地列出无辜受害者的列表。列表为:2、3、5、7、10、11、13、21、17、19、30、23、27、25、29、31、45、42、37、54、41、43、65, ...
泰奥菲尔

3
@ Sherlock9完成!如果获得批准,它将为https://oeis.org/A266679。新年快乐!
泰奥菲尔

Answers:


5

佩斯,19 22

u-G*H^_!%GH/GHrhQ2Q

@PeterTaylor的golfscript答案的一个相当幼稚的实现。

在这里在线尝试

它使用与下面其他Pyth程序相同的技巧将while循环转换为折叠。


u+G**H!%GHty%/GH2rhQ2Q

@ Sp3000算法的天真副本,翻译为Pyth。

您可以在这里在线尝试

使用reduce(折叠的python名称)模拟while循环。它枚举了range(input, 2)Pyth得出的结果range(2, input)[::-1]。与Pyth相关的其他高尔夫还包括使用not代替<2和使用y的隐藏模式,将数字参数的值加倍。


21

> <>,52 45字节

> <>的Esolangs页面

i:&&:&1-?vn;
2*1-*+20.>:&:&%1(&:&*{:}&:1-&,2%

由于需要一些模数和乘法,所以有很多复制和移动元素。逻辑与我的Python解决方案完全相同。

通过来自STDIN 的代码点获取输入,例如"!" = 33 -> 75


10
并且您获得了有史以来最笨拙的输入格式的奖项:P
Caridorc

无论如何+1,请放心:)
Caridorc 2015年

@ Sp3000 IMO,它只应算为一个
SuperJedi224

@ SuperJedi224实际上,根据此meta帖子显然-v算作三个:/
Sp3000 '16

17

Python 2,58个字节

i=n=input()
while~-i:n+=(n%i<1)*i*(n/i%2*2-1);i-=1
print n

像大多数其他答案一样,这个想法是倒退。


让我们将其称为step k+1step i,以便在step 上交换i所有的倍数i。我们需要两个简单的观察:

  • 位置n阵列中,仅在步骤交换i如果n是整除i
  • 要确定您是掉期中的较低数字还是较高数字,请查看n/i mod 2。如果这是1,则您是较低的数字(将向上交换),否则,您将是较高的数字(将向下交换)。

这为我们提供了一种向后工作的算法。从最后一步(步骤i = 6)开始,让我们尝试6。

Step 6: Position 6 swaps with position 12 (6 is divisible by 6, 6/6 = 1 == 1 mod 2)

现在我们知道数字来自位置12。然后:

Step 5: No swap (12 not divisible by 5)
Step 4: Position 12 swaps with position 16 (12 is divisible by 4, 12/4 = 3 == 1 mod 2)

所以现在我们知道它来自之前的16。最后:

Step 3: No swap (16 not divisible by 3)
Step 2: Position 16 swaps with position 14 (16 divisible by 2, 16/2 = 8 == 0 mod 2)

由于这是第一步(请记住,k+1),因此我们已经完成了,最终到达位置6的数字最初来自位置14,即第六把shot弹枪的数字是14。

因此,现在对Python进行解释:

i=n=input()             Read input, and store into i (step) and n (position)
while~-i:               while i-1 != 0:, or since we're descending with i this is just while i>1:
  n+=                   Add to the current position...
    (n%i<1)*            1* whatever's next if n is divisible by i, otherwise 0* (i.e. nothing)
    i*                  How many positions n might go up/down
    (n/i%2*2-1)         n/i%2 tell us higher/lower, *2-1 maps 0 or 1 to -1 (down) or +1 (up)
  i-=1                  Decrement the step number
print n                 Output

有趣的方式写i-1~-i
mbomb007'3

6
@ mbomb007:同意。尽管很聪明,因为它具有相同的含义,但是不需要在后面留空格while。做得好,Sp3000。
Alex A.

我可以用reduce来得到的结果最短:u+G**H!%GHty%/GH2rhQ2Q
FryAmTheEggman

1
@ FryAmTheEggman,Sp3000,你们两个都不打算发布吗?
Martin Ender'3

@MartinBüttner我最初不是发布它的,因为我认为它太过份了。我现在将其发布为CW答案。
FryAmTheEggman 2015年

6

Haskell,68个字节

n#k|mod k(2*n)<1=k-n|mod k n<1=k+n|k>0=k
s n=foldr((.).(#))id[2..n]n

可能更适合打高尔夫球,尤其是第一排。这定义了一个函数s,该函数获取n并返回n第shot弹枪编号。

map s [1..66]
[1,4,8,6,12,14,16,9,18,20,24,26,28,22,39,15,36,35,40,38,57,34,48,49,51,44,46,33,60,77,64,32,75,56,81,68,76,58,100,55,84,111,88,62,125,70,96,91,98,95,134,72,108,82,141,80,140,92,120,156,124,94,121,52,152,145]

说明

helper函数#接受两个数字nk,并k在通过将对交换操作应用于每个nth号而定义的列表中返回th号。例如,将其应用到前20个具有的数字将n = 4产生以下结果:

map (4#) [1..20]
[1,2,3,8,5,6,7,4,9,10,11,16,13,14,15,12,17,18,19,24]

的结果s n是通过使用[2..n]二阶函数(.).(#)(将一个数字m和一个函数f(最初是恒等函数id))减少(“折叠”)列表而获得的,并返回一个带k并返回的函数f (m # k)。例如,在n = 4列表[2,3,4]简化为可以接受k并返回的函数的情况下id (4 # (3 # (2 # k)))。该id只需要基本情况n = 1,其中列表是空的。最后,我们为该函数提供输入k = n,获得nshot弹枪的编号。



5

Ruby,92个字节

def s(d,n)
d==1?n:s(d-1,n%d==0?n+(n%(d*2)==0?-d :d):n)
end
n=ARGV[0].to_i
print s(n,n).to_s

我第一次打高尔夫。不基于任何其他答案。


现在,尽管我看了其他一些,但是我注意到大多数只定义一个函数,而不是一个接受输入并产生输出的完整程序。OP要求提供带有输入和输出的完整程序。习惯上不理会这些要求吗?


84字节

n=ARGV[0].to_i
d=n
while d>1
n+=(n%d==0?(n%(d*2)==0?-d :d):0)
d-=1
end
print n.to_s

在查看了其他答案并意识到迭代解决方案是可能的之后。


2
84字节解决方案的一些改进:1.更改ARGV$*magic global。2. to_s不需要。3.不用分配dn单独的一行,只需d=n=...剃掉一个字符即可。第一次打高尔夫球不错!:)
门把手

1
我在哪里要求完整的课程?“您可以编写程序或函数...”;);(这也是代码高尔夫挑战赛的默认设置,但出于完整性考虑,我通常将其包括在内。)
Martin Ender

要添加到@Doorknob的建议中,该n+=行上的两组括号是不必要的,并且==0可以安全地将这两种情况都更改为<1
彼得·泰勒

5

Python 2,97 79个字符

g=lambda n,k:n>1and g(n-1,k-(k%n<1)*n*(-1)**(k/n%2))or k
n=input()
print g(n,n)

它通过递归地向后追逐数字,为每个索引确定正确的值。该算法是独立发现的。

编辑:现在只打印n第一个数字,而不是第一个n数字。当然,迭代方法会更短一些,但是我不想复制Sp3000的代码。


是的,我想每个人都会对此予以关注。我发现该g(i,i)部分特别令人讨厌……
Sp3000 2015年

2
由于该print语句,该语言应标记为Python 2 。
mbomb007'3

@ mbomb007已更正它。
雅库布

4

Haskell,79个字节

1#i=i
s#i|i`mod`(2*s)==0=(s-1)#(i-s)|i`mod`s==0=(s-1)#(i+s)|1<2=(s-1)#i
p n=n#n

用法:p 66输出哪个145

解释不多:该函数#递归地计算i步骤位置上的the弹枪数量sp n返回nstep 位置的数字n


哦,在提交我的信息之前,我没有看到您的答案。似乎我们有完全不同的方法。
Zgarb 2015年

4

k,41个字节

{{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]}

 / apply to an int
 {{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]} 42
111
 / apply to 1 through 66
 {{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]}'1+!66
1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38 57 34 48 49 51 44 46 33 60 77 64 32 75 56 81 68 76 58 100 55 84 111 88 62 125 70 96 91 98 95 134 72 108 82 141 80 140 92 120 156 124 94 121 52 152 145
  • {...} lambda,x和y是隐式的第一和第二参数
  • $[b;t;f] 三元运算符,分别求b和t / f
  • b!a a模b
  • _ floor,将除法结果转换为一个整数
  • %
  • {...}/[x;y] 用x作质数{...}并应用于列表y,等效于f [f [.. f [f [x; y0]; y1]; .. yn-1]; yn]
  • | 相反
  • ! iota函数,生成列表0到n-1

4

普通Lisp 113 91

(迭代:91)

(defun s(n)(do((r n(1- r)))((= r 1)n)(if(= 0(mod n r))(incf n(* r(if(oddp(/ n r))1 -1))))))

(原始的,递归的:113)

(defun s(n &optional(r n))(cond((= r 1)n)((= 0(mod n r))(s(+ n(* r(if(oddp(/ n r))1 -1)))(1- r)))(t(s n(1- r)))))

使用递归版本:

(trace s)
(s 10)

  0: (S 10)
    1: (S 20 9)
      2: (S 20 8)
        3: (S 20 7)
          4: (S 20 6)
            5: (S 20 5)
              6: (S 15 4)
                7: (S 15 3)
                  8: (S 18 2)
                    9: (S 20 1)
                    9: S returned 20
         ...
    1: S returned 20
  0: S returned 20

测验

检查并测量迭代版本:

(let ((list '(1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38 57 34 48 49 51 44
              46 33 60 77 64 32 75 56 81 68 76 58 100 55 84 111 88 62 125 70 96 91 98 95
              134 72 108 82 141 80 140 92 120 156 124 94 121 52 152 145)))
  (time
   (loop for r in list
         for n from 1
         always (= r (s n)))))

 => T

Evaluation took:
  0.000 seconds of real time
  0.000000 seconds of total run time (0.000000 user, 0.000000 system)
  100.00% CPU
  807,160 processor cycles
  32,768 bytes consed

4

Mathematica,53个 49字节

(For[i=n=#,n>1,--n,If[n∣i,i+=Mod[i,2n]2-n]];i)&

我决定打高尔夫以参考实施。该是“分裂”,并计数3个字节Unicode的象征。否则,它将使用与其他所有人相同的算法。

它定义了一个未命名函数,该函数将n单个参数作为参数并返回returns n弹枪的编号。


4

GolfScript,27个字符

~.,(~%{):i\.@%!~)1$i/?i*-}/

说明

如果f(i, n)是转换n后位置的值i-1,我们有

f(1, n) = n
f(i, n) = f(i - 1, n % i == 0 ? (((n / i - 1) ^ 1) + 1) * i : n)  for i > 1

其中^表示按位异或; 给定输入n,我们要计算f(n, n)

从递归函数到循环的转换并不有趣。有趣的是

n % i == 0 ? (((n / i - 1) ^ 1) + 1) * i : n

可以重写。更明显的方法是说必须

n + (n % i == 0 ? i : 0) * g(n / i)

对于一些g。显然g1和之间交替-1,因为仓位上下交替互换;由于g(1) = 1(由于1交换到2),我们有

n + (n % i == 0 ? i : 0) * -1**(1 + n / i)

其中**表示幂。最终的节省来自于将其重写为

n - i * (n % i == 0 ? -1 : 0)**(n / i)

解剖

~             # Evaluate input to get n
.,(~%{        # For n-1 downto 1...
  ):i         #   Let i be that value + 1, so for i = n downto 2...
  \.@%!       #   Find n % i == 0 ? 1 : 0
  ~)          #   Negate
  1$i/?       #   Raise to the power of n/i
  i*-         #   Multiply by i and subtract
}/

既然您拥有最短的GS和CJam答案,为什么不也拥有最短的Pyth答案?u-G*H^_!%GH/GHrhQ2Q如果您不想自己发表此内容,请告诉我/将其添加到CW答案中。
FryAmTheEggman 2015年

@FryAmTheEggman,我可能不是在CJam实习的,但我至少可以或多或少地阅读它。我不知道您评论中的Pyth说什么,尽管从上下文来看,我认为这是这个答案的一部分。因此,最好将其发布,因为您可以回答有关它的问题。
彼得·泰勒


4

朱莉娅61 57字节

n->(i=n;while~-i!=0 n+=(n%i<1)*i*(n÷i%2*2-1);i-=1;end;n)

这将创建一个未命名函数,该函数使用单个参数n并返回returns n弹枪的编号。要给它起个名字,例如f=n->(...)

例子:

julia> for i = 1:10 println(f(i)) end
1
4
8
6
12
14
16
9
18
20

目前,这是基于@ Sp3000很棒的Python答案。我会尽快重温这一点,因为在Julia中必须比在此完成的方法更短。一如既往地欢迎任何输入。



3

CJam,28 27字节

因此,这有点令人尴尬。在发布此内容之前,我亲自尝试过打高尔夫球,并在CJam中获得了30个字节。现有的答案都还没有击败过。同时,我还设法减少了三个字节。还有就是在评论较短Pyth的解决方案,但没有较短已张贴在回答中,所以在这儿呢。也许这激发了APL / J人员在我不得不接受自己的答案之前要更加努力(或者有人实际发布了Pyth解决方案)。;)

l~__(,f-{_I_+%_+I-_zI=*+}fI

在这里测试。

说明

l~                          "Read input N and eval.";
  __(,                      "Duplicate twice, create range [0 1 2 ... N-2].";
      f-                    "Subtract each from N, giving [N N-1 N-2 ... 2].";
        {               }fI "For each element, storing the element in I.";
         _I_+%_+I-          "Compute 2(N % 2I)-I - the shuffling offset";
                  _zI=      "Check that this offset is ±I.";
                      *+    "Multiply the offset by this boolean and update to N.";

3

J,34 32字节

   (]+[*(1-~2*2|%~)*0=|)/@(_1}2+i.)

   ((]+[*(1-~2*2|%~)*0=|)/@(_1}2+i.)) every 1+i.20  NB. running with inputs 1..20
1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38

会尝试打更多的高尔夫球,稍后再添加一些说明。

在这里在线尝试。



1

Ruby,57个 47字节

本质上,这是Sp3000的Python解决方案(带有xnor的建议),翻译为Ruby。我可能会在几个地方打高尔夫球。

->n{n.downto(2).map{|i|n+=i*(n/i%2-~-n/i%2)};n}
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.