Vẽ một hexa-glyph ngẫu nhiên


23

nhập mô tả hình ảnh ở đây

Hình ảnh trên được gọi là hexa-glyph. Hexa-glyphs là một số mẫu thú vị tôi đã tạo ra trong khi vẽ nguệch ngoạc trong lớp DiffEq của mình. Đây là cách bạn tạo một:

  1. Hãy xem xét tập hợp các điểm sau đây, có hình dạng như một hình lục giác thông thường. Hình lục giác bên trong là những gì sẽ chứa glyph cuối cùng, trong khi 6 điểm bên ngoài tạo thành một ngôi sao và là nơi chúng ta sẽ bắt đầu vẽ các đường của chúng ta.

nhập mô tả hình ảnh ở đây

  1. Từ sáu điểm bên ngoài, chọn ngẫu nhiên một cặp. Để đạt hiệu quả, cần có ít nhất một điểm khác giữa hai điểm được chọn (nếu không, nó sẽ không có hiệu lực trên hình cuối cùng). Sau đó, từ mỗi điểm trong hai điểm, chiếu một tia về phía kia. Tia này bị chặn bởi các dòng trước.

nhập mô tả hình ảnh ở đây

  1. Lặp lại quá trình này cho đến khi tất cả 9 cạnh đã được hình thành, như thể hiện trong một vài hình ảnh tiếp theo.

nhập mô tả hình ảnh ở đây

  1. Dưới đây là một ví dụ về các tia bị chặn. Các đầu của đoạn tia vẫn có thể nhìn thấy, nhưng phần giữa bị che khuất bởi hai đoạn đầu tiên chúng ta đã vẽ.

nhập mô tả hình ảnh ở đây

  1. Hai tia này cũng bị "chặn", nhưng điều này không gây ra bất kỳ sự khác biệt rõ ràng nào vì chúng bị chặn bởi cùng một dòng khác.

nhập mô tả hình ảnh ở đây

  1. Chuyển tiếp nhanh cho đến khi tất cả 9 dòng được rút ra. Nếu bạn muốn giải thích chi tiết hơn về các bước bị bỏ qua này, tôi có thể giải thích.

nhập mô tả hình ảnh ở đây

  1. Cuối cùng, loại bỏ các điểm của ngôi sao. Để làm cho nó trông đẹp hơn, các chấm dày cũng được loại bỏ.

nhập mô tả hình ảnh ở đây

Các thách thức

Bạn thách thức là đưa ra một biểu diễn trực quan của hexa-glyph ngẫu nhiên. Đây là mã golf, ít byte thắng nhất.

  1. Tất cả các hexa-glyph có thể sẽ xuất hiện với một số xác suất dương. Các hexa-glyph khác nhau được tạo ra bằng cách thay đổi thứ tự trong đó 9 cạnh được vẽ.

  2. Hơn nữa, tất cả các hình ảnh đầu ra bởi chương trình của bạn phải là hexa-glyph hợp lệ. Một số mẫu nhất định (như một phác thảo hoàn chỉnh của hình lục giác bên trong) có thể không xuất hiện dưới dạng hexa-glyph, và vì vậy chương trình của bạn không được xuất ra.

  3. Đầu ra phải là một hình ảnh đồ họa (được in ra màn hình hoặc tập tin).

  4. Hình lục giác phải đều đặn, nhưng có thể xuất hiện theo bất kỳ hướng nào.

  5. Phản xạ / xoay không được coi là duy nhất. (Điều này có thể làm cho yêu cầu 1 dễ thực hiện hơn).


8
I made up while doodling during my DiffEq class. Cách tất cả những khám phá tuyệt vời xảy ra ...: P
Rɪᴋᴇʀ

Các yêu cầu tối thiểu cho hình ảnh là gì? Ở mức độ nào thì một nghệ thuật ASCII phải được nhận ra miễn là mỗi cạnh được thể hiện và đặt ở vị trí mơ hồ?
John Dvorak

@JanDvorak Tôi đã loại bỏ tùy chọn nghệ thuật ASCII của thử thách (như trong vòng 2 phút sau khi đăng) vì các chương trình sản xuất ASCII nghệ thuật và đầu ra đồ họa không dễ so sánh được.
PhiNotPi

Thế còn pixel art thì sao? Một tiêu đề PPM không quá nặng và sau đó, sự khác biệt duy nhất là sử dụng '01'với không gian xen kẽ thay vì ' *'.
John Dvorak

@JanDvorak Đầu ra sau đó sẽ là một tệp hình ảnh được định dạng chính xác, phải không? Sau đó, tôi không thấy bất cứ điều gì sai với nó.
PhiNotPi

