Nghệ thuật ngẫu nhiên ASCII trong ngày # 5: Kim cương nghiêng


21

Thời gian kết thúc!

Đây là phần thứ 5 của cả bộ Golf ngẫu nhiên trong ngày của tôisê-ri Nghệ thuật trong ngày ASCII của Trình tối ưu hóa . (Các) bài đăng của bạn trong thử thách này sẽ được tính vào cả hai bảng thành tích (mà bạn có thể tìm thấy các bài đăng được liên kết). Tất nhiên, bạn có thể coi điều này giống như bất kỳ thử thách golf mã nào khác, và trả lời nó mà không phải lo lắng về bất kỳ loạt nào.

Lỗ 5: Kim cương nghiêng

Một hình lục giác thông thường luôn có thể được lát bằng kim cương như vậy:

Chúng tôi sẽ sử dụng một đại diện nghệ thuật ASCII của những nghiêng này. Đối với một hình lục giác có chiều dài 2 cạnh, có 20 góc như vậy:

   ____     ____     ____     ____     ____     ____     ____     ____     ____     ____  
  /\_\_\   /\_\_\   /\_\_\   /\_\_\   /_/\_\   /_/\_\   /\_\_\   /_/\_\   /_/\_\   /_/\_\ 
 /\/\_\_\ /\/_/\_\ /\/_/_/\ /\/_/\_\ /\_\/\_\ /\_\/_/\ /\/_/_/\ /\_\/\_\ /\_\/_/\ /_/\/\_\
 \/\/_/_/ \/\_\/_/ \/\_\_\/ \/_/\/_/ \/\_\/_/ \/\_\_\/ \/_/\_\/ \/_/\/_/ \/_/\_\/ \_\/\/_/
  \/_/_/   \/_/_/   \/_/_/   \_\/_/   \/_/_/   \/_/_/   \_\/_/   \_\/_/   \_\/_/   \_\/_/ 
   ____     ____     ____     ____     ____     ____     ____     ____     ____     ____  
  /_/_/\   /\_\_\   /_/\_\   /_/_/\   /_/\_\   /_/\_\   /_/_/\   /_/_/\   /_/_/\   /_/_/\ 
 /\_\_\/\ /\/_/_/\ /_/\/_/\ /\_\_\/\ /\_\/_/\ /_/\/_/\ /_/\_\/\ /\_\_\/\ /_/\_\/\ /_/_/\/\
 \/\_\_\/ \/_/_/\/ \_\/\_\/ \/_/\_\/ \/_/_/\/ \_\/_/\/ \_\/\_\/ \/_/_/\/ \_\/_/\/ \_\_\/\/
  \/_/_/   \_\_\/   \_\/_/   \_\/_/   \_\_\/   \_\_\/   \_\/_/   \_\_\/   \_\_\/   \_\_\/ 

Cho một chiều dài cạnh N, bạn nên tạo một lát như vậy cho một hình lục giác có chiều dài cạnh Nngẫu nhiên. Phân phối chính xác không thành vấn đề, nhưng mỗi ốp lát phải được trả về với xác suất khác không.

Đối với N ≤ 4, việc gửi của bạn phải tạo ra một lát trong vòng 1 phút ít nhất 80% thời gian và ít nhất 80% số lần nghiêng phải có khả năng được tạo trong vòng 1 phút. Hầu hết các cách tiếp cận sẽ không phải lo lắng về quy tắc này (nó rất khoan dung) - đây chỉ là để loại trừ các thuật toán dựa trên từ chối rất ngây thơ tạo ra các chuỗi tùy ý cho đến khi một biến trở thành một lát gạch.

Bạn có thể muốn biết rằng tổng số độ nghiêng có thể có của N đã cho có thể được tìm thấy trong OEIS A008793 .

Bạn có thể viết một chương trình đầy đủ hoặc một hàm và nhận đầu vào thông qua STDIN (hoặc thay thế gần nhất), đối số dòng lệnh hoặc đối số hàm và tạo đầu ra thông qua STDOUT (hoặc thay thế gần nhất), tham số trả về hàm hoặc tham số hàm (out).

Bạn không được xuất nhiều khoảng trắng hàng đầu hơn mức cần thiết để căn chỉnh hình lục giác (đó là góc bên trái của hình lục giác không có khoảng trắng phía trước nó). Mỗi dòng có thể chứa tối đa Nkhoảng trắng (không nhất thiết phải nhất quán, do đó bạn có thể có đầu ra hình chữ nhật, in hộp giới hạn của hình lục giác).

