Fibonacci domino fayans


11

Orada klasik kombinasyon sonucu döşemek için yollar sayısı o 2*nkadar şerit 1*2domino n inci Fibonacci sayı. Amacınız, aşağıdaki n8 eğim gibi kesik çizgiler ve dikey çizgilerle çizilmiş, verilen tüm eğimleri yazdırmaktır n=5:

|————
|————

——|——
——|——

|||——
|||——

————|
————|

||——|
||——|

|——||
|——||

——|||
——|||

|||||
|||||

nGirdi olarak alan ve gerekli çıktıyı basan bir program veya adlandırılmış işlev sağlamanız gerekir. En az bayt kazanır.

Giriş

STDIN veya işlev girişi narasında 1ve 10dahil olan bir sayı .

Çıktı

2*nŞeridin yatay olarak çizilen her olası domino eğimini yazdırın . Eğimler herhangi bir sırada olabilir, ancak her biri tam olarak bir kez görünmelidir. Boş bir çizgi ile ayrılmalıdır.

Dikey domino iki dikey çubuktan ( |) ve yatay domino iki em çizgiden ( ) yapılmıştır. -ASCII'de kalmak için kısa çizgiler yerine kısa çizgiler ( ) kullanabilirsiniz .

Yazdırılan çıktı aynı göründüğü sürece boşlukla her şeyi yapabilirsiniz.


Son döşemeden sonra fazladan bir satır besleme boşluk içeren herhangi bir şeyin altına düşer mi?
Dennis

@Dennis Evet, ekstra boş satırlar iyi.
xnor

Aynı sorunu çözmek için pek çok farklı yaklaşım görmek beni gerçekten şaşırttı. Bunu bekledin mi?
Level River St

@steveverrill Hayır, tamamen yapmadım ve çeşitliliği görmekten çok memnunum! Ve seninkinden beklenmedik bir şekilde pasta alır. Kullandığım çoğu çözümde çoğunlukla Fibonacci tarzı bir özyineleme vardı. Ben filtreleme etkili olmasını bekliyoruz ve vermedi o dizeleri filtreleme olacağını rağmen ben, ben mi ölçüde ——ve |Dennis en değil uzunluk- gibi uzunluğuna göre ndizeleri ve |tarafından filtre çiftler halinde görünen. Ve ikincisi için, s.split('——sizin gibi aritmetik bir yaklaşımla değil , üretilen dize üzerindeki regexes veya string işlemleri ile olmasını beklerdim .
xnor

Bence "1x2 domino" gereksiz.
SuperJedi224

Yanıtlar:


5

C, 106

Golf versiyonu

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;
}

Orijinal versiyon

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");
  }
}

Nasıl çalışır

Değişken , 0 ile 0 iarasında çalışır 1<<n-1ve nbasamaklı tüm olası ikili sayıları üretir . İçin 0 kodlar |ve için 1 kodlar -. Çiftler halinde 1'ler içeren sayılarla ilgileniyoruz. Açıkçası bu sayılar 3 ile bölünebilir.

Bir sayı 3'e bölündüğünde, orijinal sayı sonucu 2 ile çarpıp kendine ekleyerek (3 ile etkili bir şekilde çarparak) kurtarılabilir. Çoğu sayı bir taşıma gerektirir, ancak işlem sayıları üzerinde gerçekleştirildiğinde ilgi, taşıma gerekmez, bu nedenle yalnızca bu durumlarda, ekleme yerine VEYA kullanılabilir. İfadenin i/3|i/3*2orijinal değerini döndürdüğü tek sayı oldukları için, ilgi sayılarını test etmek için kullanılır i. Aşağıdaki örneğe bakın.

1111= 15 -> 0101= 5 ---> 1111= 15 (geçerli, 0101|1010== 0101+1010)

1001= 9 -> 0011= 3 ---> 0111= 7 (geçersiz 0011|0110,! = 0011+0110)

Test değeri her zaman orijinal değere eşit veya daha küçüktür. 3'ün katları olmayan sayılar, 3'e bölündükten sonra 3 ile çarpıldığında orijinalden daha az bir sayı döndürdüğünden, test bu sayılar üzerinde de istenen YANLIŞ değeri verir.

