Увеличьте алмазную плитку


27

Любой обычный шестиугольник может быть облицован бриллиантами, например, так:

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

Мы рассмотрим вышеупомянутое значение размера 1(так как стороны алмазов сделаны из одного /или \каждого). Такой же размер 2будет выглядеть так:

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

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

Обратите внимание, что шестиугольник может быть любого размера и размером до 1x1x1 (содержит три бриллианта).

Ни входные данные, ни выходные не должны содержать никаких завершающих пробелов, ни больше начальных пробелов, чем необходимо для выравнивания формы шестиугольника. И ввод, и вывод могут опционально содержать один завершающий символ новой строки (этот выбор не должен быть одинаковым для ввода и вывода).

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

Это код гольф, поэтому самый короткий ответ (в байтах) в выигрыше.

Пример Tilings

Вот несколько вариантов ввода, которые вы можете использовать для проверки вашего представления.

 __
/_/\
\_\/

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

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

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

Следующий фрагмент содержит соответствующие выходы для входов N = 1через N = 6.


20
Я вижу, что вы заинтересованы в бриллиантах теперь, когда у вас есть один рядом с вашим именем пользователя.
user12205

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

Python 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 /может стать

   /
  /
 /
/___

Оригинальный символ появляется один раз в каждой строке, и там есть отступы с любой стороны. Здесь слева и _справа. Только нижний ряд может быть дополнен '_'; остальное всегда ' '.

Основная сложность заключается в том, что отступ справа может зависеть от предстоящего символа. В частности, '/ 'имеет разные отступы '/_', поэтому нам нужно немного заглянуть в будущее. Кроме того, чтобы избежать пробелов, мы должны отметить, что мы находимся на последнем символе и воздерживаться от заполнения справа.

Мы преодолеваем обе эти проблемы, только добавляя слева от текущего символа. Когда мы делаем это, мы также выполняем дополнение справа от предыдущего символа, используя текущий символ заполнения. Таким образом, мы печатаем правый отступ от предыдущего символа, левый отступ от текущего символа, затем текущий символ. Мы также храним сумму отступа "долг", которую должен заплатить следующий символ.

Теперь давайте пройдемся по коду.

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

Python 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

Python, 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не является допустимым входным параметром - вам нужно манипулировать самой строкой.
Исаак

Ну вы можете использовать sys.stdinи , int(sys.argv[1])но ты не собираешься получить их бесплатно, ожидая от них будет принят в качестве переменных (если это была честная игра, то вы могли бы также ожидать , псевдонимы rangeи replace` и все , что еще нужно , чтобы быть предопределить) ,
Мартин Эндер

@ MartinBüttner Это говорит о том, что я могу принять входные данные в качестве аргумента функции. Разве это не то, что я делаю здесь? В любом случае я собирался изменить аргумент функции на список строк. Это было бы хорошо? Это не очень отличается, так как оба stdinи список строк являются последовательностями строк.
Рето Коради

1

Perl, 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.