Ốp lát domino


11

kết quả kết hợp kinh điển rằng số cách xếp một 2*ndải bằng 1*2domino là số Fibonacci thứ n . Mục tiêu của bạn là in tất cả các chữ nghiêng cho trước n, được vẽ bằng dấu gạch ngang và các đường thẳng đứng như 8 chữ nghiêng này cho n=5:

|————
|————

——|——
——|——

|||——
|||——

————|
————|

||——|
||——|

|——||
|——||

——|||
——|||

|||||
|||||

Bạn phải cung cấp một chương trình hoặc chức năng được đặt tên nlàm đầu vào và in đầu ra cần thiết. Ít byte nhất sẽ thắng.

Đầu vào

Một số ngiữa 110bao gồm thông qua STDIN hoặc đầu vào chức năng.

Đầu ra

In mọi nghiêng domino có thể của 2*ndải, vẽ theo chiều ngang. Các góc có thể theo thứ tự bất kỳ, nhưng mỗi lần xuất hiện chính xác một lần. Chúng phải được phân cách bằng một dòng trống.

Một domino dọc được làm bằng hai thanh dọc ( |) và một domino ngang được làm bằng hai dấu gạch ngang ( ). Bạn có thể sử dụng dấu gạch nối ( -) thay cho dấu gạch ngang để ở lại ASCII.

Bạn có thể làm bất cứ điều gì với khoảng trắng miễn là đầu ra được in trông giống nhau.


Liệu một dòng cấp thêm sau khi lát cuối cùng rơi vào bất cứ thứ gì có khoảng trắng ?
Dennis

@Dennis Có, dòng trống thêm là tốt.
xnor

Tôi thực sự ngạc nhiên khi thấy rất nhiều cách tiếp cận khác nhau để giải quyết cùng một vấn đề. Bạn có mong đợi điều đó?
Cấp sông St