Orijinal versiyonda j, bitlerini taramak ive çıktıyı üretmek için birkaç döngü kullanılır . Golfed versiyonda tek fordöngü içinde, kullanılan htüm numaralar arasında çalışır (n*2)*(1<<n)-10. Değerler aşağı itarafından oluşturulan h/2/n. jEşdeğer miktarda elde edildiği için değişken artık kullanılmamaktadır h%n. - ifadesinin kullanımı n*2, her iki satırın da aynı döngüden yazdırılmasını sağlar; putsifadede bazı şık çoklamalar, satırın sonunda bir veya iki yeni satır yazdırır.

Bu et bir artış konumunda olduğuna dikkat for()dirsek ve bu nedenle işletilirse sonrai=h/2/h .

Örnek çıktı n = 6:

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

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

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

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

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

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

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

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

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

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

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

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

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

i/3|i/3*2Hile ustaca! Gramer için aritmetik bir ifade beklemiyordum.
xnor

3

CJam, 33 27 bayt

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

6 bayt golf için @ jimmy23013 için teşekkürler!

Çevrimiçi deneyin!

Arka fon

Bu, özyinelemeli bir algoritmanın yinelemeli bir uygulamasıdır:

Olası tilings n için olası tilings dikey bir domino eklenmesi ile elde edilebilir : 1 - n olası tilings ve iki yatay domino n - 2 .

Bu şekilde, için tilings sayısı n için tilings sayılarının toplamıdır n - 1 ve n - 2 , diğer bir deyişle N inci Fibonacci sayısı.

Nasıl çalışır

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'                ";

Örnek çalışma

$ 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\henüz 0.6.2'de uygulanmadı, ama yaklaşımlarımızı birleştirebildim. Teşekkürler!
Dennis

2

Haskell, 89 bayt

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

fbir sayı verildiğinde, n uzunluğundaki tüm olası Fibonacci eğimlerinin bir satırının listesini döndüren bir işlevdir. bir satır döndürmesi önemli değildir, çünkü tüm çıkıntıların her iki satırı aynıdır.

füzerinde ardışık arayarak çalışır n-1ve n-2ve ekleme "|"ve "--"dizelerine (sırasıyla).

gsoruları cevaplayan işlevdir. temelde fgirdiyi çağırır , her dizeyi iki katına çıkarır, böylece iki satır gösterecek ve hepsini yeni satırlarla birleştirecektir.

örnek çıktı:

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

|||--
|||--

||--|
||--|

|--||
|--||

|----
|----

--|||
--|||

--|--
--|--

----|
----|

2

CJam, 42 37 bayt

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

Soruları ASCII tireleriyle değiştirmeye izin verdiğinden, çizgileri her bir bayt olarak saydım.

Çevrimiçi deneyin.

Nasıl çalışır

2 × L'lik olası tüm eğimleri elde etmek için , negatif olmayan tüm tamsayılar I <3 L üzerinde yineleyerek , taban 3'teki basamakların bile yatay dominoslara ve tek basamakların dikey olanlara karşılık gelmesini sağlarız.

Her I , baz 3'te L veya daha az basamak içerdiğinden, bu, 2 × L şeridi örtmek için tüm olası yolları üretir . Geriye kalan tek şey, 2 × L' den daha büyük veya daha küçük kaplamaları filtrelemek ve kalan kaplamaları yazdırmaktır.

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'.           ";

Örnek çalışma

$ 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

Güzel. Neden sadece baz 3 yerine edc65 gibi baz 2'yi kullanmadığınızı merak ediyorum. Bu, sizi kopyalardan kurtarabilirdi. Sanırım önde gelen sıfırlar muhtemelen adımda kesiliyor 3b. Bu doğru mu?
Level River St

1
@steveverrill: Evet, tam da sebebi bu. Olduğu gibi, önde gelen sıfırlar hiç dominoya karşılık gelmez. Ancak kopyaların olmaması, üç bloğu tek bir blokla değiştirmeme izin verecektir. Bunu biraz daha düşünmem gerekecek.
Dennis

@steveverrill: Temel 2'nin çalışmasını başaramadım, ancak özyinelemeli bir yaklaşım daha da kısa görünüyor.
Dennis

2

JavaScript (E6) 102

0 -> '-' ve 1 -> '|' bit dizilerinden konfigürasyonlar oluşturun.

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 / kundakçı konsolunda test et

F(5)

Çıktı

|----
|----

--|--
--|--

----|
----|

|||--
|||--

||--|
||--|

|--||
|--||

--|||
--|||

