ナンバートライアングルフリップ


30

正の整数を三角形にリストし、左から右に反転するとします。番号を指定して、送信先の番号を出力します。これは自己逆マッピングです。

         1                      1         
       2   3                  3   2       
     4   5   6    <--->     6   5   4     
   7   8   9  10         10   9   8   7   
11  12  13  14  15     15  14  13  12  11

これはA038722のn番目の要素で、インデックスが1つあります:

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

このシーケンスは、長さが増加する正の整数の連続したチャンクを逆にします。

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

テストケース:

1 -> 1
2 -> 3
3 -> 2
4 -> 6
14 -> 12
990 -> 947
991 -> 1035
1000 -> 1026
1035 -> 991
1036 -> 1081
12345 -> 12305

リーダーボード:

回答:



7

ゼリー8 7バイト

RṁR€UFi

1バイトを節約してくれた@ErikTheOutgolferに感謝します!

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

使い方

RṁR€UFi  Main link. Argument: n

R        Range; yield [1, ..., n].
  R€     Range each; yield [[1], [1, 2], [1, 2, 3], ..., [1, ..., n]].
 ṁ       Mold the left argument like the right one, yielding
         [[1], [2, 3], [4, 5, 6], ...]. The elements of the left argument are 
         repeated cyclically to fill all n(n+1)/2 positions in the right argument.
    U    Upend; reverse each flat array, yielding [[1], [3, 2], [6, 5, 4], ...].
     F   Flatten, yielding [1, 3, 2, 6, 5, 4, ...].
      i  Index; find the first index of n in the result.

6

アリス、27バイト

.Cアイデアを提供してくれたSp3000に感謝します。

/o
\i@/.2:e2,tE*Y~Z.H2*~.C+

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

説明

三角形の数を使用してこれを計算するより短い方法があると思いますが、これは組み込みの興味深い乱用だと思ったので、別の解決策があります。

基本的な考え方は、アリスの「パック」および「アンパック」ビルトインを利用することです。「パック」、Zまたはは、2つの整数を全単射で単一の整数にマッピングします。「アンパック」、またはY、この全単射を反転し、1つの整数を2に変換します。通常、これを使用して、整数のリストまたはツリーを単一の(大きな)整数に格納し、個々の値を後で復元できます。ただし、この場合、関数を逆の順序で使用して、全単射の性質を機能させることができます。

1つの整数を2つの整数にアンパックすることは、基本的に3つのステップで構成されます。

  1. ℤ→Map(ゼロを含む)を単純な「折りたたみ」でマップします。つまり、負の整数を奇数の自然にマップし、負でない整数を偶数の自然にマップします。
  2. 地図ℕ→ℕ 2使用して、カントールのペアリング機能を。つまり、自然は無限グリッドの対角線に沿って書き込まれ、インデックスを返します。

       ...
    3  9 ...
    2  5 8 ...
    1  2 4 7 ...
    0  0 1 3 6 ...
    
       0 1 2 3
    

    たとえば8、ペアにマッピングされ(1, 2)ます。

  3. 地図2 →ℤ 2、個別に各整数でステップ1の逆を使用して。つまり、奇数の自然は負の整数にマップされ、偶数の自然は非負の整数にマップされます。

2つの整数を1つにパックするには、これらの各ステップを単純に反転します。

これで、Cantorペアリング関数の構造が、必要な三角形を便利にエンコードしていることがわかります(ただし、値は1つずれています)。これらの対角線を逆にするには、x座標とy座標をグリッドに入れ替えるだけです。

残念ながら、上記の3つの手順はすべて1つの組み込みY(またはZ)に統合されているため、ℤ→ℕまたはℕ→ℤマッピングを自分で元に戻す必要があります。ただし、その間、+ →ℤまたはℤ→ℕ +マッピングを直接使用して、テーブル内のオフバイワンエラー処理することにより、数バイトを節約できます。アルゴリズム全体は次のとおりです。

  1. (n / 2)*(-1)n-1を使用して+ Mapをマップします。このマッピングは、アンパック中に暗黙的なexcept→ℕマッピングをキャンセルするように選択されますが、値は1だけ下にシフトします。
  2. 結果を2つの整数にアンパックします。
  3. それらを交換します。
  4. 交換した値を再び単一の整数にパックします。
  5. マップℤ→ℕ + | 2n |を使用 +(n≥0)。繰り返しますが、このマッピングは、値を1だけシフトすることを除いて、パッキング中に暗黙的なℕ→ℤマッピングをキャンセルするように選択されます。

これで、プログラムを見ることができます。

/o
\i@/...

これは、整数の入出力を行う線形演算プログラムのフレームワークです。