Đây là mã golf, vì vậy bài nộp ngắn nhất (tính bằng byte) sẽ thắng. Và tất nhiên, lần gửi ngắn nhất cho mỗi người dùng cũng sẽ tham gia vào bảng xếp hạng tổng thể của loạt bài.

Bảng xếp hạng

Bài đầu tiên của mỗi loạt tạo ra một bảng thành tích.

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu mọi câu trả lời bằng tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

# Ruby, <s>104</s> <s>101</s> 96 bytes

(Ngôn ngữ hiện không được hiển thị, nhưng đoạn mã yêu cầu và phân tích nó và tôi có thể thêm bảng xếp hạng ngôn ngữ trong tương lai.)


3
Có phải chỉ tôi là người tiếp tục nhìn thấy hình ảnh ví dụ trong 3D?
LegionMammal978

3
@ LegionMammal978 Không có điều đó hoàn toàn bình thường. ;) (Và có lẽ cũng là một cách tốt để tiếp cận thử thách.)
Martin Ender

For N ≤ 4, your submission must produce a tiling within 1 minute at least 80% of the time.quá dễ dàng: 80% thời gian giống nhau, ốp lát cơ bản, nếu không tôi tìm thấy một lát khác trong bất cứ lúc nào tôi muốn
edc65

@ edc65 Điểm hay, hãy để tôi nói lại điều đó.
Martin Ender

Câu trả lời:


10

CJam, 105 byte