|||||
|||||

1

Haskell: 109 bayt

Bu, Fibonacci sayılarının dizisini tembel olarak hesaplamak için iyi bilinen Haskell tek-astarının bir çevirisidir:

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

Fayanssız döşeme karolarının ana sırası:

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

Ve karşılaştırma için Fibonacci tek astar:

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

Kullanım örneği:

$ 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

Kobra - 176

Cobra golf paketini bitirene kadar bekleyemem.

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 karakter

Fonksiyon nsağ tarafta argüman olarak alınır.

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

Bu golfün ana kökü (];'--'&,"1@[,'|',"1])&>/. Bu, uzunluk eğimlerinin (N-2) ve (N-1) bir listesini alır ve uzunluk eğimlerinin (N-1) ve N'nin bir listesini döndürür. Bu, standart Fibonacci nüksü, à la doğrusal cebirdir. ];sağ listeyi yeni sol olarak döndürür (değişiklik olmadığı için). '--'&,"1@[ekler --ederken, sol listeye fayans '|',"1]ekler |sağ listeye fayans ve bu arada yeni sağ liste bulunmaktadır.

Bunu ndefalarca tekrarlıyoruz (bu @[&0) ve boş döşeme ve uzunluk 1'in tek döşemesi ile başlıyoruz. Sonra çiftin ilkini ile geri veriyoruz 0{::. Yani, eğer sıfır kez çalıştırırsak, sadece ilk fayansı geri veririz. nZaman çalıştırırsak , nve ( n+1) çiftine kadar hesaplar , ancak ikincisini atarız. Ekstra bir iş ama daha az karakter.

(1 2$,:)J listelerindeki tilings kolayca uzatılabilir yapmak üzere yapması gereken bir şeydir. Sol başlangıç ​​listesini, her satırın uzunluğu 0 olan 2 satırlık bir karakter matrisinin 1 öğelik bir listesi haline getiriyoruz. Sağ başlangıç ​​listesi aynı, ancak satırların uzunluğu 1 ile doldurulmuş |. Ardından, her satıra yeni karolar ekliyoruz ve iki eğim setini birleştirirken matris listelerini ekliyoruz. J'nin rütbe olarak adlandırdığı bir kavramın basit bir uygulamasıdır: temelde argümanlarının boyutsallığını manipüle etmek ve gerektiğinde dolaylı olarak döngü yapmak.

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

--|--
--|--

--|||
--|||

|----
|----

|--||
|--||

||--|
||--|

|||--
|||--

|||||
|||||

Tryj.tk adresinde kendiniz deneyin .


1

Python 3: 70 bayt

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

sYinelenen ve yazdırılan bir dominos sırasını temsil eden tüm olası dizeleri özyinelemeli olarak oluşturur . Yeni ssatır karakteri olarak başlayarak , boş satır otomatik olarak gerçekleşir.

==İki çağrı arasında fsadece ikisi işlev çağrıları yapmaktır. Bunlar genellikle Noneyazdırıldıkları için geri döner ve ==tanımlanmış birkaç operatörden biridir None.

andLer ve ors çoğaltmak sağ kısa devre davranışı üretmek için vardır ifs ve elseungolfed kod s.

Ungolfed:

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

Retina , 44 bayt

Not: Retina bu zorluktan daha genç.

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

Sondaki satırsonu ile tek başına girdi alır.

Her satır kendi dosyasına gitmeli ve dosyadaki #satırsonu olarak değiştirilmelidir. Bu pratik değildir, ancak kodu işaretçileri olan (ve girişi yeni satır olarak değiştirerek) -sbayraklı tek bir dosya gibi çalıştırabilirsiniz . İsterseniz, okunabilirlik için çıktıları satırsonu olarak değiştirebilirsiniz . Örneğin:###

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

||--
||--

|--|
|--|

--||
--||

----
----

Yöntem:

  • Girişten başlayarak her satırı iki tane ile 1değiştiriyoruz : biri ilk değişiklikle, |diğeri ilk iki ile 1değiştirildi --. Bunu en az iki tane olana kadar yaparız 1.
  • Sadece bekar 1kaldığında bunları 'olarak değiştirdik |.
  • Her satırı ikiye katlıyoruz ve ona ekstra bir satırsonu ekliyoruz ve istenen çıktıyı alıyoruz.

Sondaki satırsonu iyi.
xnor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.