Python 2, 1033 1007 924 879 829 787 713 699 692 691 688 687 672 670 664 659 654 648 643 642 630 625 623 620 570 560 554 545 518 514 513 510 505 492 476 454 451 443 байта
6 байтов сохранено благодаря Райли
6 байтов сохранено благодаря Аднану
Поскольку этому вопросу уже более года, и он до сих пор не получил ответов, я решил попробовать.
n,i,o,u="\nI _";R=lambda x:range(1,x-1)
b=open(i).read()
s=b.split(n)
z=max(map(len,s))+3
a=[list(i+x.ljust(z,i))for x in[i]+s+[i]]
for x in R(len(a))*len(b):
A=a[x];B=a[x+1];C=a[x-1]
for y in R(z):
D=A[y-1:y+2];k=B[y];j=A[y+1]
if(i in[C[y],k]+D+(k==u)*B[y-1:y+2]or"V"==j)&(A[y]==o):A[y]=i
if"|"==A[y]==C[y]:A[y]={i:"|",j:">",A[y-1]:"<"}[i]
if[u]*3==D:A[y],B[y]={i:u+k,C[y]:"^"+k,k:" V"}[i]
print n.join(`y`[2::5]for y in a).replace(i,o)
Попробуйте онлайн!
Программа считывает таблицу с именем файла I
и печатает таблицу со стульями std::out
. Я не был уверен в куче крайних случаев, поэтому я принял лучшее решение (независимо от того, что потребовало наименьших усилий), но, похоже, он прошел все контрольные примеры. Некоторые из результатов не совпадают точно, но все они имеют одинаковое количество стульев.
объяснение
Первая строка довольно просто устанавливает некоторые определения, которые будут экономить нам байты в будущем:
(Я распакую эти макросы для удобства чтения в следующих строках)
n,i,o="\nI ";R=lambda x:range(1,x-1)
Затем мы откроем файл с именем, I
потому что у нас уже есть переменная, которая коротка для этого, поэтому он сохраняет несколько байтов.
b=open("I").read().split("\n")
Мы разбиваем вдоль строк, чтобы создать список строк (строк изображения)
s=b.split(n)
Затем я нахожу длину самой длинной строки, чтобы можно было дополнить все строки этой длиной. (Я также добавляю 3, потому что нам нужно немного дополнительного заполнения)
z=max(map(len,s))+3
Затем мы выполняем фактическое заполнение и создаем границу I
символов по краю. Это потому, что позже нам нужно будет определить разницу между внутренней и внешней частью фигуры. Мы также изменим тип данных из списка строк в список списка символов (длина строки 1).
a=[list("I"+x.ljust(z,"I"))for x in["I"]+s+["I"]]
Следующая строка - это просто еще одно определение сохранения байта.
(Я также распакую этот)
B=R(len(a))
Теперь мы хотим выкладывать I
символы повсюду за пределами фигуры. Мы можем сделать это с помощью псевдо-клеточного автомата. Каждый I
будет распространяться на любые соседние
символы. Мы можем зацикливаться, пока автомат не стабилизируется, однако это не может занять больше итераций, чем количество символов, поэтому мы просто перебираем все символы внутри b
(исходные данные)
for _ in b:
Для каждой итерации мы хотим передать каждый символ в 2D-списке (исключая внешние отступы)
for x in range(1,len(a)-1):
A=a[x] #<--Another definition I will fill in for clarity
for y in range(1,z-1):
Для каждой позиции мы запускаем следующий код:
if("I" in[a[x+1][y],a[x-1][y]]+a[x][y-1:y+2])&(a[x][y]==" "):a[x][y]=" "
Давайте разберемся с этим.
У нас есть, если с двумя условиями, разделенными &
(поразрядно and
)
Первый просто проверяет, есть ли I
в какой-либо из соседних ячеек, а второй просто проверяет, является ли текущая ячейка a " "
. Если мы передаем эти условия, мы устанавливаем текущую ячейку, чтобы бытьI
.
Теперь, когда мы определили форму снаружи и внутри, мы можем начать расставлять стулья вокруг стола.
Еще раз мы перебираем все ячейки (и устанавливаем еще несколько сокращений)
for x in range(1,len(a)-1):
A=a[x]
for y in range(1,z-1):
k=a[x+1][y]
Теперь вот моя любимая часть. Если вы дошли до моего скучного, в основном основанного на определениях, игры в гольф до сих пор, я собираюсь наградить вас приятным лакомым кусочком умного гольфа (если я сам так скажу).
Немного предыстории в python:
В Python, если вы пытаетесь назначить словарный ключ дважды, он назначает последний. Например
>>> {1:"a",1:"b"}[1]
'b'
Мы будем злоупотреблять этим свойством, чтобы присвоить текущую ячейку определенному персонажу.
Первое условие
if["_"]*3==a[x][y-1:y+2]:a[x][y],a[x+1][y]={"I":"_"+a[x+1][y],a[x-1][y]:"^ ",a[x+1][y]:" V"}["I"]
Если ячейка находится в середине края из 3 _
символов, мы переназначим текущую ячейку и ячейку под ней. Мы присвоим его результату индексации перегруженного словаря по I
. Сначала мы устанавливаем значение по умолчанию с парой, "I":"_"+a[x+1][y]
это означает, что если нет изменений, мы присвоим двум ячейкам их исходные значения. Далее мы добавим пару a[x-1][y]:"^ "
. Это ничего не сделает (важно), если ячейка над текущей ( a[x-1][y]
) не заполнена I
. Если в нем есть значение, I
то оно переопределит значение по умолчанию, говорящее нам о размещении стула в текущей ячейке. Затем мы переходим к ячейке ниже текущей ячейки, если эта ячейкаI
снова переопределяется, чтобы поместить стул, обращенный вверх, ниже текущей точки.
Следующее условие немного проще
if"|"==a[x][y]==a[x-1][y]:a[x][y]={"I":"|",A[y+1]:">",A[y-1]:"<"}["I"]
Мы проверяем, являются ли текущая ячейка и ячейка над ней |
. Если это так, мы создали словарь.
Первая пара в словаре "I":"|"
устанавливает значение по умолчанию. Поскольку мы собираемся получить доступ к ключу, I
если I
его не переназначить, он по умолчанию вернется к |
(символ, которым он уже является) и ничего не сделает.
Мы добавим две клавиши. A[y+1]:">",A[y-1]:"<"
Если любая из двух ячеек слева и справа будет, I
то она переназначит текущую ячейку на стул, указывающий в направлении наружу.
Теперь нам просто нужно вывести. Однако мы не можем просто напечатать, есть пара вещей, которые мы должны сделать в первую очередь. Мы должны преобразовать обратно в строку и удалить все I
s, которые мы создали. Это делается в одну строку.
print "\n".join(`y`[2::5]for y in a).replace("I"," ")