Đường dẫn ngẫu nhiên


23

Viết chương trình hoặc hàm có ba số nguyên, chiều rộng w, chiều cao hvà số bước s. Bạn sẽ vẽ một bước đi ngẫu nhiên không tự giao nhau sdài trên một hình ảnh 5*wtheo 5*hpixel trong đó cứ 5 ô 5 pixel là trống (màu be thuần khiết) hoặc một trong mười hai "ống" đơn giản này:

ống mở rộng

Hình ảnh trên được phóng to để hiển thị chi tiết. Dưới đây là các đường ống ở kích thước thực tế:

ống

(Các đường màu xám chỉ để tách các loại ống.)

Lối đi ngẫu nhiên sẽ là một đường ống liên tục duy nhất bắt đầu tại một điểm cuối đường ống (một trong bốn loại ống dưới cùng) và kết thúc tại điểm cuối đường ống khác.

Bắt đầu với một ô trống wbằng hlưới và chọn ngẫu nhiên một ô làm điểm bắt đầu. Sau đó chọn ngẫu nhiên một trong bốn hướng để bắt đầu và vẽ điểm cuối đường ống tương ứng. Ô bắt đầu này đánh dấu bước đầu tiên trong bước đi của bạn và mỗi khi bạn vẽ một ô mới hoặc ghi đè lên một ô hiện có, nó sẽ được tính là một bước khác.

Bây giờ, lặp đi lặp lại, chọn ngẫu nhiên để đi sang phải, trái hoặc thẳng, vẽ ô đường ống thích hợp nếu hướng được chọn là hợp lệ. Quay lại và chọn lại nếu một hướng không hợp lệ cho đến khi sđường dẫn bước hoàn chỉnh được hình thành. Đường dẫn phải kết thúc bằng điểm cuối đường ống, có thể ở bất kỳ đâu trên lưới, tùy thuộc vào khóa học mà đường dẫn đã đi.

Điều rất quan trọng cần lưu ý là chỉ có hai ô ống thẳng có thể được ghi đè và chỉ bởi ô ống thẳng có hướng ngược lại, kết quả là một ô giao nhau. Mặt khác, tất cả các ống phải được đặt trong các ô trống.

Khi một giao lộ được vẽ, một phần của đường dẫn nằm dọc từ ô bắt đầu sẽ được vẽ trên đầu.

Tùy thuộc vào việc lưới điện có các điều kiện biên định kỳ (PBC) hay không, tức là liệu một đường ống thoát ra từ một phía của lưới sẽ đi ra ở phía bên kia. Không có PBC, ranh giới lưới được tính là một rào cản mà bạn có thể gặp phải giống như các đường ống khác.

Trường hợp đặc biệt

  • Khi slà 0, không có đường ống nào được vẽ và đầu ra phải trống 5*wbằng 5*hhình ảnh (tức là tất cả màu be).
  • Khi scòn 1 ống còn sơ khai

    cuống ống mở rộng(Kích thước thực tế cuống ống:)

    nên được vẽ tại ô bắt đầu được chọn ngẫu nhiên.

Những chi tiết khác

  • Bạn có thể cho rằng đó slà nhiều nhất w*hvì vậy một con đường sẽ luôn luôn có thể. (Mặc dù các đường dẫn dài hơn có thể do các giao lộ.)
  • whsẽ luôn tích cực.
  • Tất cả các lựa chọn ngẫu nhiên phải được thống nhất ngẫu nhiên. ví dụ: bạn không nên tránh giao lộ khi có thể ngay cả khi điều đó làm cho vấn đề dễ dàng hơn. Máy phát điện giả ngẫu nhiên được cho phép.
  • Bất kỳ ba màu khác biệt trực quan có thể được sử dụng thay cho màu đen, xanh lam và màu be.
  • Hình ảnh đầu ra của bạn có thể được phóng to để chúng thực sự 5*w*kbằng 5*h*kpixel trong đó klà một số nguyên dương. (Mở rộng bất kỳ ví dụ nào bạn đăng được khuyên ngay cả khi bạn klà 1.)
  • Bất kỳ định dạng tệp hình ảnh lossless phổ biến nào cũng có thể được sử dụng và hình ảnh có thể được lưu vào một tệp, được hiển thị hoặc được phun thô vào thiết bị xuất chuẩn.

Mã ngắn nhất tính bằng byte thắng.

Ví dụ

(Tất cả được mở rộng thêm 500%.)

Nếu đầu vào là w=2, h=1, s=0thì đầu ra sẽ luôn là:

Nếu đầu vào là w=2, h=1, s=1đầu ra sẽ là một trong những hình ảnh có cơ hội như nhau:

Nếu đầu vào là w=2, h=1, s=2thì đầu ra sẽ là

hoặc có thể

nếu lưới được coi là có PBC.

(Lưu ý rằng bắt đầu đường dẫn như thế sẽ không thể thực hiện bước thứ hai.)