@steveverrill Không, tôi hoàn toàn không, và rất vui khi thấy sự đa dạng! Và bạn lấy bánh cho sự bất ngờ. Tôi chủ yếu nghĩ đến một đệ quy theo kiểu Fibonacci, vì hầu hết các giải pháp được sử dụng mà tôi đã sử dụng. Tôi không mong đợi lọc có hiệu quả, và trong phạm vi tôi đã làm, tôi mặc dù nó sẽ được lọc chuỗi ——|theo chiều dài như Dennis, không length- nchuỗi |lọc bởi xuất hiện trong cặp. Và về sau, tôi hy vọng nó sẽ thông qua các biểu thức chính quy hoặc chuỗi trên chuỗi được sản xuất, như s.split('——) `, chứ không phải bằng cách tiếp cận số học như của bạn.
xnor

Tôi nghĩ rằng "1x2 domino" là dư thừa.
SuperJedi224

Câu trả lời:


5

C, 106

Phiên bản chơi gôn

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

Phiên bản gốc

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

Làm thế nào nó hoạt động

Biến ichạy từ 1<<n-1xuống 0, tạo ra tất cả các số nhị phân có thể có nchữ số. 0 mã hóa cho |và 1 mã hóa cho -. Chúng tôi quan tâm đến các số chứa 1 trong cặp. Rõ ràng những con số như vậy chia hết cho 3.

Khi một số được chia cho 3, số ban đầu có thể được phục hồi bằng cách nhân kết quả với 2 và thêm nó vào chính nó (thực sự thay đổi bằng 3.) Hầu hết các số sẽ yêu cầu thực hiện, nhưng khi quá trình được thực hiện trên các số quan tâm, không cần mang theo, vì vậy chỉ trong những trường hợp này, HOẶC có thể được sử dụng thay vì bổ sung. Điều này được sử dụng để kiểm tra số lượng quan tâm, vì chúng là những người duy nhất mà biểu thức i/3|i/3*2trả về giá trị ban đầu của i. Xem ví dụ dưới đây.

1111= 15 ---> 0101= 5 ---> 1111= 15 (hợp lệ, 0101|1010== 0101+1010)

1001= 9 ---> 0011= 3 ---> 0111= 7 (không hợp lệ , 0011|0110! = 0011+0110)

Giá trị thử nghiệm luôn bằng hoặc nhỏ hơn giá trị ban đầu. Vì các số không phải là bội số của 3 cũng trả về một số nhỏ hơn số ban đầu khi chia cho 3 sau đó nhân với 3, bài kiểm tra cũng cho FALSE mong muốn trên các số này.

Trong phiên bản gốc, một vài vòng lặp jđược sử dụng để quét qua các bit ivà tạo đầu ra. Trong phiên bản chơi gôn, một forvòng lặp duy nhất được sử dụng, trong đó hchạy qua tất cả các số từ (n*2)*(1<<n)-1xuống đến 0. Giá trị iđược tạo bởi h/2/n. Biến jkhông còn được sử dụng, vì số lượng tương đương được lấy từ h%n. Việc sử dụng n*2cho phép cả hai dòng được in từ cùng một vòng lặp, với một số ghép kênh tiện lợi trong putscâu lệnh để in một hoặc hai dòng mới ở cuối hàng.

Lưu ý rằng thịt của việc này là ở vị trí increment của for()khung và do đó được thực hiện sau khi các i=h/2/h.

Sản lượng mẫu n = 6:

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

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

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

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

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

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

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

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

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

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

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

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

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

Các i/3|i/3*2Bí quyết là khéo léo! Tôi không mong đợi một biểu thức số học cho ngữ pháp.
xnor

3

CJam, 33 27 byte

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

Cảm ơn @ jimmy23013 vì đã chơi golf 6 byte!

Hãy thử trực tuyến!

Lý lịch

Đây là một triển khai lặp lại của thuật toán đệ quy:

Các độ nghiêng có thể có cho n có thể thu được bằng cách thêm một domino thẳng đứng vào các độ nghiêng có thể cho n - 1 và hai domino ngang cho các độ nghiêng có thể cho n - 2 .

Theo cách này, số lượng nghiêng cho n là tổng của số lượng nghiêng cho n - 1n - 2 , tức là số Fibonacci thứ n .

Làm thế nào nó hoạt động

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

Chạy ví dụ

$ 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\chưa được thực hiện trong 0.6.2, nhưng tôi đã có thể kết hợp các phương pháp của chúng tôi. Cảm ơn!
Dennis

2

Haskell, 89 byte

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

flà một hàm cho một số trả về một danh sách một dòng của tất cả các độ nghiêng Fibonacci có thể có độ dài n có thể. nó không quan trọng rằng nó trả về một dòng, bởi vì cả hai dòng của tất cả các nghiêng đều giống nhau.

fhoạt động bằng cách gọi đệ quy trên n-1n-2thêm "|""--"(tương ứng) vào chuỗi.

glà chức năng trả lời các câu hỏi. về cơ bản, nó gọi fđầu vào, nhân đôi mọi chuỗi để nó hiển thị hai dòng và nối tất cả chúng bằng dòng mới.

đầu ra ví dụ:

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

|||--
|||--

||--|
||--|

|--||
|--||

|----
|----

--|||
--|||

--|--
--|--

----|
----|

2

CJam, 42 37 byte

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

Tôi đã đếm các dấu gạch ngang là một byte mỗi câu hỏi vì câu hỏi cho phép thay thế chúng bằng dấu gạch nối ASCII.

Hãy thử trực tuyến.

Làm thế nào nó hoạt động

Để có được tất cả các độ nghiêng có thể là 2 × L , chúng tôi lặp lại trên tất cả các số nguyên không âm I <3 L , tạo các chữ số chẵn trong cơ sở 3 tương ứng với các chữ số ngang và chữ số lẻ thành các số dọc.

Vì mỗi I có chữ số L hoặc ít hơn trong cơ sở 3, điều này tạo ra tất cả các cách có thể để che dải 2 × L. Tất cả những gì còn lại là lọc ra các lớp phủ lớn hơn hoặc nhỏ hơn 2 × L và in các lớp phủ còn lại.

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

Chạy ví dụ

$ 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

Mát mẻ. Tôi chỉ tự hỏi tại sao bạn không sử dụng cơ sở 2 như edc65 thay vì cơ sở 3. Điều đó sẽ giúp bạn không bị trùng lặp. Tôi cho rằng đó là vì các số 0 đứng đầu có thể bị cắt ngắn trong bước này 3b. Có đúng không?
Cấp sông St

1
@steveverrill: Vâng, đó chính xác là lý do. Như nó là, số không hàng đầu tương ứng với không có domino. Nhưng không có bản sao sẽ cho phép tôi thay thế ba khối bằng một khối duy nhất. Tôi sẽ phải suy nghĩ về điều này nhiều hơn nữa.
Dennis

@steveverrill: Tôi đã không quản lý để làm cho cơ sở 2 hoạt động, nhưng một cách tiếp cận đệ quy dường như thậm chí còn ngắn hơn.
Dennis

2

JavaScript (E6) 102

Tạo cấu hình từ các chuỗi bit, 0 -> '-' và 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?'|':'--';
}

Kiểm tra trong bảng điều khiển firefox / fireorms

F(5)

Đầu ra

|----
|----

--|--
--|--

----|
----|

|||--
|||--

