新しい注文#6:イースターエッグ


13

はじめに(無視してもよい)

すべての正の整数を通常の順序(1、2、3、...)に配置するのは少し退屈ですよね?したがって、すべての正の整数の順列(再編成)に関する一連の課題があります。これは、このシリーズの6番目の課題です(1番目2番目3番目4番目5番目の課題へのリンク)。

このチャレンジには、イースターのテーマがあります(イースターだからです)。私はこの非常に装飾された(そして私の個人的な意見ではかなりugい)ガチョウの卵からインスピレーションを得ました。

装飾されたガチョウの卵

すべての正の整数が反時計回りのスパイラルに配置されているウラムスパイラルを思い出しました。このスパイラルには素数に関連する興味深い機能がいくつかありますが、それはこの課題には関係ありません。

ウラムスパイラル

Ulamスパイラルの数値を取得し、1から始まる時計回りに回転するスパイラルですべての整数をトレースすると、この課題の正の整数の順列に到達します。このようにして、次のようになります。

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

両方のスパイラルを描画する場合は、ある種の無限のメッシュ(卵殻)スパイラルが得られます(そこのNew Orderリファレンスに注意してください)。

このシーケンスは、OEISの番号A090861にあります。これは「純粋なシーケンス」チャレンジであるため、タスクは与えられたを入力として出力することです。ここではA090861です。a(n)na(n)

仕事

整数入力所与、出力整数形式であるA090861na(n)a(n)

注:ここでは、1ベースのインデックス付けが想定されています。0から始まるインデックスを使用できるためなどa(0)=1;a(1)=6

テストケース

Input | Output
---------------
1     |  1
5     |  3
20    |  10
50    |  72
78    |  76
123   |  155
1234  |  1324
3000  |  2996
9999  |  9903
29890 |  29796

ルール

  • 入力と出力は整数です。
  • プログラムは、少なくとも1〜32767の範囲の入力をサポートする必要があります。
  • 無効な入力(0、フロート、文字列、負の値など)は、予期しない出力、エラー、または(未)定義された動作につながる可能性があります。
  • デフォルトのI / Oルールが適用されます。
  • デフォルトの抜け穴は禁止されています。
  • これはであるため、バイト単位の最短回答が優先されます

回答:


12

ゼリー 16 14 11 10 9  8 バイト

-1リンのおかげで(MOD-2;論理否定、自己に入れる:Ḃ¬+- >ビット単位のOR 1: |1

|1×r)ẎQi

整数を受け入れる単項リンク。n整数を生成しa(n)ます。

オンラインでお試しください!(レイヤーされるため、非常に非効率的です)n2

11バイトバージョンでは½‘|1×rƲ€ẎQi、30秒未満で最大のテストケースを除くすべてが完了します。TIOで試してください。これにより、使用するレイヤーが制限されます。n+12

どうやって?

順列は、長さの逆スライスで自然数を取ることです[1,5,3,11,5,17,7,23,9,29,11,35,13,...]-モジュロ6に一致する正の整数が点在する正の奇数の整数、すなわち[1, 2*3-1, 3, 4*3-1, 5, 6*3-1, 7, 8*3-1, 9, ...]

これは、これらのスライスの長さの累積和(つまり、各スライスの最大値)の逆の範囲[1..x]を連結して重複排除することと同じです。これは、偶数の整数を掛けた奇数の整数に乗算します。x[1,6,9,20,25,42,49,72,81,110,121,156,169,...][1*1, 2*3, 3*3, 4*5, 5*5, 6*7, 7*7,...]

差はすべて1より大きいので、範囲を[x..k]直接構築することで1バイト(反転)を保存できkます。ここで、スライスの1インデックス付きインデックスです。

この構造により、順列は自己共役順列です。つまり、であることがわかっているため、(1-indexed)index ()で値を見つけるのではなく、実際に()の最初の出現の(1-indexed)インデックスを取得します。P(n)=vP(v)=nn|1×r)ẎQị@n|1×r)ẎQi

|1×r)ẎQi - Link: integer, n       e.g. 10
    )    - for each k in [1..n]:  vs = [ 1, 2, 3, 4, 5, 6, 7, 8, 9,10]
|1       -   bitwise-OR (k) with 1     [ 1, 3, 3, 5, 5, 7, 7, 9, 9,11]
  ×      -   multiply (by k)           [ 1, 6, 9,20,25,42,49,72,81,110]
   r     -   inclusive range (to k)    [[1],[6..2],[9..3],[20..4],...,[110..10]]
     Ẏ   - tighten                     [1,6,5,4,3,2,9,8,7,6,5,4,3,20,...,4,......,110,...,10]
      Q  - de-duplicate                [1,6,5,4,3,2,9,8,7,20,...,10,......,110,...82]
       i - first index with value (n)  20