.    Duplicate the input.
2:   Halve it.
e    Push -1.
2,   Pull up the other copy of the input.
t    Decrement.
E    Raise -1 to this power.
*    Multiply. We've now computed (n/2) * (-1)^(n-1).
Y    Unpack.
~    Swap.
Z    Pack.
.H   Duplicate the result and take its absolute value.
2*   Double.
~    Swap with other copy.
.C   Compute k-choose-k. That's 1 for k ≥ 0 and 0 for k < 0.
+    Add. We've now computed |2n| + (n≥0).



4

オクターブ71 68バイト

Conor O'Brienのおかげで3バイト節約されました。

x=triu(ones(n=input('')));x(~~x)=1:nnz(x);disp(nonzeros(flip(x))(n))

メモリの制限により、これは大きな入力では機能しません。

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

説明

入力を検討してくださいn = 4。コードは最初にマトリックスを構築します

 1     1     1     1
 0     1     1     1
 0     0     1     1
 0     0     0     1

そして、それはによって(そして全体で、ダウン)列優先順にゼロ以外のエントリを置き換え123...:

 1     2     4     7
 0     3     5     8
 0     0     6     9
 0     0     0    10

次に、マトリックスを垂直に反転します。

 0     0     0    10
 0     0     6     9
 0     3     5     8
 1     2     4     7

最後に、n列優先順で0番目の非ゼロ値を取ります6。この場合はです。


1
@ rahnema1それeは天才です!他の非常に良い提案とともに、間違いなくそれを回答として投稿すべきです。についてはans =、それが有効かどうかは
わかり

4

Haskell、31バイト

r=round
f n=r(sqrt$2*n)^2-r n+1

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

この答えは単に式を使用しています。ここでは最もおもしろい答えではありませんが、偶然にも最もゴルフ好きです。

Haskell38 36 34バイト

x!y|x<=y=1-x|v<-y+1=v+(x-y)!v
(!0)

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

(!0) 私たちが関係しているポイントフリー関数です。

説明

この答えにとても満足していると言って始めましょう。

ここでの基本的な考え方は、入力よりも小さい最大の三角形の数を削除すると、それを逆にして三角形の数を追加し直すことができるということです。だから我々は、演算子を定義し!!私たちの定期的な入力を受け取りx、それはまた、余分な数になりますyy増加する三角形の数のサイズを追跡します。x>y再帰したい場合は、1ずつ減らしxy増やしyます。計算(x-y)!(y+1)して追加y+1します。場合x<=y我々はベースケースに達している、逆にx我々は返す三角形の行での配置を1-x

Haskell、54バイト

f x|u<-div(x^2-x)2=[u+x,u+x-1..u+1]
(!!)$0:(>>=)[1..]f

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

(!!)$0:(>>=)[1..]f 無点関数です

説明

私たちが最初に懸念しているのはf、逆方向に3番目の三角形のth行を取得して返すf関数です。これは、最初にnd三角番号を計算し、それをに割り当てることで行います。。次に、リストを返します。は、行の最初の三角形の数であり、それよりも1つ小さく、行の2番目の数は最後の三角形の数、したがって行の最後の数よりも1大きくなります。xxx-1uu<-div(x^2-x)2[u+x,u+x-1..u+1]u+xxu+x-1u+1

fリストを作成したら(>>=)[1..]f、三角形を平坦化します。前にゼロを追加し0:て、答えが1で相殺されないようにし、インデックス関数に提供します(!!)

Haskell、56バイト

f 0=[0]
f x|u<-f(x-1)!!0=[u+x,u+x-1..u+1]
(!!)$[0..]>>=f

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

これは2バイト長くなりますが、私の意見ではもう少しエレガントです。


3

C(gcc)、48バイト

k,j,l;f(n){for(k=j=0;k<n;)l=k,k+=++j;n=1+k-n+l;}

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

おそらく次善策ですが、私はこれにかなり満足しています。という事実を使用します

NTF N = T N + A057944N-N + 1

(式を正しく書き留めていれば、つまり。)


returnを呼び出していませんが、戻り値が使用されます。それは未定義の動作です。
2501年

@ 2501プログラムが機能する限り、許可されます。また、関数の最初の引数に書き込むことは、値を返すことと同じです。
コナーオブライエン

また、関数の最初の引数に書き込むことは、値を返すことと同じです。C言語にはそのようなものは存在しません。標準では、返されない関数から返された値を使用することは、未定義の動作であると明示的に規定されています。
2501

