Сантехнічні випадкові шляхи


23

Напишіть програму або функцію, яка займає три цілі числа, ширину w, висоту hта кількість кроківs . Ви будете малювати непересічні кроки випадкових прогулянок s довгими зображеннями 5*wна 5*hпіксель, де кожні 5 на 5 піксельних комірок або порожні (чисто бежевий), або одна з цих дванадцяти простих «труб»:

збільшені труби

Зображення вгорі збільшується для деталізації. Ось труби фактичного розміру:

труби

(Сірі лінії призначені лише для розділення типів труб.)

Випадкова прогулянка буде єдиним безперервним контуром труби, який починається в одній кінцевій точці труби (одній із чотирьох нижніх типів труб) і закінчується в іншій кінцевій точці труби.

Почніть з порожнього wза hсіткою і випадковим чином виберіть одну клітинку для початкової точки. Потім випадковим чином виберіть один із чотирьох напрямків для початку та намалюйте відповідну кінцеву точку труби. Ця початкова комірка означає перший крок у вашій прогулянці, і кожен раз, коли ви малюєте нову клітинку або перезаписуєте існуючу, вона вважається ще одним кроком.

Тепер, неодноразово, випадковим чином вибирайте, щоб рухатись праворуч, ліворуч або прямо, малюючи відповідну комірку труби, якщо обраний напрямок є дійсним. Зворотній sшлях і повторно вибирайте, якщо напрямок недійсний, поки не буде сформований повний шлях кроку. Шлях повинен закінчуватися кінцевою точкою труби, яка може бути в будь-якій точці сітки, залежно від курсу, який пройшов шлях.

Дуже важливо відзначити, що можуть бути перезаписані лише дві прямі комірки труби, і лише пряма комірка труби протилежної орієнтації, результатом чого є клітина перетину. В іншому випадку всі труби повинні бути розміщені в порожніх осередках.

Коли проведено перетин, частина шляху, яка знаходиться далі від вихідної комірки, повинна бути намальована зверху.

Від вас залежить, чи має сітка періодичні граничні умови (PBC), тобто, чи буде виходити труба, що виходить з однієї сторони сітки з іншого боку. Без PBC межа сітки вважається бар'єром, на який можна зіткнутися так само, як і в інших трубах.

Спеціальні справи

  • Коли s0, жодних труб не слід малювати, а вихід має бути порожнім 5*wпо 5*hзображенню (тобто всі бежеві).
  • Коли s1 заглушка на одній трубі

    збільшена заглушка труби(Фактичний розмір: заглушка труби)

    слід намалювати у випадково вибраній вихідній комірці.

Інші подробиці

  • Ви можете припустити, що sце максимум, w*hтому шлях завжди буде можливим. (Хоча можливі довші шляхи через перехрестя.)
  • wі hзавжди буде позитивним.
  • Всі випадкові вибори повинні бути однаково випадковими. наприклад, ви не повинні уникати перехресть, коли вони можливі, навіть якщо це полегшує проблему. Генератори псевдовипадкових чисел дозволені.
  • Будь-які три візуально чіткі кольори можуть використовуватися замість чорного, синього та бежевого.
  • Ваші вихідні зображення можуть бути збільшені таким чином , що вони на насправді 5*w*kвід 5*h*kточок , де kє позитивним цілим числом. (Розширення будь-яких прикладів, які ви публікуєте, рекомендується, навіть якщо вашk належить 1.)
  • Може використовуватися будь-який загальний формат файлу зображень без втрат, і зображення може бути збережено у файл, відображатися або промальовуватися в режимі 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=6, якщо припустити PBC:


Ось можливий вихід для w=3, h=3, s=9, якщо припустити PBC:

Зауважте, що шляху не потрібно було охоплювати всі комірки через перетин, рахуючи два кроки. Крім того, ми можемо зробити висновок, що кутова кінцева точка була вихідною коміркою, оскільки шляхопровід перетину повинен бути намальований згодом. Таким чином, ми можемо зробити висновок про послідовність випадкових виборів:

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
Вся ідея - це лише випадкова прогулянка, правда?
Акангка

Рядок 2: You will be drawing a non-self-intersecting random walk... це самопересічення чи ні?
edc65

@ChristianIrwan Ну не дуже. Випадкові прогулянки, як правило, можуть подвоюватися назад або взагалі не перетинатися. Це унікальний випадок, оскільки проводяться перехрестя, але вони не вважаються такими, що відтягують ту саму землю. І так, це може бути у форматі ascii-art або щось подібне, але мені подобається ідея зробити приємні образи.
Захоплення Кальвіна

2
@ChristianIrwan я вже відповів, що, коли я сказав: "Так, це може бути у форматі ascii-art або щось подібне, але мені подобається ідея робити красиві образи". Я вирішу не включати 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 рази:
  • вибрати випадковий напрямок; якщо ця сторона вже використана, відмовте і почніть спочатку
  • позначте сторону як використану та намалюйте фактичну трубу на зображенні (намалюйте 3 суміжні лінії довжиною 6, починаючи справа "після" центрального пікселя поточної комірки, потім додайте крапку, щоб закріпити кінець труби)
  • оновити поточну позицію (перехід до наступної комірки)
  • перевірити, чи клітинка порожня чи це дійсна перехрестя; якщо ні, не виходить з ладу і почніть спочатку
  • позначте сторону в зворотному напрямку, як використовується в цій комірці, а потім продовжте цикл

1

QBasic, 517 516 байт

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, hіs з введення користувача, розділений комами.
  • Виведення виводиться на екран. Поки програма шукає рішення, ви можете побачити, що часткові рішення мерехтять минулим.
  • Не використовує періодичні граничні умови. Мені було простіше намалювати і перевірити з'єднання труб, не турбуючись про те, що половина труби знаходиться з одного боку решітки і половина з іншого.

Підхід тут полягає в тому, щоб спробувати випадковий напрямок на кожному кроці і почати все спочатку, якщо це призведе до недійсного ходу. Ми малюємо труби за рішенням напрямків і використовуємо POINTдля тестування точок на екрані для наших дійсних умов. Хід дійсний, якщо він не виходить за межі сітки та:

  1. Переміщена до комірки порожня; або
  2. І те й інше
    1. Осередок, що переміщується, містить трубу, що проходить прямо горизонтально або вертикально, і
    2. Нова трубна секція не подвоює існуючу секцію труби

Як і відповідь CJam aditsu , цей код дуже повільний і може бути розумно повільним, якщо 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 у роботі. Ось приклад запуску:

люкс сантехніка.bas в дії

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.