ri:A" __"e*A,2f*:B,[W1]{J+B:):B,{N1$S*"\/"J%A2*4$-:D*
0{;B{_1&!2mr+J*m1e>D(2*e<}%__:)&}g:B{'_t}/+@J+}*}fJ;

Dòng mới được thêm vào để tránh cuộn. Dùng thử trực tuyến

Giải trình:

Giải pháp này bắt đầu mỗi dòng dưới dạng ngoằn ngoèo, sau đó đặt N gạch dưới lên nó, dựa trên vị trí của chúng trên dòng trước đó và một vài quy tắc. Tôi đã nhận được điều này từ một loạt các quan sát trong khi xem đầu ra dưới dạng ma trận 2D đơn giản của các ký tự:

  • mỗi dòng có chính xác N dấu gạch dưới
  • các dấu gạch dưới có thể được thay thế bằng / hoặc \ để tạo ra một mẫu zigzag lặp lại hoàn hảo ( /\ở nửa trên, \/ở nửa dưới)
  • dấu gạch dưới không thể chạm vào các cạnh và không thể liền kề với dấu gạch dưới khác
  • khi đi đến dòng tiếp theo, vị trí của mỗi dấu gạch dưới thay đổi theo -1, 0 hoặc 1
  • nhiều hơn thế, /_/chỉ có thể thay đổi bằng -1 hoặc 0 và \_\chỉ có thể thay đổi bằng 0 hoặc 1
  • Đối với các vị trí gạch dưới ban đầu, chúng ta có thể sử dụng một "_ "mẫu hoặc một " _"mẫu, cả hai đều ổn
  • các quy tắc trên là đủ để có được tất cả các nghiêng

Vì vậy, tôi quyết định thực hiện nó bằng cách giữ các vị trí gạch dưới trước đó, sửa đổi chúng với một yếu tố ngẫu nhiên (2 lựa chọn cho mỗi dấu gạch dưới) và lặp lại cho đến khi các quy tắc được thỏa mãn. Trong quá trình tối ưu hóa, tôi chuyển sang các vị trí gạch dưới so với bên trái của hình lục giác (không bao gồm khoảng trắng).

ri:A" __"e*       read the input (A) and generate the top line
A,2f*:B           make an array [0 2 4 ... 2A-2] and store in B
                  these are the initial positions for the underscores
,                 B's length = A, used as the initial number of leading spaces
                  let's call it C
[W1]{…}fJ         for J in [-1 1] (top half, bottom half)
  J+              add J to C
  B:):B           increment the underscore positions (adjustment before each half)
  ,{…}*           repeat A times
    N1$S*         add a newline and C spaces
    "\/"J%        take "\/" and reverse it if J=-1 (zigzag pattern)
    A2*4$-:D*     calculate D=A*2-C and repeat the pattern
    0             dummy value (for the next loop)
    {…}g          do-while
      ;B          pop last value and push B
      {…}%        apply block to each item (say x)
        _1&!      duplicate x and calculate !(x&1) (for /_/ vs \_\)
        2mr+      randomly add 0 or 1
        J*m       multiply by J and subtract from x
        1e>       limit the minimum value to 1
        D(2*e<    and the maximum value to 2*(D-1)
      __:)&       check if the modified array has any adjacent values
    :B            store the new positions in B
    {'_t}/        place underscores over the zigzag pattern
    +@J+          bring C to the top and add J to it
;                 pop C

Phiên bản "3D" cũ, 189 byte:

ri:A" __"e*aA4*S*aA2**+[0-2XXW1]:C;"/\_\\\/_/":D;A3m*{{C2/.f*:.+~
A(2*+:V;A+:U;2{UI+1$1$=4{_V+D4/I=@=t}/t}fI}:F~}/[0Y1WWW]:C;
"/_/\\\_\/":D;AaA*:B;A{A[_{_BI=e<)mr}fI]:B;{BQ={[PQR]F}fR}fQ}fPN*

Dùng thử trực tuyến


+1 cho công việc tuyệt vời và cũng vì một phiếu bầu nữa sẽ đưa bạn ở mức 10k, nhưng chủ yếu là cho công việc tuyệt vời. (Ồ này, nhìn kìa. Chúc mừng 10k :))
Alex A.

Một phân tích tuyệt vời về các mẫu! Tôi sẽ sử dụng nó cho câu trả lời của tôi.
anatolyg

6

Python 2, 337 335 324 318 311 300 296 byte

from random import*
n=input()
R=range(n*2)
b=[]
l=[]
for i in R:o=abs(i-n)-(i<n);b+=[o];l+=[list(' '*o+'\//\\'[i<n::2]*(n*2-o))]
for i in R[:n]:
 o=1;p=n+i*2
 for j in R:r=randint(0,p<n*3+i*2-j);p+=(r or-1)*(o==r);q=p<=b[j];o=r|q;p+=q;l[j][p]='_';b[j]=p+1
for s in[' '*n+'__'*n]+l:print''.join(s)

Ý tưởng đầu tiên là tạo ra một hình lục giác kim cương, như thế này:

  ____
 /\/\/\
/\/\/\/\
\/\/\/\/
 \/\/\/

Và sau đó lấp đầy nó bằng các đường xuống dưới của dấu gạch dưới, như thế này:

  ____                          ____
 /_/\/\                        /\_\/\
/_/\/\/\    or maybe this:    /\/_/\/\
\_\/\/\/                      \/_/\/\/
 \_\/\/                        \_\/\/

Kết quả cuối cùng với tất cả các đường dẫn được thêm vào sẽ trông giống như thế này:

  ____                          ____  
 /_/\_\                        /\_\_\ 
/_/\/_/\    or maybe this:    /\/_/\_\
\_\/_/\/                      \/_/\/_/
 \_\_\/                        \_\/_/ 

Khá nhiều mã đi vào để đảm bảo các đường dẫn này không đi ra khỏi giới hạn hoặc giao nhau.

Mã không mã hóa:

# Initialize l with all diamonds
blocked = []
l = [[] for _ in range(n*2)]
for i in range(n*2):
    offset = n-i-1 if i<n else i-n
    blocked.append(offset)
    l[i] += ' '*offset + ('/\\' if i<n else '\/')*(2*n - offset)

# Generate the random _'s
for i in range(n):
    oldright = True
    pos = n + i*2
    for j in range(n*2):
        # Go randomly right (true) or left (false), except when you out of bounds on the right side
        right = randint(0, 1) and pos < n*3 + i*2 - j
        if right == oldright:
            pos += 1 if right else -1
        if pos <= blocked[j]:
            right = True
            pos += 1
        l[j][pos] = '_'
        blocked[j] = pos + 1
        oldright = right

# Print the result
print ' '*n + '__'*n
for s in l:
    print ''.join(s)

1
Tôi chỉ nhận thấy rằng đầu ra của bạn có vẻ sai. Bạn đã có hình tam giác trong hai kết quả exaple của bạn (trên cùng bên phải và dưới cùng bên phải).
Martin Ender

1
@MartinEnder Các ví dụ chỉ hiển thị một 'đường dẫn của dấu gạch dưới', để hiển thị ý tưởng của thuật toán. Đầu ra cuối cùng có tất cả các đường dẫn (trong trường hợp này là 2), loại bỏ các hình tam giác. Tôi đã thêm vào các ví dụ về đầu ra cuối cùng là tốt.
Matty

Ohhh tôi thấy, điều đó có ý nghĩa. Cảm ơn bạn đã làm rõ.
Martin Ender

2
Tôi nghĩ rằng bạn có thể rút ngắn randint(0,1)*(p<n*3+i*2-j)tới randint(0,p<n*3+i*2-j).
12Me21

Ồ vâng, cảm ơn!
Matty

4

Perl, 174 168 166 161

#!perl -n
for$l(-$_..$_){$t=/_/?join'',map'/_'x($%=rand
1+(@z=/__?/g)).'/\\'.'_\\'x(@z-$%),split/\/\\/:__
x$_;$l>0&&$t!~s!^.(\\.*/).$!$1!?redo:print$"x abs$l-.5,$_=$t.$/}

Hãy thử tôi .


Nó dường như luôn tạo ra cùng một lát (ít nhất là trên ideone)
aditsu

@aditsu, Ideone hiển thị kết quả được lưu trong bộ nhớ cache nếu bạn chỉ cần nhấp vào liên kết. Bạn cần phải rẽ nhánh để thực sự chạy lại nó.
nutki

2

JavaScript ( ES6 ), 376 416 494

Chỉ cần ở đó ...

Điều này xây dựng tất cả các nghiêng, sau đó chọn một ngẫu nhiên. Thời gian cho 232848 nghiêng cho N = 4 là ~ 45 giây trên máy tính xách tay của tôi. Tôi đã không thử N = 5.

Là EcmaScript 6, nó chỉ chạy trên Firefox.

F=n=>{
  for(i=s=r=b='';i<n;i++)
    s='\n'+b+'/\\'[R='repeat'](n-i)+'_\\'[R](n)+s,
    r+='\n'+b+'\\/'[R](n-i)+'_/'[R](n),
    b+=' ';
  for(h=[t=0],x=[s+r];s=x[t];t++)
    for(d='';!d[n*3];d+='.')
      if(l=s.match(r=RegExp("(\n"+d+"/)\\\\_(.*\n"+d+"\\\\)/_","g")))
        for(j=2<<l.length;j-=2;h[z]||(h[z]=x.push(z)))
          z=s.replace(r,(r,g,h)=>(k+=k)&j?g+'_/'+h+'_\\':r,k=1);
  return b+'__'[R](n)+x[Math.random()*t|0]
}


function go()
{
  var n = N.value | 0,
  t0 = performance.now(),
  r = F(n),
  t1 = performance.now();
  
  O.innerHTML = r+'\n\nTime (msec): '+(t1-t0)
}
N: <input id=N value=3><button onclick="go()">GO</button>
<pre id=O></pre>


Trong Chromium 42, tôi nhận được "Uncaught SyntaxError: Unazed token =>" và "Uncaught ReferenceError: go không được xác định"
aditsu

1
@aditsu là ES6, Chrome: không có Firefox: có. Nó không phải là một thực tế nổi tiếng?
edc65

Tôi không biết, tôi mong đợi Chromium sẽ sử dụng bất kỳ thứ gì mới nhất và lớn nhất mà nó được gọi là không rõ ràng. Cảm ơn vì đã giải thích.
aditsu

Tôi đã chạy nó ngay bây giờ trong firefox (31.5.3) và nó hoạt động với N = 1, 2 hoặc 3, nhưng với N = 4, nó chạy trong khoảng 10 giây, kết thúc và không hiển thị gì cả (và không có lỗi trong bảng điều khiển )
aditsu

@aditsu không chắc chắn ... có thể javascript trong hộp cát bị giết một cách lặng lẽ khi vượt quá giới hạn thời gian dom.max_script_run_time. Đó là một ưu tiên toàn cầu trong about: config, mine được đặt thành 30.
edc65

1

SmileBASIC, 241 byte

INPUT N
T=N*2CLS?" "*N;"__"*N
DIM B[T]FOR I=-1TO N-1O=1P=N+I*2FOR J=0TO T-1IF I<0THEN O=ABS(J0N+.5)<<0B[J]=O?" "*O;MID$("\/\",J<N,2)*(T-O)ELSE R=P<N*3+I*2-J&&RND(2)P=P+(R*2-1)*(O==R)A=P<=B[J]R=R||A:P=P+A:LOCATE P,J+1?"_"B[J]=P+1O=R
NEXT
NEXT

Dựa trên câu trả lời của Matty

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.