Пітон 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:
Для кожної ітерації ми хочемо передати кожен символ у двовимірному списку (за винятком самого зовнішнього накладки)
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 " "
. Якщо ми переходимо ці умови, ми встановимо, що поточна комірка є an 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"," ")