1
@ 2501 C仕様のC環境(gcc)を混乱させているようです。はい、C言語/仕様では未定義と呼ばれていますが、そのように実装されています。したがって、「同等」と言うとき、私はgccや他のほとんどのコンパイラによるCの実装について最も明確に言及しています。PPCGでは、「完璧な」コードを記述しません。多くのコードはゴルフのために仕様に反します。私が言ったように、それが機能する限り、それは有効な答えです。
コナーオブライエン

@ 2501メタサイトの記事、特にこの記事を読むことをお勧めします。
コナーオブライエン

2

05AB1E、30バイト

U1V[YLO>X›iYLOX-UY<LO>X+,q}Y>V

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


「何?Unicodeのない05AB1Eの答えは?」しかし、その後、1つの非ASCII文字がそれを台無しにします...:P最初の良い答えは、プログラミングパズルとコードゴルフへようこそ!
clismique

@ Qwerp-Derpありがとうございます!私はこの言語を習い始めたばかりなので、答えがそんなに悪かったのは驚くことではありません。
エドゥアルドヘフェル

2

、6バイト

!ṁ↔´CN

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

説明

!ṁ↔´CN  -- implicit input N, for example: 4
   ´ N  -- duplicate the natural numbers:
           [1,2,3,…] [1,2,3,…]
    C   -- cut the second argument into sizes of the first:
           [[1],[2,3],[4,5,6],[7,8,9,10],…]
 ṁ↔     -- map reverse and flatten:
           [1,3,2,6,5,4,10,9,8,7,15,…
!       -- index into that list:
           6

2

tinylisp、78バイト

(d _(q((R N T)(i(l T N)(_(a R 1)N(a T R))(a 2(a T(s T(a N R
(d f(q((N)(_ 2 N 1

関数を定義します fマッピングを実行を。オンラインでお試しください!

非ゴルフ

入力数以上の最小の三角形の数と、その数が入っている三角形の行を見つけます。これらから、数の反転バージョンを計算できます。

  • 現在の三角形の数がNより小さい場合、三角形の次の行に再帰します。(計算を簡単にするために、一番上の行を行2として扱います。)
  • それ以外の場合、Nの反転バージョンは(TN)+(TR)+2です。

メイン関数flipは、単純に_flip一番上の行からヘルパー関数を呼び出します。

(load library)

(def _flip
 (lambda (Num Row Triangular)
  (if (less? Triangular Num)
   (_flip Num (inc Row) (+ Triangular Row))
   (+ 2
    (- Triangular Num)
    (- Triangular Row))))))

(def flip
 (lambda (Num) (_flip Num 2 1)))

1

05AB1E、9バイト

·LD£í˜¹<è

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

説明

·L          # push range [1 ... 2n]
  D         # duplicate
   £        # split the first list into pieces with size dependent on the second list
    í       # reverse each sublist
     ˜      # flatten
      ¹<è   # get the element at index <input>-1

残念ながら、配列のフラット化では、大きなリストをうまく処理できません。
1バイトのコストで、OEISにある数式を使用して・t2z +ïn¹->を実行できます。floor(sqrt(2*n)+1/2)^2 - n + 1


1

バッチ、70バイト

@set/ai=%2+1,j=%3+i
@if %j% lss %1 %0 %1 %i% %j%
@cmd/cset/ai*i+1-%1

ループを使用して、少なくともと同じ大きさの三角数のインデックスを見つけますn




0

APL(Dyalog)、27バイト

同じバイト数で2つのソリューションがあります。

電車:

⊢⊃⊃∘(,/{⌽(+/⍳⍵-1)+⍳⍵}¨∘⍳)

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

そして、dfn:

{⍵⊃⊃((⍳⍵),.{1+⍵-⍳⍺}+\⍳⍵)}

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

これらのソリューションはどちらも、最初に反転した三角形を作成し、次に引数で指定されたインデックスで要素を抽出します(1-based)。


0

J、25バイト

3 :'>:y-~*:>.-:<:%:>:8*y'

説明として、を検討してくださいf(n) = n(n+1)/2f(r)は、行を指定すると、ミラーリングされた三角形のth番目の行のr左端の番号を返します。今、考えてみてください。、インデックスを指定すると、インデックスiが見つかった行を返します。次に、インデックスnが見つかった行の左端の番号を返します。そう、rg(n) = ceiling[f⁻¹(n)]g(i)if(g(n))h(n) = f(g(n)) - (n - f(g(n)-1)) + 1上記の問題への答えです。

簡素化、私たちは得る h(n) = [g(n)]² - n + 1 = ceiling[(-1 + sqrt(1 + 8n))/2]² - n + 1ます。

@Arnauldの式の外観から、次のように見えます。

ceiling[(-1 + sqrt(1 + 8n))/2] = floor[1/2 + sqrt(2n)]


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