グリッドを三角形に分割する


18

ゴール

この課題の目標は、次の機能を生成することです nn X 1グリッドを三角形に分割する方法の数を計算する。三角形のすべての頂点がグリッドポイント上にあります。

たとえば、2 x 1グリッドを分割するには14の方法があるためf(2) = 14、次のパーティションを使用して2 x 1のパーティション して、それぞれ2、2、2、2、4、および2つの異なる方向に分割します。

得点

これはなので、最短のコードが優先されます。


10
追加のテストケースがあれば有益であるため、提出物が正しいことを確認できます。
AdmBorkBork

8
非縮退三角形を指定することもできます。
アーナウルド

1
この解釈を反映するために、OEISシーケンスA051708を編集しました。
ピーターカギー

回答:


2

05AB1E、13 バイト

·LÉœÙεÅγo;P}O

@BubblerのJelly回答のポート。

置換が組み込まれているため、非常に遅い。

オンラインそれを試してみたり、最初の4つの入力を確認します

説明:

·                # Double the (implicit) input
 L               # Create a list in the range [1, doubled_input]
  É              # Check for each if they're odd (1 if truthy, 0 is falsey)
                 # We now have a list of n 0s and n 1s (n being the input)
   œ             # Get all permutations of that list
    Ù            # Only leave the unique permutations
     ε     }     # Map each permutation to:
      Åγ         #  Run-length encode the current value (short for `γ€g`)
        o        #  Take 2 to the power for each
         ;       #  Halve each
          P      #  Take the product of the mapped permutation
            O    # Sum all mapped values together (and output implicitly)

19

ハスケル60 55 54 52バイト

多くの例を描いてプログラミングした後、これはルークの問題と同じであることが私に思い浮かびました:

上の(n+1)×(n+1)のチェス盤から行くにはルークのためにどのように多くの方法がある(0,0)(n,n)だけ右に移動することにより+(1,0)またはアップ+(0,1)

基本的に、1×nグリッドの一番上と一番下の行があります。次に、非水平線を入力する必要があります。各三角形には、2本の非水平線が必要です。側面の1つが上部の線の一部であるか下部の線の一部であるかは、ルークの問題で進む方向と長さに対応します。これはOEIS A051708です。この対応の例として、次の例を検討してください。ここで、上の行は上向きの動きに対応し、下の行は右向きの動きに対応しています。

-6バイトを@PeterTaylorに、-2バイトを@PostLeftGarfHunterに感謝します!

b 0=1
b 1=2
b n=div((10*n-6)*b(n-1)-9*(n-2)*b(n-2))n

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


最初のいくつかの値で検索して、OEISシーケンスを見つけました。一致する理由の説明。この代替組み合わせ解釈についてコメントを追加するために編集しますか?そうでない場合、私は可能性があります。
ピーターテイラー

ところで、正しい答えはであるため、インデックス作成を調整する必要がありますA051708(n+1)。だから私は最初の正しいを投稿しました答え :-P
ピーターテイラー

私は、上と下のエッジが上または右の動きに対応する三角形を作成することで、ルークが三角形にマップされると考えていますか?
ニール

@PeterTaylorくそー、私の間違いを指摘してくれてありがとう:)
flawr

5
@Neilグラフィカルな説明を追加しました。
flawr

8

Haskell、42バイト

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

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

2つ以上の変数を再帰するかなり直接的な実装。

このソリューションを取得する方法は次のとおりです。直接再帰式を実装するコードから始めます。

54バイト

0%0=1
a%b=sum$map(a%)[0..b-1]++map(b%)[0..a-1]
f n=n%n

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

を使用して flawrのルークの移動の解釈するとa%bルークをから(a,b)(0,0)移動するパスの数は、移動だけで座標が減少します。最初の動きは減少aまたは減少しますb、他のは同じに保たれるため、再帰式になります。

49バイト

a?b=sum$map(a%)[0..b-1]
0%0=1
a%b=a?b+b?a
f n=n%n

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

私たちは中に繰り返しを避けることができるmap(a%)[0..b-1]++map(b%)[0..a-1]二つの半分が同じであることを注意することによってa、およびb交換ます。補助コールはa?b最初の動きが減少する経路をカウントしa、そのためb?a最初の移動が減少する場合、それらをカウントしますb。これらは一般的に異なり、に追加されa%bます。

の合計はa?b、リストの内包表記として書くこともできa?b=sum[a%i|i<-[0..b-1]]ます。

42バイト

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

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

最後に、次の%点で再帰を取り除きます。?置き換えa%ia?i+i?a再帰呼び出しで。

新しいベースケースでは、これが原因?の出力与えるのダブルそのために?49バイトのバージョンでは、とのことから0?0=1、私たちは持っているでしょう0%0=0?0+0?0=2。これによりf n=n?n、他のユーザーが行う必要のある半分を使わずにdefine を使用できます。


49バイトのソリューションでは、私の答えと同じ再帰を使用しますが、42バイトの解決策はまだわかりません。説明がいいでしょう。
ピーターテイラー

以前のプログラムの1つで同じアプローチを使用したと思います。アイデアは、右から左への非水平線を生成することによってすべてのパーティションを生成(またはカウント)することです。垂直線から始めます。その後、再帰することができます。前の行の終了ノードの1つを取得し、この行のすべての前のノードの左にある反対の水平線上のノードに接続します。
-flawr