Dưới đây là một số kết quả đầu ra có thể cho w=3, h=2, s=6, giả sử PBC:


Đây là một đầu ra có thể cho w=3, h=3, s=9, giả sử PBC:

Lưu ý rằng đường dẫn không cần phải bao gồm tất cả các ô do giao lộ được tính là hai bước. Ngoài ra, chúng ta có thể suy luận rằng điểm cuối góc là ô bắt đầu do cầu vượt giao cắt phải được rút ra sau đó. Do đó chúng ta có thể suy ra chuỗi các lựa chọn ngẫu nhiên đã được thực hiện:

start at top left, facing east
go straight
go right
go right
go right
go straight
go left
go right
end

Cuối cùng, đây là ví dụ về w=4, h=5, s=20w=4, h=5, s=16:


1
Toàn bộ ý tưởng chỉ là một cuộc dạo chơi ngẫu nhiên, phải không?
Akangka

Hàng 2: You will be drawing a non-self-intersecting random walk... nó có tự giao nhau hay không?
edc65

@ChristianIrwan Vâng không thực sự. Đi bộ ngẫu nhiên thường có thể tự nhân đôi hoặc không giao nhau. Đây là một trường hợp duy nhất kể từ khi các giao lộ được thực hiện nhưng chúng không được tính là lấy lại cùng một mặt bằng. Và vâng, điều này có thể ở định dạng nghệ thuật ascii hoặc một cái gì đó nhưng tôi thích ý tưởng tạo ra những hình ảnh đẹp mắt.
Sở thích của Calvin

2
@ChristianIrwan Tôi đã trả lời rằng khi tôi nói "Và vâng, đây có thể là định dạng nghệ thuật ascii hoặc một cái gì đó nhưng tôi thích ý tưởng tạo ra những hình ảnh đẹp mắt." Tôi chọn không liên quan đến nghệ thuật ascii.
Sở thích của Calvin

1
"Nút thắt" có được phép không?
aditsu

Câu trả lời:


4

CJam, 274