||--|
||--|

|--||
|--||

--|||
--|||

|||||
|||||

1

Haskell: 109 byte

Đây là bản dịch của Haskell one-liner nổi tiếng để tính toán một cách lười biếng chuỗi các số Fibonacci:

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

Chuỗi chính của chuỗi ốp lát, không được chỉnh sửa:

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

Và một lớp lót để so sánh:

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

Ví dụ sử dụng:

$ 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

Rắn hổ mang - 176

Không thể đợi đến khi tôi hoàn thành gói chơi gôn Cobra.

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 char

Chức năng lấy nlàm đối số bên phải.

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

Nguồn gốc chính của golf này là (];'--'&,"1@[,'|',"1])&>/. Cái này lấy một danh sách các độ dài (N-2) và (N-1), và trả về một danh sách các độ dài (N-1) và N. Đây là phép tái phát Fibonacci tiêu chuẩn, đại số tuyến tính. ];trả về danh sách bên phải là bên trái mới (vì không có thay đổi). '--'&,"1@[thêm các --ô vào danh sách bên trái, trong khi '|',"1]thêm các |ô vào danh sách bên phải và các ô đó là danh sách bên phải mới.

Chúng tôi lặp đi lặp lại nhiều nlần (đó là @[&0) và bắt đầu với lát gạch trống và lát gạch đơn có độ dài 1. Sau đó, chúng tôi trả lại cặp đầu tiên với 0{::. Có nghĩa là, nếu chúng ta chạy nó 0 lần, chúng ta chỉ trả về lần đầu tiên tức là lát gạch trống. Nếu chúng tôi chạy nlần này, chúng tôi tính toán đến cặp nvà ( n+1), nhưng loại bỏ cái sau. Đó là công việc làm thêm nhưng ít nhân vật hơn.

Đây (1 2$,:)là điều J phải làm để làm cho các góc trong danh sách dễ dàng được mở rộng. Chúng tôi tạo danh sách bắt đầu bên trái là danh sách 1 mục của ma trận 2 hàng ký tự, mỗi hàng có độ dài 0. Danh sách bắt đầu bên phải giống nhau, nhưng có các hàng có độ dài 1, được điền |. Sau đó, chúng tôi thêm các ô mới vào mỗi hàng và nối thêm các danh sách ma trận khi chúng ta kết hợp hai bộ nghiêng với nhau. Đây là một ứng dụng đơn giản của một khái niệm J gọi thứ hạng: về cơ bản thao túng tính chiều của các đối số của nó và ngầm lặp khi cần thiết.

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

--|--
--|--

--|||
--|||

|----
|----

|--||
|--||

||--|
||--|

|||--
|||--

|||||
|||||

Hãy thử nó cho chính mình tại tryj.tk .


1

Python 3: 70 byte

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

Xây dựng đệ quy tất cả các chuỗi có thể sđại diện cho một hàng domino, được sao chép và in. Bắt đầu slà ký tự dòng mới làm cho dòng trống tự động xảy ra.

Các ==giữa hai cuộc gọi cho flà chỉ để thực hiện cả hai chức năng cuộc gọi. Chúng thường trả về Nonevì chúng chỉ in và ==là một trong số ít toán tử được định nghĩa cho None.

Các ands và ors sẽ tạo ra hành vi ngắn mạch đúng để tái tạo ifs và elses của mã không được mã hóa.

Ung dung:

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

Võng mạc , 44 byte

Lưu ý: Retina trẻ hơn thử thách này.

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

Đưa đầu vào trong unary với một dòng mới.

Mỗi dòng nên đi đến tệp riêng của nó và #nên được thay đổi thành dòng mới trong tệp. Điều này là không thực tế nhưng bạn có thể chạy mã dưới dạng một tệp với -scờ, giữ các #điểm đánh dấu (và thay đổi dòng mới thành #trong đầu vào). Bạn có thể thay đổi #trở lại dòng mới trong đầu ra để dễ đọc nếu bạn muốn. Ví dụ:

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

||--
||--

|--|
|--|

--||
--||

----
----

Phương pháp:

  • Bắt đầu từ đầu vào, chúng tôi trao đổi mọi dòng với hai dòng khác: một với 1thay đổi đầu tiên |và một với hai 1thay đổi đầu tiên thành --. Chúng tôi làm điều này cho đến khi chúng tôi có các dòng có ít nhất hai 1.
  • Khi chỉ 1còn lại một mình, chúng tôi đã thay đổi chúng thành |.
  • Chúng tôi nhân đôi mỗi dòng và thêm một dòng mới vào nó và chúng tôi nhận được đầu ra mong muốn.

Trailing newline là tốt.
xnor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.