オペレーターa%bは、0,1,...,a一番上の行のノードと一番下の行のノードを使用して、パーティションの数をカウントし0,1,..,bます。演算子a?bは、a最下位ノードbが既に使用されている場合に最上位ノードから新しい行を追加できる方法の数をカウントします。(aすべてのノードに接続できますが、それらのノード[0,1,...,b-1]ごとに再帰する必要があります。)
flawr

@flawr、これは49バイトです。それはだ?、私はしません42バイトの1の、そしてどのような特に好奇心旺盛なのは、それは対称ではないということです。
ピーターテイラー

@PeterTaylor混乱して申し訳ありませんが、どういうわけか2つのソリューションを混同しました。2つのソリューションを互いに簡単に変換できると思います。最初のステップmap...ではリスト内包表記に置き換えることができ、2番目のステップでは次の定義をプラグインするだけです%a?b=sum$map(a%)[0..b-1], a%b=a?b+b?a a?b=sum[a%i|i<-[0..b-1]], a%b=a?b+b?a a?b=sum[a?i+i?a|i<-[0..b-1]]
-flawr

7

CJam(24バイト)

{2,*e!{e`0f=:(1b2\#}%1b}

オンラインデモ

これは、バブラーのアプローチを使用して、n 0とn1のしています。

解剖

{         e# Define a block
  2,*     e#   Given input n, create an array of n 0s and n 1s
  e!      e#   Generate all permutations of that array
  {       e#   Map:
    e`    e#     Run-length encode
    0f=:( e#     Extract just the lengths and decrement them
    1b    e#     Sum
    2\#   e#     Raise 2 to the power of that sum
  }%
  1b      e#  Sum the mapped values
}

代替アプローチ(28バイト)

{_1aa{_2$,f{j}@@,f{j}+1b}2j}

オンラインデモ

解剖

三角形にはすべて、1つの水平エッジと、水平線をリンクする2つのエッジがあります。2つのx座標のタプルで非水平エッジにラベルを付け、辞書式に並べ替えます。次に、最初のエッジは(0,0)で、最後のエッジは(n,n)で、2つの連続したエッジは2つの位置の1つで正確に異なります。これにより、単純な再帰が作成されます。これは、メモした再帰演算子を使用して実装しましたj

{            e# Define a block
  _          e#   Duplicate the argument to get n n
  1aa        e#   Base case for recursion: 0 0 => 1
  {          e#   Recursive body taking args a b
    _2$,f{j} e#     Recurse on 0 b up to a-1 b
    @@,f{j}  e#     Recurse on a 0 up to a b-1
    +1b      e#     Combine and sum
  }2j        e#   Memoised recursion with 2 args
}

注意

fjCJamでサポートを受けたいと思ったのはこれが初めてではありません。ここでは、スコアも24バイトになります。おそらく、パッチを作成する必要があります...


ええ、私はあなたを10秒で打ちました、私はこれまでに近かったとは思いません:)
flawr

@flawr、解剖を書く前に投稿を検討しましたが、すぐにノックアウトする時間があると思いました。それから「新しい答え」を見たので、自分で書いた解剖を削除し、投稿し、編集しました。
ピーターテイラー

1
ところで-5バイトありがとう:D
flawr

4

ゼリー15 14バイト

Ø.xŒ!QŒɠ€’§2*S

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

ピーターテイラーのコメントに基づく-1バイト。

結果の数式ではなく、flawrのイラストを直接使用します。

使い方

Ø.xŒ!QŒɠ€’§2*S    Main link (monad). Input: positive integer N.
Ø.x               Make an array containing N zeros and ones
   Œ!Q            All unique permutations
      Œɠ€         Run-length encode on each permutation
         ’§       Decrement and sum each
           2*S    Raise to power of 2 and sum

四角いグリッド上のすべての可能なルートを取ります。ルークとしてLユニットを一方向に動かす方法の数は2**(L-1)です。これをすべてのルートに適用し、各ルートを横断する方法の数を合計します。


いいアプローチ。CJamに移植すると、長さをデクリメントし、合計し、2を合計するのが短くなりました。2を長さに増やし、半分にしてから乗算するのではなく。バイトを節約できるかどうかわからない。
ピーターテイラー

3

44 31バイト

取り消し線44はまだ通常の44です

F⊕θ«≔⟦⟧ηF⊕θ⊞ηΣ∨⁺ηEυ§λκ¹⊞υη»I⊟⊟υ

オンラインでお試しください!説明:反対側の長さの台形m,nをすべて整数オフセットにある三角形に分割する方法の数を計算することによって機能します。これは、単にn問題のサイズの長方形の一般的なケースです。パーティションの数は、すべての辺m,0..n-1およびのパーティション数の合計として再帰的に与えられn,0..m-1ます。これは、ルークの一般化された問題、OEIS A035002と同等です。このコードは、以前に計算された値0,0n,n使用するまでの作業パーティションの数を単純に計算します。

F⊕θ«

行をループします0..n

≔⟦⟧η

空の行から始めます。

F⊕θ

行の列をループします0..n

⊞ηΣ∨⁺ηEυ§λκ¹

これまでの行と現在の列の前の行の値を取得し、合計を現在の行に追加します。ただし、値がまったくない場合1は、合計の代わりに置き換えます。

⊞υη»

これまでに、完成した行を行のリストに追加します。

I⊟⊟υ

計算された最終値を出力します。




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