q~:K;:B;:A;{0aA*aB*:M5*5f*:I;K{[Bmr:QAmr:P]5f*:R;3Ym*{R.+:)2{1$0=I=2$W=@tI@0=@t:I;}:F~}/R2f+1FK({MQ=P=:EY4mr:D#&1{{MQMQ=PE2D#+tt:M;}:G~7,1>[W0_1_0_W]2/D=:Off*{[QP]5f*2f+.+_:H1F_OW%.+2FOW%.m2F}/H2FO~P+:P;Q+:Q;MQ=P=:E_5YD2%-*=!JK2-=+*1{D2+4%:D;G}?}?}fJ]}0?}g'P2NA5*SI,N2NI:+N*

Dùng thử trực tuyến

Sử dụng PBC, đầu ra ở định dạng PGM. Bạn có thể xóa phần :+gần cuối để có đầu ra hình ảnh đẹp hơn trong trình duyệt.

Nó rất chậm đối với đầu vào lớn hơn, đặc biệt là nếu số bước gần với khu vực.

Kết quả ví dụ cho đầu vào 4 3 10(tỷ lệ 500%):

thí dụ

Giải thích ngắn gọn:

Cách tiếp cận chung là:

  • lặp lại tất cả các bước sau cho đến khi thành công:
  • khởi tạo 2 ma trận: một bản ghi mà các mặt đang được sử dụng trong mỗi ô và một cho hình ảnh
  • nếu s = 0, chúng ta đã hoàn thành, khác:
  • chọn một ô ngẫu nhiên và vẽ một hình vuông, sau đó thực hiện s-1 lần sau:
  • chọn một hướng ngẫu nhiên; nếu bên đó đã được sử dụng, thất bại và bắt đầu lại
  • đánh dấu bên là được sử dụng và vẽ đường ống thực tế trong hình ảnh (vẽ 3 đường liền kề có độ dài 6, bắt đầu ngay "sau" pixel trung tâm của ô hiện tại, sau đó thêm một dấu chấm vào nắp cuối của đường ống)
  • cập nhật vị trí hiện tại (di chuyển đến ô tiếp theo)
  • kiểm tra xem ô trống hay nó là dấu gạch chéo hợp lệ; nếu không, thất bại và bắt đầu lại
  • đánh dấu bên theo hướng ngược lại như được sử dụng trong ô này, sau đó tiếp tục vòng lặp

1

QBasic, 517 516 byte

RANDOMIZE TIMER
SCREEN 9
INPUT w,h,s
1CLS
IF s=0GOTO 9
x=5*INT(RND*w)
y=5*INT(RND*h)
GOSUB 7
FOR k=1TO s-1
r=INT(RND*4)+1
a=x+5*((r=2)-(r=4))
b=y+5*((r=1)-(r=3))
c=(POINT(a,b+2)*POINT(a+4,b+2)+POINT(a+2,b)*POINT(a+2,b+4))*(0=POINT((a+x)\2+2,(b+y)\2+2))
IF((0=POINT(a+2,b+2))+c)*(a>=0)*(b>=0)*(a<5*w)*(b<5*h)=0GOTO 1
x=a
y=b
GOSUB 7
o=1AND r
p=x-2+3*o-5*(r=2)
q=y+1-3*o-5*(r=1)
u=p+3-o
v=q+2+o
LINE(p,q)-(u,v),7,B
LINE(p+o,q+1-o)-(u-o,v-1+o),1
NEXT
9IF c GOTO 1
END
7LINE(x+1,y+1)-(x+3,y+3),7,B
PSET(x+2,y+2),1
RETURN
  • Mất w, hstừ người dùng nhập vào, bằng dấu phẩy.
  • Đầu ra được vẽ trên màn hình. Trong khi chương trình đang tìm kiếm một giải pháp, bạn có thể thấy các giải pháp một phần nhấp nháy.
  • Không sử dụng điều kiện biên định kỳ. Tôi thấy việc vẽ và kiểm tra kết nối các đường ống dễ dàng hơn mà không phải lo lắng về một nửa đường ống nằm ở một bên của lưới và một nửa ở phía bên kia.

Cách tiếp cận ở đây là thử một hướng ngẫu nhiên ở mỗi bước và bắt đầu lại từ đầu nếu nó dẫn đến một động thái không hợp lệ. Chúng tôi vẽ các đường ống khi các hướng được quyết định và sử dụng POINTđể kiểm tra các điểm trên màn hình cho các điều kiện hợp lệ của chúng tôi. Di chuyển là hợp lệ nếu nó không đi ra ngoài ranh giới của lưới và:

  1. Các ô được chuyển đến trống rỗng; hoặc là
  2. Cả hai
    1. Ô di chuyển đến chứa một đường ống đi thẳng, theo chiều ngang hoặc chiều dọc và
    2. Phần ống mới không nhân đôi một phần ống hiện có

Giống như câu trả lời CJam của aditsu , mã này rất chậm và có thể chậm đến mức khó tin nếu slà một phần đáng kể w*h. Trong thiết lập QB64 của tôi, nó đưa ra một câu trả lời 5,5,19khá nhanh chóng, nhưng mất nhiều thời gian hơn tôi sẵn sàng chờ đợi 5,5,20.

Nếu bạn muốn chạy các ví dụ lớn hơn / dày đặc hơn, đây là cách tiếp cận ban đầu của tôi bằng cách sử dụng tìm kiếm theo chiều sâu . Nó hiệu quả hơn nhiều, với chi phí lên tới 300 byte.

RANDOMIZE TIMER
SCREEN 9
INPUT w,h,s
DIM t(s),m(s)
0
FOR z=1TO s
t(z)=-1
NEXT
i=5*INT(RND*w)
j=5*INT(RND*h)
k=1
1CLS
IF s=0GOTO 9
x=i
y=j
GOSUB 7
FOR z=1TO k-1
r=m(z)
GOSUB 6
x=a
y=b
GOSUB 7
o=1AND r
p=x-2+3*o-5*(r=2)
q=y+1-3*o-5*(r=1)
u=p+3-o
v=q+2+o
LINE(p,q)-(u,v),7,B
LINE(p+o,q+1-o)-(u-o,v-1+o),1
NEXT
IF c*(k=s)THEN k=k-1:GOTO 1 ELSE IF k=s GOTO 9
IF k<1GOTO 0
IF t(k)>=0GOTO 4
t(k)=0
f=30
WHILE f
r=INT(RND*4)+1
IF f AND 2^r THEN t(k)=t(k)*5+r:f=f-2^r
WEND
4r=t(k)MOD 5
m(k)=r
t(k)=t(k)\5
GOSUB 6
c=(POINT(a,b+2)*POINT(a+4,b+2)+POINT(a+2,b)*POINT(a+2,b+4))*(0=POINT((a+x)\2+2,(b+y)\2+2))
IF((0=POINT(a+2,b+2))+c)*(a>=0)*(b>=0)*(a<5*w)*(b<5*h)THEN k=k+1 ELSE IF t(k)>0GOTO 4 ELSE t(k)=-1:k=k-1
GOTO 1
6a=x+5*((r=2)-(r=4))
b=y+5*((r=1)-(r=3))
RETURN
7LINE(x+1,y+1)-(x+3,y+3),7,B
PSET(x+2,y+2),1
RETURN
9

Ví dụ đầu ra cho đầu vào 10, 10, 100, kích thước thực tế:Hệ thống ống nước ngẫu nhiên 10x10

Một phiên bản vẫn còn fancier có thể được tìm thấy trong ý chính này . Bên cạnh việc không được nhận xét và nhận xét kỹ lưỡng, nó tăng tỷ lệ đầu ra theo một yếu tố không đổi và cho phép đặt độ trễ giữa các bước, cho phép bạn xem thuật toán DFS tại nơi làm việc. Đây là một ví dụ chạy:

deluxe plenses.bas trong hành động

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.