フィボナッチドミノタイル


11

あります古典的な組み合わせの結果タイルに、いくつかの方法があること2*nによって、ストリップ1*2ドミノがn 番目のフィボナッチ数は。あなたの目標は、nこれらの8つのタイルのようにダッシュと垂直線で描かれた特定のすべてのタイルを印刷することですn=5

|————
|————

——|——
——|——

|||——
|||——

————|
————|

||——|
||——|

|——||
|——||

——|||
——|||

|||||
|||||

n入力として必要な出力を出力するプログラムまたは名前付き関数を提供します。最少バイトが勝ちます。

入力

n1および10STDINまたは機能入力を介して包括的な。

出力

2*nストリップの可能なドミノタイルをすべて水平に描画して印刷します。タイルの順序は任意ですが、それぞれ1回だけ表示される必要があります。これらは空白行で区切る必要があります。

垂直ドミノは2つの垂直バー(|)で構成され、水平ドミノは2つのダッシュ()で構成されています。-ASCIIのままにするために、ダッシュの代わりにハイフン()を使用できます。

印刷出力が同じように見える限り、空白で何でもできます。


最後のタイリングの後の余分な改行は、空白のあるものに該当しますか?
デニス14

@Dennisはい、余分な空白行で問題ありません。
xnor 14

同じ問題を解決するための非常に多くの異なるアプローチを見て、本当に驚いています。あなたはそれを期待しましたか?
レベルリバーセント14

