배관 임의 경로


23

세 개의 정수, 너비 w, 높이 h및 걸음 수 를 취하는 프로그램이나 함수를 작성하십시오 s. 당신은 비 자기 교차 그리기됩니다 랜덤 워크 (random walk)의 s A의 긴 단계 5*w5*h픽셀마다 5 × 5 픽셀 셀 중 하나를 빈 (순수한 베이지)는 이미지 또는 이들 열두 간단한 "파이프"중 하나를

확대 파이프

위 이미지는 확대하여 자세히 보여줍니다. 실제 크기의 파이프는 다음과 같습니다.

파이프

회색 선은 파이프 유형을 구분하기위한 것입니다.

랜덤 보행은 하나의 파이프 끝점 (하단 4 개 파이프 유형 중 하나)에서 시작하여 다른 파이프 끝점에서 끝나는 단일 연속 파이프 경로입니다.

빈 시작 w으로 h그리드 무작위 출발점으로 하나 개의 셀을 선택합니다. 그런 다음 시작하는 네 방향 중 하나를 임의로 선택하고 해당 파이프 끝점을 그립니다. 이 시작 셀은 보행의 첫 번째 단계이며 새 셀을 그리거나 기존 셀을 덮어 쓸 때마다 다른 단계로 계산됩니다.

이제 반복적으로 선택한 방향이 유효한 경우 적절한 파이프 셀을 그려 오른쪽, 왼쪽 또는 직선으로 임의로 선택하십시오. 전체 s단계 경로가 형성 될 때까지 방향이 유효하지 않은 경우 역 추적하고 다시 선택하십시오 . 경로는 파이프 끝점으로 끝나야합니다. 파이프 끝점은 경로의 경로에 따라 그리드의 어느 곳에 나있을 수 있습니다.

두 개의 직선 파이프 셀만 덮어 쓸 수 있으며 반대 방향의 직선 파이프 셀만 결과를 교차 셀로 만들 수 있습니다. 그렇지 않으면 모든 파이프를 빈 셀에 배치해야합니다.

교차점이 그려 질 때 시작 셀에서 더 나아간 경로 부분이 맨 위에 그려 져야합니다.

그리드에 주기적 경계 조건 (PBC)이 있는지 여부, 즉 그리드의 한 쪽에서 나가는 파이프가 다른 쪽에서 나올지 여부는 사용자에게 달려 있습니다. PBC가 없으면 그리드 경계는 다른 파이프와 마찬가지로 실행할 수있는 장벽으로 계산됩니다.

특수한 상황들

  • 경우 s0 아니 파이프 그려지지되어야하며, 출력은 비어 있어야 5*w의한 5*h화상 (즉, 모든 베이지).
  • 경우 s단일 관 스터브 1

    확대 파이프 스터브(실제 크기 : 파이프 스텁)

    임의로 선택된 시작 셀에 그려 져야합니다.

그 외 세부 사항

  • s최대 라고 가정 할 수 있으므로 w*h항상 경로가 가능합니다. 교차로로 인해 더 긴 경로가 가능합니다.
  • w그리고 h항상 긍정적 인 것입니다.
  • 모든 무작위 선택은 균일하게 무작위 이어야합니다 . 예를 들어, 문제가 더 쉬워 지더라도 가능할 때 교차로를 만들지 마십시오. 의사 난수 생성기가 허용됩니다.
  • 검은 색, 파란색 및 베이지 색 대신 시각적으로 다른 3 가지 색상을 사용할 수 있습니다.
  • 귀하의 출력 이미지는 진짜 너무 확대 될 수 있습니다 5*w*k에 의해 5*h*k픽셀 k양의 정수이다. ( k1 이더라도 게시 한 예제를 확대하는 것이 좋습니다 .)
  • 일반적인 무손실 이미지 파일 형식을 사용할 수 있으며 이미지를 파일에 저장하거나 표시하거나 stdout으로 뿌릴 수 있습니다.

바이트 단위의 가장 짧은 코드가 이깁니다.

(모두 500 % 확대)

입력이 있으면 w=2, h=1, s=0출력은 항상 다음과 같습니다.

입력이 입력 w=2, h=1, s=1되면 출력은 동일한 기회로 다음 이미지 중 하나가됩니다.

입력이 입력 w=2, h=1, s=2되면 출력은

또는 가능

그리드에 PBC가 있다고 가정합니다.

(경로를 시작하면 두 번째 단계는 불가능합니다.)


w=3, h=2, s=6PBC를 가정 할 때 가능한 몇 가지 출력은 다음과 같습니다 .


w=3, h=3, s=9PBC를 가정하면 가능한 결과는 다음과 같습니다 .

교차로가 두 단계로 계산되어 경로가 모든 셀을 포함 할 필요는 없습니다. 또한 교차로 육교가 이후에 그려 졌으므로 코너 끝 점이 시작 셀이라고 추론 할 수 있습니다. 따라서 우리는 무작위로 선택된 순서를 추론 할 수 있습니다.

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