Câu trả lời:


18

Toán học, 273 268 264 242 byte

c=CirclePoints;b@_=k=1>0;Graphics[Line/@Cases[Append[Join@@({c@6,{3^.5/2,-Pi/6}~c~6}),{0,0}][[b@#=!k;#]]&/@TakeWhile[#,t=k;(r=t;t=b@#;r)&]&/@Join@@RandomSample[{#,Reverse@#}&/@Partition[Range@12,3,2,1]~Join~Array[{2#,13,2#+6}&,3]],{_,__}]]

Các ám như một superscript Ttrong Mathematica và là một nhà điều hành postfix transpose.

Sắp xếp các lỗi trong việc này mất mãi mãi ... đến cuối cùng tôi đã hack một vài thứ cùng nhau để làm cho nó hoạt động, vì vậy đây chắc chắn là tối ưu. Tôi cũng tự hỏi liệu có thể tốt hơn về mặt tổng thể để thực hiện thông số kỹ thuật theo nghĩa đen hơn thông qua các đường ngang qua hình lục giác bên ngoài và để các hàm hình học của Mathicala xử lý các giao điểm.

Lưu ý rằng đây là một chương trình đầy đủ và nếu bạn muốn chạy mã nhiều lần trong một phiên REPL, bạn sẽ phải thêm tiền tố vào đó Clear[b].

Dưới đây là kết quả của 20 lần chạy:

nhập mô tả hình ảnh ở đây

Giải trình

Giải pháp này hoàn toàn không sử dụng các điểm sao bên ngoài. Thay vào đó, nó hoạt động trực tiếp với các điểm là một phần của hexaglyph và các đường bao phủ ba trong số chúng cùng một lúc.

Hãy ghi nhãn các điểm:

nhập mô tả hình ảnh ở đây

1bắt đầu ở một góc hơi kỳ lạ nhưng điều này là do hành vi mặc định (cũng hơi kỳ lạ) của CirclePoints. Bắt đầu hình lục giác từ đó hóa ra rẻ nhất.

Bây giờ chúng tôi muốn tìm các đường liên quan thông qua ba trong số các điểm tương ứng với các điểm được kết nối của ngôi sao bên ngoài. Những cái xung quanh hình lục giác tất nhiên chỉ là 3 điểm liền kề (modulo 12), bắt đầu từ một số lẻ. Những người trên trung tâm bao gồm một số chẵn n, 13n+6.

Đại diện của các dòng này (dưới dạng danh sách ba điểm được tạo bởi mã sau đây):

Partition[Range@12,3,2,1]~Join~Array[{2#,13,2#+6}&,3]

Các Partitiondòng tạo ra các đường xung quanh hình lục giác và Arraycác đường qua trung tâm. Để xử lý cả hai chùm tia, chúng tôi ánh xạ hàm này qua danh sách các dòng:

{#,Reverse@#}&

Bây giờ chúng tôi trộn chúng với RandomSampleđể xử lý chúng theo thứ tự ngẫu nhiên. Join @@làm phẳng danh sách các cặp để chúng ta có một danh sách các chùm.

Tạm dừng ngắn: để theo dõi những điểm nào đã bị chặn, chúng tôi sử dụng chức năng tra cứu b, được khởi tạo Truecho tất cả các giá trị theo b@_=k=1>0;. Khi xử lý một chùm tia, chúng ta giữ tất cả các điểm cho đến điểm đầu tiên có b[n] == False( bao gồm cả điểm đó):

TakeWhile[#,t=k;(r=t;t=b@#;r)&]&

Tôi cảm thấy như đây là phần dễ chơi nhất hiện nay ... việc sử dụng hai biến tạm thời để chơi Mastermind có vẻ thực sự tốn kém. Dù sao, kết quả của việc này mang lại cho chúng ta những điểm trong một dòng chúng ta được phép vẽ. Bây giờ chức năng này được ánh xạ qua từng điểm đó:

Append[Join@@({c@6,{3^.5/2,-Pi/6}~c~6}),{0,0}][[b@#=!k;#]]&

Phần đầu tiên tạo danh sách tất cả 13 điểm bằng cách sử dụng kết quả xen kẽ của hai cuộc gọi đến CirclePoints(với bán kính khác nhau cho các tâm cạnh và các góc của hình lục giác). Lưu ý cái b@#=!kmà bây giờ đặt giá trị của bảng tra cứu cho điểm hiện tại để Falsekhông có chùm tia nào nữa có thể đi qua nó. Cuối cùng, giá trị được sử dụng như một chỉ mục vào danh sách tọa độ để có được điểm 2D chính xác.

Cases[...,{_,__}]

Điều này loại bỏ tất cả các danh sách thành phần đơn, bởi vì chúng sẽ hiển thị dưới dạng các điểm riêng lẻ (và hiển thị). Cuối cùng, chúng tôi đưa ra kết quả:

Graphics[Line/@...]

b@_=1>0=b=1>0&
Máy

@CatsAreFluffy Tôi không nghĩ rằng nó hoạt động, bởi vì tôi cần có thể ghi đè lên các giá trị riêng lẻ sau này.
Martin Ender

Sử dụng tốt Circle Circle.
DavidC

Tôi đánh giá cao liên kết Youtube đó.
DanTheMan

8

Giày (Ruby) Rev C 184 byte

12 byte được lưu bằng cách chuyển trách nhiệm kiểm tra xem có nên rút một nửa dòng cụ thể từ chương trình chính sang phương thức vẽ không. Chương trình chính vẫn phải kiểm tra xem toàn bộ dòng có bị chặn hoàn toàn không.

Shoes.app{t=[]
d=->p,q{t[p]&&t[q]||line(p/6*8,p%6*14,q/6*8,q%6*14)}
%w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|b=i.sum/2
c=b*2-a=i.ord
t[a]&&t[c]||(d[a,b]
d[b,c]
t[a]=t[b]=t[c]=1)}}

Giày (Ruby) 205 ... Rev B 196 byte

Giày là một công cụ dựa trên ruby ​​để xây dựng GUI, v.v ... Đây là lần đầu tiên tôi sử dụng nó. Mothereff.in/byte-count tính trình của tôi là 196 byte, nhưng vì một số lý do, Giày tính nó là 202.

Ngoài ra, Ruby cho phép bạn làm những việc như thế t[a=i.ord]nhưng kỳ lạ thay, dường như nó không hoạt động như mong đợi với Giày.

Shoes.app{t=[]
d=->p,q{line(p/6*8,p%6*14,q/6*8,q%6*14)}
%w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|b=i.sum/2
c=b*2-a=i.ord
t[a]&&t[c]||(t[a]&&t[b]||d[a,b]
t[b]&&t[c]||d[b,c]
t[a]=t[b]=t[c]=1)}}

Giải trình

Tôi không xem xét các phần của dòng bên ngoài hình lục giác. Tôi chỉ vẽ phần cần vẽ. Điều quan trọng là liệu các đường có giao nhau với giao lộ hay không (Nếu chúng ta chỉ vẽ các phần cần vẽ, điều này có nghĩa là chúng bắt đầu / kết thúc tại các giao lộ.)

Nguyên tắc cơ bản là nếu cả hai điểm cuối của một dòng đã được truy cập, dòng đó sẽ bị chặn và không nên được rút ra. Vì các đường được vẽ thành hai nửa, chúng ta cũng phải kiểm tra xem điểm giữa có được truy cập để xem mỗi nửa có nên được vẽ hay không.

Tôi theo dõi những điểm đã được truy cập trong mảng t[]. Điều này kết thúc có chứa một mục nhập cho mỗi tọa độ vật lý trên lưới bên dưới. Không có mảng logic 13 phần tử riêng biệt. Cuối cùng, t[]có thể có 87 yếu tố, mặc dù chỉ có tối đa 13 yếu tố sẽ chứa dữ liệu hữu ích.

Trong nội bộ, tọa độ các điểm cuối của các đường được cho bởi một số duy nhất z, trong đó z% 6 là tọa độ y và z / 6 là tọa độ x. Trong hệ thống này, hình lục giác được làm phẳng. Khi các đường được vẽ, thang đo x được nhân với 8 và thang đo y được nhân với 14, đó là một xấp xỉ hợp lý rất gần với tỷ lệ chính xác: 14/8 = 1,75 so với sqrt (3) = 1.732.

Hệ thống tọa độ bên trong được hiển thị bên dưới, với một vài kết quả đầu ra mẫu.

nhập mô tả hình ảnh ở đây

Bị đánh cắp

Shoes.app{
  t=[]                                          #Empty array for status tracking
  d=->p,q{line(p/6*8,p%6*14,q/6*8,q%6*14)}      #Drawing method. Convert p and q into x,y pairs, scale and draw line.
  %w{1I IW WM M5 5' '1 =A P. R,}.shuffle.map{|i|#take an array of the coordinates of the endpoints of each line, shuffle, then for each line
    b=i.sum/2                                   #b = midpoint of line, convert ASCII sum to number (average of the two coordinates)
    a=i.ord                                     #a = first endpoint of line, convert ASCII to number (no need to write i[0].ord)
    c=b*2-a                                     #c = second endpoint of line (calculating is shorter than writing i[1].ord)
    t[a]&&t[c]||(                               #if both endpoints have already been visited, line is completely blocked, do nothing. ELSE
      t[a]&&t[b]||d[a,b]                        #if first endpoint and midpoint have not both been visited, draw first half of line
      t[b]&&t[c]||d[b,c]                        #if second endpoint and midpoint have not both been visited, draw second half of line
      t[a]=t[b]=t[c]=1                          #mark all three points of the line as visited
    )
  }
}

Thêm đầu ra mẫu

Chúng được thực hiện với một phiên bản cũ hơn của chương trình. Sự khác biệt duy nhất là vị trí của hexaglyph trong cửa sổ bây giờ hơi khác nhau.

nhập mô tả hình ảnh ở đây


mothereff.in/byte-counter counts my submission as 196 bytes, but for some reason Shoes counts it as 202.Tôi không biết 100% có đúng không, nhưng tôi nghĩ rằng lý do mà Giày tính mã của bạn là 202 byte thay vì 196 là vì dòng mới của bạn thực sự là một chuỗi hai ký tự "\ r \ n." Điều này làm cho mỗi dòng mới được tính hai lần. Đây là câu trả lời tràn ngăn xếp liên quan đến \ r và \ n.
K Zhang

Hehe Tôi không thể vượt qua cái tên Ruby with Shoes XD
Beta Decay

3

Trăn, 604 591 574 561 538 531 536 534 528 493 483 452 431 420 419 415 388 385 385 384 byte

Tôi đã điều chỉnh ý tưởng của Level River St về việc kiểm tra xem một dòng có bị chặn hay không bằng cách kiểm tra xem cả hai điểm cuối của dòng đã được truy cập trước đó chưa. Điều này tiết kiệm 27 byte. Gợi ý chơi golf chào mừng.

Chỉnh sửa: Sửa lỗi và chơi gôn g(p,q)trong 3 byte. Chơi gôn Lcho một byte.

from turtle import*
from random import*
R=range
G=goto
*L,=R(9)
shuffle(L)
a=[0]*13
ht()
T=12
c=[(j.imag,j.real)for j in(1j**(i/3)*T*.75**(i%2/2)for i in R(T))]+[(0,0)]
def g(p,q):pu();G(c[p]);a[p]*a[q]or pd();G(c[q])
for m in L:
 p=2*m;x,y,z=R(p,p+3)
 if m<6:
  if a[x]*a[z%T]<1:g(x,y);g(y,z%T);a[x]=a[y]=a[z%T]=1
 else:
  if a[p-11]*a[p-5]<1:g(p-11,T);g(p-5,T);a[p-11]=a[p-5]=a[T]=1

Ungolfing:

from turtle import*
from random import*

def draw_line(points, p_1, p_2):
    penup()
    goto(points[p_1])
    if not (a[p] and a[q]):
        pendown()
    goto(points[p_2])

def draw_glyph():
    ht()
    nine_lines = list(range(9))
    shuffle(nine_lines)
    size = 12
    center = [0,0]

    points = []
    for i in range(12):      # put in a point of a dodecagon
                             # if i is even, keep as hexagon point
                             # else, convert to hexagon midpoint
        d = 1j**(i/3) * 12   # dodecagon point
        if i%2:
            d *= .75**.5     # divide by sqrt(3/4) to get midpoint
        points += (d.imag, d.real)
    points.append(center)

    a = [0]*13
    for m in nine_lines:
        p = 2*m
        if m<6:
            x, y, z = p, p+1, p+2
            if not (a[x] and a[z%12]):
                draw_line(points, x, y)
                draw_line(points, y, z%12)
                a[x] = a[y] = a[z%12] = 1
        else:
            if not (a[p-11] and a[p-5]):
                draw_line(p-11, 12)
                draw_line(p-5, 12)
                a[p-11] = a[p-5] = a[12] = 1

Bản thân hexa-glyphs khá nhỏ khi chúng tôi sử dụng hình lục giác 12 pixel làm cơ sở (vì lý do chơi gôn). Dưới đây là một số ví dụ hexa-glyphs (xin lỗi vì cắt xén kém):

Một ví dụ hexa-glyph Một ví dụ hexa-glyph Một ví dụ hexa-glyph Một ví dụ hexa-glyph Một ví dụ hexa-glyph Một ví dụ hexa-glyph


Có thể lưu một vài byte:R=range;G=goto
Tim Čas
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.