Випадкове мистецтво дня ASCII №5: алмазна плитка


21

Збільшити час!

Це розстрочка №5 як моєї Random Golf of the Day, так і серії ASCII Art of the дня з оптимізатора . Ваші подання в цьому виклику будуть зараховані до обох таблиць лідерів (ви можете знайти пов’язані публікації). Звичайно, ви можете ставитися до цього, як до будь-якого іншого виклику з гольфу з кодом, і відповідати на нього, не турбуючись про будь-яку серію.

Отвір 5: Алмазна плитка

Звичайний шестикутник завжди може бути викладений діамантами так:

Ми будемо використовувати художнє представлення цих плиток ASCII. Для шестикутника довжиною в бік 2 існує 20 таких обрешіток:

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

Враховуючи бічну довжину N, слід створити таку плитку для шестикутника бічної довжини Nнавмання. Точний розподіл не має значення, але кожну плитку потрібно повернути з ненульовою ймовірністю.

Тому що N ≤ 4ваші подання повинні створити плитку протягом 1 хвилини принаймні 80% часу, і щонайменше 80% облицювань потенційно повинні бути сформовані протягом 1 хвилини. Більшість підходів не повинні турбуватися щодо цього правила (це дуже поблажливо) - це лише для виключення дуже наївних алгоритмів на основі відкидання, які генерують довільні рядки, поки не трапиться плитка.

Можливо, ви хочете знати, що загальна кількість можливих нахилів для даного N можна знайти в OEIS A008793 .

Ви можете написати повну програму або функцію і взяти вхід через STDIN (або найближчу альтернативу), аргумент командного рядка або аргумент функції та виробляти вихід через STDOUT (або найближчу альтернативу), значення повернення функції або параметр функції (out).

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

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

Табло лідерів

Перший пост кожної серії генерує таблицю лідерів.

Щоб переконатися, що ваші відповіді відображаються, будь ласка, почніть кожну відповідь із заголовка, використовуючи такий шаблон Markdown:

# Language Name, N bytes

де Nрозмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:

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

(Мова наразі не відображається, але фрагмент вимагає і аналізує його, і я можу додати мовну таблицю лідерів за мовою в майбутньому.)


3
Чи тільки я продовжує бачити приклад зображення в 3D?
LegionMammal978

3
@ LegionMammal978 Ні, це абсолютно нормально. ;) (І це, мабуть, також хороший спосіб вирішити виклик.)
Мартін Ендер

For N ≤ 4, your submission must produce a tiling within 1 minute at least 80% of the time.занадто просто: 80% часу те саме, основна плитка, інакше я знаходжу іншу плитку в будь-який час, коли мені захочеться
edc65

@ edc65 Добре, дозвольте перефразувати це.
Мартін Ендер

Відповіді:


10

CJam, 105 байт

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;

Новий рядок додано, щоб уникнути прокрутки. Спробуйте в Інтернеті

Пояснення:

Це рішення починає кожен рядок як зигзаг, після чого розміщує на ньому N підкреслення, виходячи з їх положення в попередньому рядку та пари правил. Я отримав це з серії спостережень, дивлячись на вихід як на звичайну 2D матрицю символів:

  • кожен рядок має рівно N підкреслень
  • підкреслення можна замінити на / або \, щоб зробити ідеально повторюваний зигзагоподібний візерунок ( /\у верхній половині, \/у нижній половині)
  • Підкреслення не можуть торкатися сторін і не можуть примикати до іншого підкреслення
  • при переході до наступного рядка положення кожного підкреслення змінюється на -1, 0 або 1
  • більше того, /_/може змінюватися лише на -1 або 0, а \_\може змінюватися лише на 0 або 1
  • для початкових позицій підкреслення ми можемо використовувати "_ "малюнок або " _"візерунок, обидва - це добре
  • вищезазначених правил достатньо для отримання всіх облицювань

Тому я вирішив застосувати це, зберігаючи попередні позиції підкреслення, модифікуючи їх випадковим фактором (2 варіанти для кожного підкреслення) і повторюючи, поки правила не будуть виконані. У процесі оптимізації я перейшов до позицій підкреслення щодо лівої частини шестикутника (не враховуючи пробілів).

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

Стара "3D" версія, 189 байт:

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*

Спробуйте в Інтернеті


+1 за дивовижну роботу, а також тому, що ще один голос поставив би вас за 10 кп, але в основному за дивовижну роботу. (Ой, погляньте на це. Поздравляю 10 к :))
Олексій А.

Чудовий аналіз шаблонів! Я використаю це для своєї відповіді.
anatolyg

6

Python 2, 337 335 324 318 311 300 296 байт

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)

Ідея полягає в тому, щоб спочатку створити шестикутник з алмазів, як це:

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

А потім заповніть її низхідними контурами підкреслення, наприклад:

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

Кінцевий результат із доданими шляхами виглядатиме приблизно так:

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

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

Невикористаний код:

# 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
Я щойно помітив, що ваш висновок здається неправильним. Ви отримали трикутники у ваших двох вищих результатах (праворуч угорі та знизу праворуч).
Мартін Ендер

1
@MartinEnder Приклади показали лише один "шлях підкреслення", щоб показати ідею алгоритму. Кінцевий вихід має всі шляхи (у цьому випадку 2), що виключає трикутники. Я додав і в прикладах кінцевого результату.
Матті

О, я бачу, це має сенс. Дякуємо за роз’яснення.
Мартін Ендер

2
Я думаю , що ви можете скоротити randint(0,1)*(p<n*3+i*2-j)до randint(0,p<n*3+i*2-j).
12Me21

О, так, дякую!
Матті

4

Перл, 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.$/}

Спробуй мене .


Здається, завжди створюється однакова плитка (принаймні, на ideone)
aditsu

@aditsu, Ideone показує кешований результат, якщо просто натиснути на посилання. Вам потрібно розщедритися, щоб фактично запустити його знову.
nutki

2

JavaScript ( ES6 ), 376 416 494

Просто бути там ...

Це побудує всі обшивки, а потім виберіть випадковий. Час 232848 обрізів для N = 4 становить ~ 45 сек на моєму ноутбуці. Я не пробував N = 5.

Будучи EcmaScript 6, він працює лише на 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>


У Chromium 42 я отримую "Uncaught SyntaxError: Unexpected token =>" та "Uncaught ReferenceError: go не визначено"
aditsu

1
@aditsu це ES6, Chrome: немає Firefox: так. Хіба це не відомий факт?
edc65

Я поняття не мав, я очікував, що Chromium використовуватиме найновіше і найголовніше, що називається - мабуть, не - JavaScript. Дякуємо за пояснення.
aditsu

Я запустив його зараз у firefox (31.5.3), і він працює для N = 1, 2 або 3, але для N = 4 він працює близько 10 секунд, закінчується і нічого не показує (і в консолі немає помилок )
aditsu

@aditsu не впевнений ... можливо, JavaScript у пісочниці спокійно вбивається, коли перевищує обмеження часу dom.max_script_run_time. Це глобальна перевага в about: config, моя встановлена ​​на 30.
edc65

1

SmileBASIC, 241 байт

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

Сильно спираючись на відповідь Матті

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