ショットガン番号


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つの番号は固定されます。したがって、ショットガン数の無限シーケンスを、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(または最も近い代替)に出力できます。

これはコードゴルフであるため、最短の提出(バイト単位)が優先されます。

リーダーボード

これは、私が思っていたよりも多くの回答を得ているだけでなく、同じ言語で競っている数人の人々もいます。そこで、ここでは、定期的なリーダーボードと言語ごとの勝者の概要の両方を生成するスタックスニペットを示します。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

# Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

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


1
この楽しい事実はおかしいです、このアルゴリズムはすべての素数を最後までシャッフルしますか?または、発生しない他の自然数もありますか?
デボンパーソンズ

1
@DevonParsonsはい、すべての素数を「最後まで」シャッフルします。しかし、他にも不足している数字があると思います。それはのように見える102125および30例えば、いずれかの表示されません。
マーティンエンダー

3
これは、プロジェクトオイラーの質問のように聞こえます。私はそれが...とは思わないが、多分そうあるべきだ。
コーリー

9
一般に、kthの繰り返しkで、配列のthの要素は2kthの位置に2k転置され、それが4kthの位置に無限に転置されるとき、thの繰り返しまで再び触れられません。プライムは転向するまで転置されないので、いわば、すべてのプライムは前方にシャッフルされます。しかし、イテレーション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になります。明けましておめでとうございます!
テオフィル

回答:


5

ピス、19 22

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

@PeterTaylorのgolfscript answerのかなり単純な実装。

こちらからオンラインでお試しください

これは、以下のその他のPythプログラムが行うのと同じトリックを使用して、whileループをフォールドに変換します。


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

Pythに翻訳された@ Sp3000のアルゴリズムの素朴なコピー。

こちらからオンラインで試すことができます

reduce(pythonのfoldの名前)を使用して、whileループをエミュレートします。それはrange(input, 2)、Pythでにどのがうまくいくかを列挙していrange(2, input)[::-1]ます。他のPyth関連のゴルフでは、数値引数の値を2倍にする非表示モードの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

SP3000 @ IMOそれは一つだけとしてカウントすべきである
SuperJedi224

@ SuperJedi224実際、このメタ投稿によると明らかに-v3としてカウントされます:/
Sp3000

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が交換されるようにします。2つの簡単な観察が必要です。

  • 位置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から来ました。つまり、6番目のショットガン番号は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

6
@ mbomb007:同意した。賢いのは、同じ意味を持ちますが、後にスペースが不要になるためwhileです。素晴らしい仕事、Sp3000。
アレックスA.

pythでこれを取得できる最短時間は、reduceを使用することu+G**H!%GHty%/GH2rhQ2Q
でした。– FryAmTheEggman

1
@ FryAmTheEggman、Sp3000、あなたも二人とも投稿しませんか?
マーティンエンダー

@MartinBüttnerコピーが多すぎると感じたので、私はもともと投稿しませんでした。今のところ、CWの回答として投稿します。
FryAmTheEggman

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を定義します。nn

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]

説明

ヘルパー関数#は2つの数値nとを受け取り、ペアスワップ操作をすべての数値に適用することで定義されたリスト内の数値kを返します。たとえば、最初の20個の数値に適用すると、次のようになります。knn = 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]

の結果は、数と関数(最初は恒等関数)を取り込んで2番目の関数を返す2番目の関数によってs nリストを縮小(「折り畳み」)することによって取得され、を取得して返す関数を返します。たとえば、リストがを取り、返す関数に縮小される場合。唯一の基本ケースのために必要とされているリストが空です、。最後に、この関数にinputを与えて、番目のショットガン番号を取得します。[2..n](.).(#)mfidkf (m # k)n = 4[2,3,4]kid (4 # (3 # (2 # k)))idn = 1k = nn



5

ルビー、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$*ます。2. to_sは不要です。代わりに割り当てるの3 dn別の行には、ただやるd=n=...の文字を剃り落とすします。初めてのゴルフに最適!:)
ドアノブ

1
完全なプログラムはどこで求めていますか?「プログラムまたは関数を記述できます...」;)(これはコードゴルフのチャレンジのデフォルトでもありますが、完全
マーティン・エンダー

@Doorknobの提案に追加するために、n+=行にある2組の括弧は不要であり、の両方の出現は==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

2
このprintステートメントのため、言語はPython 2としてマークする必要があります。
mbomb007

@ 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

説明することはあまりありません:この関数は、stepの#位置iでショットガン番号を再帰的に計算しsます。stepのp n位置nの数値を返しますn


ああ、私は私のものを提出する前にあなたの答えを見ませんでした。まったく異なるアプローチがあるようです。
ズガルブ

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
  • {...} ラムダ、x、およびyは、暗黙の1番目と2番目の引数です。
  • $[b;t;f] 三項演算子、それぞれb / t / fを評価します
  • b!a aを法とするb
  • _ floor、除算の結果をintにキャストします
  • % 分割
  • {...}/[x;y] プライム{...}とxを使用してリストyに適用し、f [f [.. f [f [x; y0]; y1]; .. yn-1]; yn]と同等です。
  • |
  • ! iota関数、リスト0からn-1を生成

4

Common 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単一のパラメータとして使用し、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

ここで、^ビット単位のxorを示します。入力が与えられたら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) = 11までスワップするため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

@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を返す名前のない関数が作成されますn。呼び出すには、名前を付けf=n->(...)ます。

例:

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

現在、これは@ Sp3000のすばらしいPython answerに基づいています。ジュリアでこれを行うには、ここで行った方法よりも短い方法が必要なので、すぐに再訪します。いつものように、どんな入力でも歓迎です。



3

CJam、28 27バイト

だからこれは少し恥ずかしい...これを投稿する前に、私はこれを自分でゴルフしてみて、CJamで30バイトになった。既存の答えのどれもまだそれを打ち負かしていません。それまでの間、私はさらに3バイトを削ることができました。コメントには短い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.";



1

ルビー、57 47バイト

これは本質的に、Sp3000のPythonソリューション(xnorの提案による)をRubyに変換したものです。私はおそらくいくつかの場所でそれをゴルフダウンすることができました。

->n{n.downto(2).map{|i|n+=i*(n/i%2-~-n/i%2)};n}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.