Масштабуйте алмазну плитку


27

Будь-який звичайний шестикутник можна обробити алмазами, наприклад так:

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

Ми розглянемо вищенаведений розмір плитки 1(оскільки сторони алмазів виготовлені з однієї /або \кожної). Виглядає такий же розмір плитки 2:

      ____________ 
     /   /   /\   \  
    /___/___/  \___\ 
   /   /\   \  /\   \  
  /___/  \___\/  \___\ 
 /\   \  /   /\  /   /\  
/  \___\/___/  \/___/  \ 
\  /   /\   \  /   /\  /
 \/___/  \___\/___/  \/ 
  \   \  /   /\   \  /
   \___\/___/  \___\/ 
    \   \   \  /   /
     \___\___\/___/ 

Ваше завдання - отримати таку графічну плитку ASCII (за розміром 1), як вхід, разом із додатним цілим числом N(у десятковій чи одинарній формі ) із зазначенням розміру потрібного виводу. Потім слід вивести масштабовану версію тієї ж плитки.

Зауважте, що шестикутник може бути будь-якого розміру та розміром 1х1х1 (містить три діаманти).

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

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

Це кодовий гольф, тому найкоротша відповідь (у байтах) у виграші.

Приклад облицювання плит

Ось декілька вхідних обшивок, які ви можете використати для тестування ваших робіт.

 __
/_/\
\_\/

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

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

    ________
   /_/\_\_\_\
  /\_\/\_\_\_\
 /\/_/\/_/_/\_\
/\/\_\/_/_/\/\_\ 
\/\/_/\_\_\/\/_/
 \/\_\/_/\_\/_/
  \/\_\_\/_/_/
   \/_/_/_/_/

Наступний фрагмент містить відповідні виходи для входів N = 1через N = 6.


20
Я бачу, що вас цікавлять алмази зараз, коли у вас є один біля вашого імені користувача.
користувач12205

3
@ace: Ви знаєте, що вони кажуть: алмази - найкращий друг модератора.
Олексій А.

