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 bajtów
6 bajtów zapisanych dzięki Riley
6 bajtów zapisanych dzięki Adnan
Ponieważ to pytanie ma ponad rok i wciąż nie ma odpowiedzi, pomyślałem, że spróbuję.
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)
Wypróbuj online!
Program odczytuje tabelę o nazwie pliku I
i drukuje tabelę z krzesłami do std::out
. Nie byłam pewna co do kilku skrajnych przypadków, więc dokonałam najlepszej oceny (cokolwiek wymagało najmniejszego wysiłku), ale wydaje się, że zdała wszystkie testy. Niektóre wyjścia nie pasują dokładnie, ale wszystkie mają taką samą liczbę krzeseł.
Wyjaśnienie
Pierwszy wiersz po prostu ustanawia niektóre definicje, które pozwolą nam zaoszczędzić bajty w przyszłości:
(Rozpakuję te makra, aby były czytelne w przyszłych wierszach)
n,i,o="\nI ";R=lambda x:range(1,x-1)
Następnie otworzymy plik o nazwie, I
ponieważ mamy już zmienną, która jest krótka, więc zapisuje kilka bajtów.
b=open("I").read().split("\n")
Dzielimy się wzdłuż nowego wiersza, aby utworzyć listę ciągów (wiersze obrazu)
s=b.split(n)
Następnie znajduję długość najdłuższej linii, aby móc dopełnić wszystkie linie do tej długości. (Dodaję również 3, ponieważ potrzebujemy trochę dodatkowego wypełnienia)
z=max(map(len,s))+3
Następnie wykonujemy rzeczywiste wypełnienie i tworzymy ramkę I
znaków wokół krawędzi. Wynika to z tego, że później będziemy musieli odróżnić wnętrze od zewnętrznej strony kształtu. Zmienimy również typ danych z listy ciągów na listę znaków (długość 1 ciągów).
a=[list("I"+x.ljust(z,"I"))for x in["I"]+s+["I"]]
Następny wiersz to kolejna definicja zapisywania bajtów.
(Rozpakuję również ten)
B=R(len(a))
Teraz chcemy rozprowadzać I
postacie wszędzie poza kształtem. Możemy to zrobić za pomocą automatu pseudokomórkowego. Każda I
zostanie przeniesiona na dowolne sąsiednie
postacie. Możemy zapętlać, dopóki automat się nie ustabilizuje, jednak nie może to zająć więcej iteracji niż znaków, więc po prostu zapętlamy każdy znak w b
(oryginalne wejście)
for _ in b:
Dla każdej iteracji chcemy pominąć każdy znak na liście 2D (wyłączając najbardziej zewnętrzne dopełnienie)
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):
Dla każdej pozycji uruchamiamy następujący kod:
if("I" in[a[x+1][y],a[x-1][y]]+a[x][y-1:y+2])&(a[x][y]==" "):a[x][y]=" "
Rozbijmy to.
Mamy if z dwoma warunkami oddzielonymi przez &
(bitowe and
)
Pierwszy sprawdza po prostu, czy jest I
w którejś z sąsiednich komórek, a drugi sprawdza, czy bieżąca komórka to " "
. Jeśli spełnimy te warunki, ustawimy bieżącą komórkę na I
.
Teraz, gdy ustaliliśmy zewnętrzną i wewnętrzną postać kształtu, możemy zacząć ustawiać krzesła wokół stołu.
Po raz kolejny przeglądamy wszystkie komórki (i ustawiamy więcej skrótów)
for x in range(1,len(a)-1):
A=a[x]
for y in range(1,z-1):
k=a[x+1][y]
Oto moja ulubiona część. Jeśli przeszedłeś przez moje nudne, w większości oparte na definicji golfa, do tej pory nagrodzę cię przyjemnym smakiem sprytnego golfa (jeśli sam to powiem).
Małe tło w pythonie:
W Pythonie, jeśli spróbujesz dwukrotnie przypisać klucz słownika, przypisuje on ten drugi. Na przykład
>>> {1:"a",1:"b"}[1]
'b'
Wykorzystamy tę właściwość, aby przypisać bieżącą komórkę do określonej postaci.
Pierwszy warunek to
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"]
Jeśli komórka znajduje się pośrodku krawędzi 3 _
znaków, ponownie przypisamy bieżącą komórkę i komórkę poniżej niej. Przypiszemy go do wyniku indeksowania przeciążonego słownika według I
. Najpierw ustawiamy nasze domyślne ustawienie na parę, "I":"_"+a[x+1][y]
co oznacza, że jeśli nie będzie żadnych zmian, przywrócimy pierwotne wartości obu komórek. Następnie dodajemy parę a[x-1][y]:"^ "
. Nie zrobi to nic (ważnego), chyba że komórka powyżej bieżącego ( a[x-1][y]
) zostanie wypełniona znakiem I
. Jeśli ma I
w sobie, zastąpi domyślną, mówiącą nam, abyśmy ustawili krzesło w bieżącej komórce. Następnie przechodzimy do komórki poniżej bieżącej komórki, jeśli ta komórka I
ponownie przeskakuje, aby ustawić krzesło skierowane w górę poniżej bieżącego miejsca.
Kolejny warunek jest odrobinę prostszy
if"|"==a[x][y]==a[x-1][y]:a[x][y]={"I":"|",A[y+1]:">",A[y-1]:"<"}["I"]
Sprawdzamy, czy bieżąca komórka i komórka nad nią są jednocześnie |
. Jeśli tak, tworzymy słownik.
Pierwsza para w słowniku "I":"|"
ustawia wartość domyślną. Ponieważ uzyskamy dostęp do klucza, I
jeśli I
nie zostanie on ponownie przypisany, domyślnie powróci do |
(postać, którą już jest) i nic nie zrobi.
Dodajemy dwa klucze. A[y+1]:">",A[y-1]:"<"
Jeśli którakolwiek z dwóch komórek po lewej i prawej stronie znajduje się, I
wówczas ponownie przypisze bieżącą komórkę do krzesła wskazującego w kierunku na zewnątrz.
Teraz musimy po prostu wyjść. Jednak nie możemy po prostu drukować, musimy najpierw zrobić kilka czynności porządkowych. Musimy przekonwertować z powrotem na ciąg i usunąć wszystkie I
stworzone przez nas s. Odbywa się to w jednej linii.
print "\n".join(`y`[2::5]for y in a).replace("I"," ")