2
非常に素晴らしい。そして、あなたはMATLの答えを超えました!
agtoever

1
今縛ら... :-)
ルイスMendo

@LuisMendo私はちょうどここでこっそり何かをして、1バイトを節約できることに気付きました:)
ジョナサンアラン

1
@JonathanAllan Aww。それは1つの賛成に値する:-)
ルイス・メンド

1
@Lynn私は実際には異なる9バイトに更新しています。あなたのものは8になりそうです!
ジョナサンアラン

6

JavaScript(ES7)、 46 45  41バイト

0インデックス付き。

n=>((x=n**.5+1&~1)*2-(n<x*x+x)*4+3)*x+1-n

オンラインでお試しください!

どうやって?

これは、A090861のサンプルプログラムで使用される1インデックス付きの式に基づいています。

xn0

xn=n1+12

オンラインでお試しください!

kn62

kn={2if n4xn2+2xn6さもないと

オンラインでお試しください!

an

an=8バツn2+knバツn+2n

オンラインでお試しください!

次のように翻訳できます:

n=>8*(x=(n-1)**.5+1>>1)*x+(n<=4*x*x+2*x?-2:6)*x+2-n

インデックスを0にすると、すぐに5バイトが節約されます。

n=>8*(x=n**.5+1>>1)*x+(n<4*x*x+2*x?-2:6)*x+1-n

数式は、次を使用してさらに簡略化できます。

xn=2×n+12

次のように表現できます。

x=n**.5+1&~1

につながる:

n=>2*(x=n**.5+1&~1)*x+(n<x*x+x?-1:3)*x+1-n

そして最後に:

n=>((x=n**.5+1&~1)*2-(n<x*x+x)*4+3)*x+1-n




3

パイソン3.8、104の 74 65 60 57バイト

lambda n:(-2,6)[n>4*(x:=(n**.5+1)//2)*x+2*x]*x+2+~n+8*x*x

編集:74バイトから57バイトに変更してくれたJohnathan Allanに感謝します!

このソリューションは、0ベースのインデックスを使用します。


1
保存39、輸入を避け、いくつかの冗長な括弧を削除し、使用して>の代わりに、<=x*xの代わりにx**2...そうのように:def f(n):x=((n-1)**.5+1)//2;return 8*x**2+(-2,6)[n>4*x*x+2*x]*x+2-n... TIO
ジョナサン・アラン

驚くばかり!編集内容を組み込みます。コメントを見る前にいくつかの変更を加えて、74バイトに減らしました。あなたがフロートを返すことは重要ですか?私は...ないと仮定
Kapocsi

整数の浮動小数点表現は問題ないはずです。Python 3.8割り当てを使用してさらに保存します...編集:インデックスをゼロにします
ジョナサンアラン

とてもかっこいい。さらに直接編集を行ってください!
カポクシ


2

Befunge、67 57バイト

このソリューションは、入力値の0ベースのインデックス付けを想定しています。

p&v-*8p00:+1g00:<
0:<@.-\+1*g00+*<|`
0g6*\`!8*2+00g4^>$:0

オンラインでお試しください!

説明

入力nがループで見つかる「半径」を計算することから始めます。

radius = 0
while n > 0
  radius += 1
  n -= radius*8

ループの最後で、nの以前の値は、その半径でのスパイラルへのオフセットです。

offset = n + radius*8

次に、次のようにしてスパイラルの上部または下部のどちらにいるかを判断できます。

bottom = offset >= radius*6

そして、これらすべての詳細が得られると、スパイラル値は次のように計算されます。

value = ((bottom?10:2) + 4*radius)*radius + 1 - offset

半径は「変数」として保存する必要がある唯一の値であり、Befunge-93では最大値127に制限されているため、このアルゴリズムは最大65024の入力を処理できます。


1

Japt、15バイト

Port of JonathanのJellyソリューション。1インデックス付き。

gUòȲ+X*v)õÃcÔâ

それを試してみてください

gUòȲ+X*v)õÃcÔâ     :Implicit input of integer U
g                   :Index into
 Uò                 :  Range [0,U]
   È                :  Map each X
    ²               :    Square X
     +X*            :    Add X multiplied by
        v           :    1 if X is divisible by 2, 0 otherwise
         )          :    Group result
          õ         :    Range [1,result]
           Ã        :  End map
            c       :  Flatten
             Ô      :    After reversing each
              â     :  Deduplicate

私はジョナサンにそれx+(1-x%2)x|1(ジェリーに1バイト節約する)と言ったところですが、この答えも恩恵を受けることができると思います。
リン

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.