Я думаю, що знаю відповідь, але сподіваюся, що я помиляюся: провідні рядки вважатимуться провідним простором, який ви оголосили незаконним? Моє початкове рішення має N-1провідні порожні рядки. :(
Ретро Кораді

@RetoKoradi Дійсно, жодних провідних рядків немає. Вибачте.
Мартін Ендер

1
Я з'ясував. Коштує мене близько 10 байт. Не так вже й погано, як це виглядало, коли я вперше визнав проблему.
Рето Коради

Відповіді:


8

CJam, 85 79 76 72 байт

li:Tlf*NqN/T,f{ff{"_/"2$#_1<@+*~ST*@t}:+z{S+e`);e~{"_ "/"__"*W%}T2**N}/}

Розмір повинен бути на першому рядку. І алмаз випливає.

Не дуже гольф ... А половина персонажів виходила з деталей.

Пояснення (попередньої версії)

li:T            e# Read the size and save to T.
qN/             e# Read and split to lines.
\,fm*           e# Convert each character X to [X 0] [X 1]... [X T(]
{~              e# For each [X I] in each line:
    ST*         e# T spaces.
    \           e# I.
    "_\\"3$#    e# If X is '_, '\ or '/, return Y = 0, 1, -1 respectively.
    _W>@+       e# If it was '_ or '\, increase I by one.
    *(          e# I * Y - 1.
    @t          e# Set the character at that position to X.
}f%
:z:+            e# Make the returned lists from each iteration across T lines.
{S+e`);e~N+}%   e# Boring details to remove trailing spaces and append a newline.
T(>(\s          e# Boring details to extract the first line and only work on others.
{_{"_ "/"__"*W%}2*_@=!}g
                e# Boring details to make underlines expand left and right.

10

Пітон 2, 164

def g(s,n,j=1):
 for W in s.split("\n"):exec"O=p='';d=0\nfor c in W:q=' _'[j*'_'in p+c];e=[n-j,j-1][c=='/'];O+=q*(e+d)+[c,q][c>'^'];p=c;d=n+~e\nprint O;j-=1;"*j;j=n

Виведення на тестові справи.

Отже, що тут відбувається?

Основна ідея полягає в тому, що кожен персонаж в оригіналі вибухає в n*nблок. Наприклад, для n = 4 /може стати

   /
  /
 /
/___

Оригінальний символ з'являється один раз у кожному рядку, і там є прокладка в обидві сторони. Тут, це на лівій стороні , а й _справа. Лише нижній ряд може бути оббитий '_'; решта завжди ' '.

Основна складність полягає в тому, що накладка праворуч може залежати від майбутнього символу. Зокрема, '/ 'вона відрізняється від прокладки '/_', тому нам знадобиться деякий погляд вперед. Крім того, щоб уникнути пробілів, ми повинні зазначити, що ми перебуваємо на останньому символі та утримаємося від прокладки праворуч.

Обидві ці проблеми ми долаємо лише за допомогою ліворуч від поточного символу. Коли ми це робимо, ми також виконуємо праворуч від попереднього символу, використовуючи поточний символ прокладки. Отже, ми друкуємо праву підкладку, що заборговується з попереднього char, ліву підкладку з поточної char, потім поточної char. Також ми зберігаємо суму "заборгованості", яку потрібно заплатити наступним графіком.

Тепер перейдемо до коду.

def g(s,n,j=1):
    for W in s.split("\n"):
        while j:
            O=p='';d=0
            for c in W:
                q=' _'[j*'_'in p+c]
                e=[n-j,j-1][c=='/']
                O+=q*(e+d)+[c,q][c>'^']
                p=c
                d=n+~e
            print O;j-=1;
        j=n

Вхідний рядок є, sа коефіцієнт масштабу - n. Ми йдемо по черзі, друкуючи nрядки для кожного рядка введення W, при цьому копії індексуються j=n,n-1,...,2,1. Перший рядок копіюється лише один раз, що ми досягаємо цього, ініціалізуючи його jна 1, але змінюючи його на nкожен цикл.

Ми повторюємо через рядок введення, накопичуючи рядок для друку O. По-перше, ми з'ясуємо відповідний символ прокладки q, який є підкресленням, якщо ми знаходимося в нижній рядку, або поточний або попередній символ є підкресленням, інакше пробіл

Потім ми вирішуємо кількість накладки, яку потрібно поставити зліва ( e). Бо /це j-1(зменшується зі зменшенням кількості рядкових копій), а доповнення n-jдо \. Ми ставимось до інших персонажів так само. Наприклад, хоча _здається, що він дає ряд nпідкреслень, він фактично дає єдине підкреслення, підкреслене підкресленнями зліва та справа. Це здається неефективним, але це дозволяє нам працює _і в тих же рамках, /і \позиції «центрального» підкреслення не має значення, тому ми звалювати його і з \; цей вибір також змушує працювати верхній ряд без спеціальних кожухів.

Далі додаємо у вихідний рядок. Ми розібрали символ прокладки qта поточну суму прокладки e, але нам також потрібно пам’ятати про заборгованість під замовлення dз попереднього символу. Отже, додамо q*(e+d). Потім ми додаємо поточний символ c, за винятком того, що нам потрібно уникати підкреслення в нижньому рядку, який ми фіксуємо, перетворюючи підкреслення в символ прокладки.

Нарешті, ми записуємо суму заборгованості, яка доповнює n+~dпоточну ліворучну суму. Ми також записуємо поточний символ у p, щоб згодом дізнатися, чи був попередній символ _.


3

JavaScript ( ES6 ) 274 281 289 338

// GOLFED
F=(b,n)=>{
b=b[R='replace'](/ |_/g,c=>c[T='repeat'](n))[R](/_(?=[\\\/])/g,'_'[T](n))[R](/\/\\/g,`/${'  '[T](n-1)}\\`)
.split('\n');
for(i=l=b.length*n-n+1;--i;)
b[i]=i%n?b[i+1][R](/_/g,' ')[R](/\/ ?/g,' /')[R](/ \\(.)?/g,'\\$1$1')
:' '[T](i>l/2?n-1:0)+b[i/n];
return b.join('\n')}


// UNGOLFED
U=(b,n)=>{
  b=b
  .replace(/ |_/g,c=>c.repeat(n))
  .replace(/_(?=[\/\\])/g,'_'.repeat(n))
  .replace(/\/\\/g,`/${'  '.repeat(n-1)}\\`)
  .split('\n');
  for(i=l=b.length*n-n+1;--i;)
  {
    if(i%n)
     b[i]=b[i+1]
     .replace(/_/g,' ')
     .replace(/\/ ?/g,' /')
     .replace(/ \\/g,'\\ ').replace(/ +$/,'')
     .replace(/ \\(.)?/g,'\\$1$1')
    else {
      b[i]=b[i/n]
      if(i>l/2)b[i]=' '.repeat(n-1)+b[i];
    }
  }
  return b.join('\n')
}

//TEST

test=[
' __\n/_/\\\n\\_\\/',
'  ____\n /_/\\_\\\n/\\_\\/_/\\\n\\/_/\\_\\/\n \\_\\/_/',
'   ______\n  /_/_/\\_\\\n /_/\\_\\/\\_\\\n/\\_\\/_/\\/_/\\\n\\/_/\\_\\/_/\\/\n \\_\\/_/\\_\\/\n  \\_\\_\\/_/',
'    ________\n   /_/\\_\\_\\_\\\n  /\\_\\/\\_\\_\\_\\\n /\\/_/\\/_/_/\\_\\\n/\\/\\_\\/_/_/\\/\\_\\\n\\/\\/_/\\_\\_\\/\\/_/\n \\/\\_\\/_/\\_\\/_/\n  \\/\\_\\_\\/_/_/\n   \\/_/_/_/_/'
]

test.forEach(t=>{
  var row = '<td>'+t+'<td>'
  for(rr=2;rr<5;rr++)
    row += '<td>'+F(t,rr)+'</td>'
  OUT.innerHTML += '<tr>'+row+'</tr>'
})
td {
  font-family: monospace;
  white-space: pre;
}
(better full page)
<table id=OUT></table>


3

Пітон 2, 217 211 195 194 190

b,f,s='\/ '
R=str.replace
def m(g,n,z=1):
 for d in g.split('\n'):
    for i in range(z):a=z+~i;print[i,a][d[-1]>f]*s+R(R(R(R(d,s,s*n),'_','_ '[i<z-1]*(z+n-1)),f+b,f+s*2*i+b),b+f,b+s*2*a+f);z=n

6 байт завдяки Sp3000.

Виклик, mпричому перший аргумент - це алмаз як рядок, а другий аргумент - номер повторення.

Це ґрунтується на 3-кроковій послідовності заміни рядків:

  • Спочатку замініть підкреслення на пробіли 2n-1 або підкреслення, залежно від лінії.
  • По- друге, замінити /\з / \, з числом проміжних просторів , що йде від 2 до 2 * (п-1) по лініях.
  • В- третіх, замінити \/з \ /, з числом проміжних просторів , що йде від 2 * (п-1) до 2 по лініях.

Тоді є різноманітні розмови про те, щоб виправити провідні пробіли та отримати правильний перший рядок.

Зауважте, що заключним рядком програми має бути вкладка, а не 4 пробіли. Розмітка не підтримує вкладки.


Два гольфи: (i+(n-i+~i)*(d[-1]>f)) --> [i,n+~i][d[-1]>f]і ви використовуєте лише '_'один раз, тому ви витрачаєте байт, визначаючи його.
Sp3000

3

Пітон, 272 238 228 243 байт

Оновлена ​​версія, тепер приймає в якості введення одну рядок замість послідовності рядків. Також видаляється пробіл пробілів, який був у попередній версії. На жаль, ці зміни збільшують розмір.

s,u,f,b=' _/\\'
r=str.replace
def d(t,n,j=1):
 for p in t.split('\n'):
  for k in range(n-j,n):m,v=n+~k,'_ '[k<n-1];print r(r(r(r(r(r(r(r(p,f+u,'(_'),u+b,'_)'),s,s*n),u,v*n),f,s*m+f+s*k),'(',v*m+f+v*k),b,s*k+b+s*m),')',v*k+b+v*m).rstrip();j=n

Версія з пробілом та висловлюваннями, розбитіми на менші одиниці для читабельності:

s, u, f, b = ' ', '_', '/', '\\'
def d(t, n):
    j = n - 1
    for p in t:
        for k in range(j, n):
            m, v = n - 1 - k, '_ '[k < n - 1]
            q = p[:-1]
            q = q.replace(f + u, '(_')
            q = q.replace(u + b, '_)')
            q = q.replace(s, s * n)
            q = q.replace(u, v * n)
            q = q.replace(f, s * m + f + s * k)
            q = q.replace('(', v * m + f + v * k)
            q = q.replace(b, s * k + b + s * m)
            q = q.replace(')', v * k + b + v * m)
            print q
            j = 0

Основний підхід тут:

  1. Проведіть петлю по всіх рядках у введенні.
  2. Для кожного рядка переведіть цикл на вихідний розмір N, генеруючи вихідний рядок у кожній ітерації циклу. Існує особливий випадок для першого рядка, де генерується лише останній вихідний рядок, щоб уникнути генерації порожніх рядків на початку виводу.
  3. Замініть кожен рядок у рядку Nсимволами, де:
    • Кожен простір замінюється Nпробілами.
    • Кожне підкреслення замінюється Nпробілами для першої N -1ітерації циклу, і Nпідкреслюється для останньої ітерації циклу.
    • Штрихи та зворотні риси підбиті N - 1пробілами або підкресленнями.

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

Що я зробив для вирішення цього питання, це те, що я спочатку замінюю певні дві символьні комбінації різними символами, щоб я міг по-різному ставитися до них під час фактичної заміни. Наприклад, /_замінюється на (_. Після цього (фактично є "коса коса риса" з подальшим підкресленням, яка потім може бути відповідно замінена.

Основна програма, що використовується для тестування функції:

import sys
import Golf

n = int(sys.argv[1])
t = ''.join(sys.stdin).rstrip()

Golf.d(t, n)

1
n-1-kєn+~k
рекурсивна

На користь повного розкриття інформації: я щойно виявив, що моє рішення створює певні пробіли. Оскільки це не дозволено у вихідному визначенні, воно не відповідає вимогам. У гіршому випадку мені доведеться додати ще .rstrip()9 символів. Я сподіваюся, що зможу зробити краще, а також знайшов спосіб вирізати 5 символів.
Рето Коради

Схоже, ваш формат введення заборонений. sys.stdinне є допустимим вхідним параметром - потрібно маніпулювати самим рядком.
isaacg

Ну ви можете використовувати sys.stdinі , int(sys.argv[1])але ти не збираєшся отримати їх безкоштовно, чекаючи від них буде прийнятий в якості змінних (якщо це була чесна гра, то ви могли б також очікувати , псевдоніми rangeі replace` і все , що ще потрібно , щоб бути зумовити) .
Мартін Ендер

@ MartinBüttner У ньому йдеться про те, що я можу сприйняти дані як аргумент функції. Хіба це не те, що я роблю тут? Я все одно збирався змінити аргумент функції на список рядків. Це було б нормально? Це не дуже відрізняється, оскільки обидва stdinі список рядків - це послідовності рядків.
Рето Коради

1

Перл, 132

#!perl -p
INIT{$f=pop}s!.!$&x$f!ge;s! $!! while s!\\+\K\\|/(/)! $1!;
for$x(2..m!/!*$f){print y!_! !r;s!\\.?! \\!g;s!./(.)?!/$1$1!g;s!_ !__!g}

Комбінований вхід STDIN та ARGV. Приклад:

$ perl ~/hex.pl <~/hex.txt 3
         __________________
        /     /     /\     \
       /     /     /  \     \
      /_____/_____/    \_____\
     /     /\     \    /\     \
    /     /  \     \  /  \     \
   /_____/    \_____\/    \_____\
  /\     \    /     /\    /     /\
 /  \     \  /     /  \  /     /  \
/    \_____\/_____/    \/_____/    \
\    /     /\     \    /     /\    /
 \  /     /  \     \  /     /  \  /
  \/_____/    \_____\/_____/    \/
   \     \    /     /\     \    /
    \     \  /     /  \     \  /
     \_____\/_____/    \_____\/
      \     \     \    /     /
       \     \     \  /     /
        \_____\_____\/_____/

1

Рубін 236 237

->i,z{i.split(?\n).map{|l|z.times.map{|y|l.size.times.map{|i|z.times.map{|x|c=l[i]
z<y+2&&(l[i-1..i]=='_\\'||l[i..i+1]=='/_')&&o=?_
(c<?!||(x==y&&c==?\\)||(z==y+1&&c>?^)||(x+y+1==z&&c==?/))&&o=c
o||' '}.join}.join.rstrip}-['']}.join ?\n}

Тест в Інтернеті: http://ideone.com/e6XakQ

Це код перед гольфом:

-> diamond, zoom {
  diamond.split(?\n).map do |l|
    zoom.times.map do |y|
      l.size.times.map do |i|
        zoom.times.map do |x|
          out_char = crt_char = l[i]

          out_char = ' '

          # _ has to be continued under / or \
          if zoom == y+1 && l[i-1..i]=='_\\'
            out_char = ?_
          end
          if zoom == y+1 && l[i..i+1]=='/_'
            out_char = ?_
          end

          # logic to "zoom" \, / and _ characters 
          out_char = crt_char if crt_char == ' '
          out_char = crt_char if x==y && crt_char == ?\\  
          out_char = crt_char if zoom==y+1 && crt_char == ?_
          out_char = crt_char if x+y+1==zoom && crt_char == ?/

          out_char
        end.join
      end.join.rstrip
    end - ['']
  end.join ?\n
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.