@steveverrillいいえ、私はまったくしませんでした、そしてその多様性を見て喜んでいます!そして、あなたのものは予想外のケーキを取る。私が使用したほとんどのソリューションが使用されたように、私はほとんどフィボナッチスタイルの再帰を念頭に置いていました。私は有効であるためにフィルタリングし、そして私がやった限り、私はそれがの文字列をフィルタリングすることでしょうが期待していなかった——|デニスのような長さではなく、長さ- nの文字列|によってフィルタリングペアで登場します。後者の場合、生成された文字列に対する正規表現または文字列操作(s.split('——)など)であり、あなたのような算術的アプローチではないことを期待しています。
xnor 14

「1x2ドミノ」は冗長だと思います。
SuperJedi224

回答:


5

C、106

ゴルフバージョン

f(n){
  for(int i,h=n*2<<n;h--;(i/3|i/3*2)-i||(putchar(i>>h%n&1?45:124),h%n||puts(h%(n*2)?"":"\n")))
    i=h/2/n;
}

元のバージョン

i,j,n;
main(){
  scanf("%d",&n);
  for(i=1<<n;i--;)if((i/3|i/3*2)==i){
    for(j=1<<n;j/=2;)printf("%c",i&j?'-':'|');puts("");
    for(j=1<<n;j/=2;)printf("%c",i&j?'-':'|');puts("\n");
  }
}

使い方

変数i1<<n-10から0 まで実行され、n数字の可能なすべての2進数を生成します。0はをエンコードし|、1はをエンコードし-ます。ペアで1を含む数値に興味があります。明らかに、そのような数値は3で割り切れます。

数値を3で除算すると、結果に2を掛けてそれ自体に加算することで元の数値を回復できます(実質的に3倍になります)。ほとんどの数値はキャリーを必要としますが、キャリーは不要なので、これらの場合にのみ、ORを加算の代わりに使用できます。これは、式i/3|i/3*2がの元の値を返す唯一のものであるため、対象の数をテストするために使用されますi。以下の例を参照してください。

1111= 15 ---> 0101= 5 ---> 1111= 15(有効、0101|1010== 0101+1010

1001= 9 ---> 0011= 3 ---> 0111= 7(無効、0011|0110!= 0011+0110

テスト値は常に元の値以下です。3の倍数ではない数値も、3で割って3で乗算すると元の数値よりも小さい数値を返すため、テストではこれらの数値に対しても望ましいFALSEが返されます。

元のバージョンでは、いくつかのループjが使用され、ビットをスキャンしiて出力を生成します。ゴルフバージョンでは、単一のforループが使用されます。このループでは、0から0 hまでのすべての数値が実行されます。の(n*2)*(1<<n)-1iはによって生成されh/2/nます。jから同等の量が取得されるため、変数は使用されなくなりましたh%n。を使用するとn*2、同じループから両方の行をputs印刷できます。行の最後に1行または2行の改行を印刷するために、ステートメント内で気の利いた多重化を行います。

この肉はの増分位置にあることに注意してくださいfor()、ブラケット、従って実行されますi=h/2/h

サンプル出力n = 6:

$ ./a
6
------
------

----||
----||

--|--|
--|--|

--||--
--||--

--||||
--||||

|----|
|----|

|--|--
|--|--

|--|||
|--|||

||----
||----

||--||
||--||

|||--|
|||--|

||||--
||||--

||||||
||||||

i/3|i/3*2トリックは独創的です!文法の算術式を期待していませんでした。
xnor 14

3

CJam、33 27バイト

LN{_'|f+@"——"f++}ri*\;{_N}/

6バイトのゴルフをしてくれた@ jimmy23013に感謝します!

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

バックグラウンド

これは、再帰アルゴリズムの反復実装です。

用可能なタイリングnが可能タイリングに垂直ドミノを添加することによって得ることができる1 - n個の可能なタイリングおよび二つの水平ドミノN - 2

このように、nのタイル数は、n-1n-2のタイル数の合計、つまりn 番目のフィボナッチ数です。

使い方

LN                                " A:= [''] B:= ['\n']                         ";
  {             }ri*              " Repeat int(input()) times:                  ";
   _'|f+                          "   C = copy(B); for T ∊ C: T += '|'          ";
              @                   "   Swap A and B.                             ";
               "——"f+             "   for T ∊ B: T += "——"                      ";
                     +            "   B = C + B                                 ";
                        \;        " Discard A.                                  ";
                          {_N}/   " for T ∊ B: print T, T + '\n'                ";

実行例

$ alias cjam='java -jar cjam-0.6.2.jar'

$ cjam domino.cjam <<< 3
|||
|||

——|
——|

|——
|——

$ for i in {1..10}; do echo $[$(cjam domino.cjam <<< $i | wc -l) / 3]; done1
2
3
5
8
13
21
34
55
89

LNli{_'|f\@"——"f\+2/}*\;{_N}/
jimmy23013

f\0.6.2にはまだ実装されていませんでしたが、アプローチを組み合わせることができました。ありがとう!
デニス

2

Haskell、89バイト

f(-1)=[]
f 0=[""]
f n=map('|':)(f$n-1)++map("--"++)(f$n-2)
g=unlines.(>>= \x->[x,x,""]).f

fは、数を指定すると、長さnの可能なすべてのフィボナッチタイリングの1行のリストを返す関数です。すべてのタイリングの両方の行が同じであるため、1行を返すことは問題ではありません。

fn-1and を再帰的に呼び出し、n-2andを(それぞれ)文字列に追加すること"|"で機能"--"します。

g質問に答える関数です。基本的にf入力を呼び出し、すべての文字列を2倍にして2行を表示し、それらをすべて改行で結合します。

出力例:

*Main> putStrLn $ g 5
|||||
|||||

|||--
|||--

||--|
||--|

|--||
|--||

|----
|----

--|||
--|||

--|--
--|--

----|
----|

2

CJam、42 37バイト

3li:L#,{3b"——|"2/f=s}%{,L=},_&{N+_N}/

質問ではダッシュをASCIIハイフンに置き換えることができるため、ダッシュを1バイトとしてカウントしました。

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

使い方

2×Lのすべての可能なタイルを取得するには、すべての非負整数I <3 Lを反復処理し、基数3の偶数桁を水平ドミノに、奇数桁を垂直ドミノに対応させます。

各以来、私が持っているLベース3における以下の数字を、これはカバーのすべての可能な方法生成する2×Lのストリップ。残っているのは、2×Lよりも大きいまたは小さいカバーを除外し、残りのカバーを印刷することだけです。

3li:L#,      " Read an integer L from STDIN and push A := [ 0 1 ... (3 ** N - 1) ].       ";
{            " For each integer I in A:                                                   ";
  3b         " Push B, the array of I's base 3 digits.                                    ";
  "——|"2/    " Push S := [ '——' '|' ].                                                    ";
  f=         " Replace each D in B with S[D % 2] (the modulus is implicit).               ";
  s          " Flatten B.                                                                 ";
}%           " Collect the result in an array R.                                          ";
{,L=},       " Filter R so it contains only strings of length L.                          ";
_&           " Intersect R with itself to remove duplicates.                              ";
{N+_N}/      " For each string T in B, push (T . '\n') twice, followed by '\n'.           ";

実行例

$ cjam domino.cjam <<< 3
|——
|——

——|
——|

|||
|||

$ for i in {1..10}; do echo $[$(cjam domino.cjam <<< $i | wc -l) / 3]; done
1
2
3
5
8
13
21
34
55
89

涼しい。なぜベース3の代わりにedc65のようなベース2を使用しなかったのか不思議に思っています。これにより、重複を避けることができます。先行ゼロはおそらくステップで切り捨てられるためだと思い3bます。そうですか?
レベルリバーセント14

1
@steveverrill:はい、それがまさにその理由です。そのままでは、先行ゼロはドミノがまったくないことに対応します。しかし、重複がないと、3つのブロックを1つのブロックに置き換えることができます。これについてもう少し考えなければなりません。
デニス14

@steveverrill:私はベース2を動作させることができませんでしたが、再帰的なアプローチはさらに短くなるようです。
デニス14

2

JavaScript(E6)102

0-> '-'および1-> '|'のビットシーケンスから構成を生成します。

F=n=>{
  for(i=0;(j=++i)<2<<n;s.length==1+n&&console.log('\n'+s+s))
    for(s='\n';j>1;j>>=1)s+=j&1?'|':'--';
}

firefox / firebugコンソールでテストする

F(5)

出力

|----
|----

--|--
--|--

----|
----|

|||--
|||--

||--|
||--|

|--||
|--||

--|||
--|||

|||||
|||||

1

Haskell:109バイト

これは、フィボナッチ数列を遅延計算するための有名なHaskellワンライナーの翻訳です:

b=map.map.(++)
w=zipWith
z=w(++)
s=["\n"]:["|\n"]:z(b"--"s)(b"|"$tail s)
f=sequence_.map putStrLn.(w z s s!!)

タイル張り文字列の主なシーケンス、ungolfed:

dominos = [""] : ["|"] : zipWith (++) ("--" `before` dominos) ("|" `before` tail dominos)
    where before = map . map . (++)

比較のためのフィボナッチワンライナー:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

使用例:

$ ghci fibtile
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( fibtile.hs, interpreted )
Ok, modules loaded: Main.
*Main> f 5
----|
----|

--|--
--|--

--|||
--|||

|----
|----

|--||
|--||

||--|
||--|

|||--
|||--

|||||
|||||

*Main>

1

コブラ-176

コブラゴルフパッケージが完成するまで待ちきれません。

def m(n)
    for t in.f(n),print t+t
def f(n,x='')as String*
    if x.length<n,for i in.f(n,x+'-').toList+.f(n,x+'|').toList,yield i
    else if not'-'in x.replace('--',''),yield x+'\n'

1

J-54文字

n右側の引数として使用する関数。

0{::(];'--'&,"1@[,'|',"1])&>/@[&0&((1 2$,:)&.>'';,'|')

このゴルフの主な根源は(];'--'&,"1@[,'|',"1])&>/です。これは、長さ(N-2)と(N-1)のタイルのリストを取り、長さ(N-1)とNのタイルのリストを返します。これは、線形代数のような標準のフィボナッチ回帰です。];右のリストを新しい左として返します(変更がないため)。'--'&,"1@[追加し--ながら、左のリストにタイルを'|',"1]追加します|右のリストにタイルを、そして一緒にそれらは新しい右側のリストです。

それをn何度も繰り返し(それが@[&0)、空のタイルと長さ1の単一のタイルで開始します。次に、で最初のペアを返し0{::ます。つまり、ゼロ回実行すると、最初の空のタイルを返すだけです。数n回実行すると、nand(n+1)ペアまで計算されますが、後者は破棄されます。余分な作業ですが、文字数が少なくなります。

これ(1 2$,:)は、リスト内のタイルを簡単に拡張できるようにするためにJがしなければならないことです。左の開始リストを、各行の長さが0である2行の文字の行列の1項目リストにします。右の開始リストは同じですが、行の長さは1で、で埋められ|ます。次に、新しいタイルを各行に追加し、2セットのタイルを結合するときに行列のリストを追加します。これは、Jがランクと呼ぶ概念の単純なアプリケーションです。基本的に、引数の次元を操作し、必要に応じて暗黙的にループします。

   0{::(];'--'&,"1@[,'|',"1])&>/@[&0&((1 2$,:)&.>'';,'|')5
----|
----|

--|--
--|--

--|||
--|||

|----
|----

|--||
|--||

||--|
||--|

|||--
|||--

|||||
|||||

tryj.tkで試してみてください。


1

Python 3:70バイト

f=lambda n,s="\n":n>0and f(n-1,"|"+s)==f(n-2,"--"+s)or n or print(s*2)

sドミノの1行を表すすべての可能な文字列を再帰的に作成します。これらは複製および印刷されます。s改行文字として開始すると、空白行が自動的に発生します。

==2つの呼び出しの間は、f両方の関数呼び出しを実行するだけです。これらは通常None、単に印刷するために返され、に==定義されてNoneいる数少ない演算子の1つです。

andsおよびorsが再現する権利短絡行動生成するためにあるifのとelseungolfedコードの秒。

ゴルフをしていない:

def f(n,s="\n"):
 if n==-1:pass
 elif n==0: print(s*2)
 else: f(n-1,"|"+s);f(n-2,"--"+s)

1

網膜、44バイト

注:網膜はこの課題よりも若いです。

+`([-|]*)11(1*#)
$1|1$2$1--$2
1
|
.*?#
$0$0#

末尾の改行で単項で入力を取ります。

各行は独自のファイルに移動#し、ファイル内の改行に変更する必要があります。これは実用的ではありませんが、-sフラグを付けたまま1つのファイルとしてコードを実行し、#マーカーを保持することができます(#入力の改行も変更します)。#読みやすくするために、出力内のを改行に戻すことができます。例えば:

> echo 1111# | retina -s fib_tile | tr # '\n'
||||
||||

||--
||--

|--|
|--|

--||
--||

----
----

方法:

  • 入力から始めて、すべての行を他の2つと交換します。1つは最初の1変更で|、もう1つは最初の2つ1の変更--です。少なくとも2つ1の行があるまでこれを行います。
  • 単一1ののみが残っている場合、それらをに変更しました|
  • 各行を2倍にして、さらに改行を追加すると、目的の出力が得られます。

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