마지막으로 w=4, h=5, s=20와의 예는 다음 과 w=4, h=5, s=16같습니다.


1
전체 아이디어는 무작위로 걷는 것입니다.
Akangka

2 행 : You will be drawing a non-self-intersecting random walk... 자체 교차 여부입니까?
edc65

@ChristianIrwan 글쎄요. 임의의 보행은 일반적으로 스스로 두 배로 돌아가거나 전혀 교차하지 않을 수 있습니다. 교차로가 만들어졌지만 동일한지면을 회귀하는 것으로 간주되지 않기 때문에 이것은 독특한 경우입니다. 그리고 예, 이것은 아스키 아트 형식 일 수도 있지만 멋진 이미지를 만드는 아이디어를 좋아합니다.
캘빈의 취미 22

2
@ChristianIrwan 나는 이미 "아시 아트 형식이나 다른 형식 일 수 있지만 멋진 이미지를 만드는 아이디어를 좋아한다"고 대답했습니다. 나는 ascii-art를 포함하지 않기로 선택합니다.
캘빈의 취미

1
"매듭"이 허용됩니까?
aditsu

답변:


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*

온라인으로 사용해보십시오

PBC를 사용하여 PGM 형식으로 출력합니다. :+끝 부분을 제거 하면 브라우저에서 더 나은 시각적 출력을 얻을 수 있습니다 .

특히 스텝 수가 영역에 가까우면 더 큰 입력에 대해 매우 느립니다.

입력 결과 예 4 3 10(500 % 스케일) :

예

간단한 설명 :

일반적인 접근 방식은 다음과 같습니다.

  • 성공할 때까지 다음 단계를 모두 반복하십시오.
  • 2 개의 행렬 초기화 : 각 셀에서 어느 쪽이 사용되고 있는지 한 번의 기록과 이미지에 대한 한 번의 기록
  • s = 0이면 완료된 것입니다.
  • 임의의 셀을 선택하고 사각형을 그린 다음 s-1 번을 수행하십시오.
  • 임의의 방향을 선택하십시오. 해당 측면이 이미 사용 된 경우 페일 오버하고 다시 시작하십시오.
  • 측면을 사용 된 것으로 표시하고 이미지에 실제 파이프를 그립니다 (현재 셀의 중심 픽셀 바로 뒤에서 시작하여 길이 6의 인접한 3 개의 선을 그린 다음 파이프의 끝을 덮는 점을 추가합니다)
  • 현재 위치 업데이트 (다음 셀로 이동)
  • 셀이 비어 있거나 유효한 교차인지 확인하십시오. 그렇지 않은 경우 실패하고 다시 시작하십시오.
  • 이 셀에 사용 된 것과 반대 방향으로 측면을 표시 한 다음 루프를 계속

1

Q 기본, 517516 바이트

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
  • 취하고 w, hs사용자 입력의 쉼표로 구분.
  • 화면에 출력이 그려집니다. 프로그램이 솔루션을 검색하는 동안 부분 솔루션이 깜빡이는 것을 볼 수 있습니다.
  • 주기적 경계 조건을 사용하지 않습니다. 파이프의 절반이 그리드의 한쪽에 있고 다른 절반은 걱정하지 않아도 파이프 연결에 대한 그리기 및 테스트가 더 쉽다는 것을 알았습니다.

여기서 접근하는 방법은 각 단계에서 임의의 방향을 시도하고 잘못된 움직임이 발생하면 처음부터 다시 시작하는 것입니다. 방향이 결정되면 파이프를 그리고 POINT유효 조건에 대한 화면의 포인트를 테스트 하는 데 사용 합니다. 그리드의 경계를 벗어나지 않는 이동은 다음과 같습니다.

  1. 이동 된 셀이 비어 있습니다. 또는
  2. 양자 모두
    1. 이동 된 셀에는 가로 또는 세로로 직선으로가는 파이프가 있습니다.
    2. 새 파이프 섹션은 기존 파이프 섹션을 두 배로 늘리지 않습니다.

aditsu의 CJam 답변마찬가지로이 코드는 매우 느리며의 s소수에 해당하면 엄청나게 느릴 수 있습니다 w*h. QB64 설정에서 5,5,19신속하게 답변을 얻을 수 있지만 기다릴 때보 다 시간이 오래 걸립니다 5,5,20.

더 크고 밀도가 높은 예제를 실행하려면 깊이 우선 검색을 사용하는 원래 방법이 있습니다. 300 바이트의 추가 바이트를 희생시키면서 훨씬 더 효율적입니다.

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

입력 10, 10, 100에 대한 출력 예 , 실제 크기 :10x10 랜덤 배관

이 요지 에서 더 멋진 버전을 찾을 수 있습니다 . 골프를 풀지 않고 철저하게 주석을 달는 것 외에도 출력을 일정한 비율로 확장하고 단계 사이에 설정된 지연을 허용하여 직장에서 DFS 알고리즘을 볼 수 있습니다. 다음은 예제 실행입니다.

디럭스 배관. 행동에 바

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.