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 byte
6 byte được lưu nhờ Riley
6 byte được lưu nhờ vào Adnan
Vì câu hỏi này đã hơn một năm tuổi và vẫn chưa có câu trả lời, tôi nghĩ tôi sẽ thử.
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)
Hãy thử trực tuyến!
Chương trình đọc bảng một tập tin có tên I
và in bảng với ghế của nó std::out
. Tôi không chắc chắn về một loạt các trường hợp cạnh nên tôi đã đưa ra phán quyết tốt nhất của mình (bất cứ điều gì tốn ít công sức nhất) nhưng dường như nó vượt qua tất cả các trường hợp thử nghiệm. Một số kết quả đầu ra không khớp chính xác nhưng tất cả chúng đều có cùng số ghế.
Giải trình
Dòng đầu tiên khá đơn giản là thiết lập một số định nghĩa sẽ giúp chúng ta tiết kiệm byte trong tương lai:
(Tôi sẽ giải nén các macro này để dễ đọc trong các dòng trong tương lai)
n,i,o="\nI ";R=lambda x:range(1,x-1)
Sau đó, chúng tôi sẽ mở một tệp có tên I
vì chúng tôi đã có một biến là viết tắt của nó để nó tiết kiệm một vài byte.
b=open("I").read().split("\n")
Chúng tôi chia theo dòng mới để tạo danh sách các chuỗi (Các hàng của hình ảnh)
s=b.split(n)
Sau đó tôi tìm độ dài của dòng dài nhất để tôi có thể đệm tất cả các dòng theo chiều dài đó. (Tôi cũng thêm 3 vì chúng tôi cần thêm một chút phần đệm)
z=max(map(len,s))+3
Sau đó, chúng tôi thực hiện phần đệm thực tế và tạo một đường viền của các I
ký tự xung quanh cạnh. Điều này là do chúng ta sẽ cần phải nói sự khác biệt giữa bên trong và bên ngoài của hình dạng sau này. Chúng tôi cũng sẽ thay đổi kiểu dữ liệu từ danh sách các chuỗi thành danh sách các ký tự (độ dài 1 chuỗi).
a=[list("I"+x.ljust(z,"I"))for x in["I"]+s+["I"]]
Dòng tiếp theo chỉ là một định nghĩa lưu byte.
(Tôi cũng sẽ giải nén cái này)
B=R(len(a))
Bây giờ chúng tôi muốn truyền bá I
nhân vật đến mọi nơi bên ngoài hình dạng. Chúng ta có thể làm điều này với một máy tự động giả tế bào. Mỗi người I
sẽ lây lan sang bất kỳ
nhân vật liền kề . Chúng ta có thể lặp cho đến khi automaton ổn định tuy nhiên điều này không thể thực hiện nhiều lần lặp hơn so với các ký tự để chúng ta chỉ lặp qua mỗi ký tự trong b
(đầu vào ban đầu)
for _ in b:
Đối với mỗi lần lặp, chúng tôi muốn vượt qua mọi ký tự trong danh sách 2D (không bao gồm phần đệm ngoài cùng)
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):
Đối với mỗi vị trí, chúng tôi chạy mã sau đây:
if("I" in[a[x+1][y],a[x-1][y]]+a[x][y-1:y+2])&(a[x][y]==" "):a[x][y]=" "
Hãy phá vỡ điều này.
Chúng ta có một if với hai điều kiện cách nhau bởi một &
(bitwise and
)
Cái đầu tiên chỉ đơn giản kiểm tra xem có một ô I
nào trong các ô liền kề không và ô thứ hai chỉ kiểm tra xem ô hiện tại có phải là a không " "
. Nếu chúng ta vượt qua các điều kiện đó, chúng ta đặt ô hiện tại là một I
.
Bây giờ chúng tôi đã xác định bên ngoài và bên trong của hình dạng, chúng tôi có thể bắt đầu đặt những chiếc ghế xung quanh bàn.
Một lần nữa, chúng tôi lặp qua tất cả các ô (và đặt thêm một số tốc ký)
for x in range(1,len(a)-1):
A=a[x]
for y in range(1,z-1):
k=a[x+1][y]
Bây giờ đây là phần yêu thích của tôi. Nếu bạn đã vượt qua sự nhàm chán, chủ yếu dựa trên định nghĩa của tôi, thì chơi golf cho đến nay tôi sẽ thưởng cho bạn một miếng ngon của môn đánh gôn thông minh (nếu tôi tự nói như vậy).
Một chút nền tảng về python:
Trong Python nếu bạn cố gán một khóa từ điển hai lần thì nó sẽ gán cho cái sau. Ví dụ
>>> {1:"a",1:"b"}[1]
'b'
Chúng tôi sẽ lạm dụng thuộc tính này để gán ô hiện tại cho một ký tự cụ thể.
Điều kiện đầu tiên là
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"]
Nếu ô nằm ở giữa một cạnh của 3 _
ký tự, chúng ta sẽ gán lại ô hiện tại và ô bên dưới nó. Chúng tôi sẽ gán nó cho kết quả của việc lập chỉ mục một từ điển quá tải I
. Trước tiên, chúng tôi đặt mặc định của chúng tôi với cặp "I":"_"+a[x+1][y]
này có nghĩa là nếu không có thay đổi, chúng tôi sẽ gán hai ô trở lại giá trị ban đầu của chúng. Tiếp theo chúng ta thêm cặp a[x-1][y]:"^ "
. Điều này sẽ không làm bất cứ điều gì (quan trọng) trừ khi ô phía trên ô hiện tại ( a[x-1][y]
) chứa đầy một I
. Nếu nó có I
trong đó, nó sẽ ghi đè mặc định cho chúng ta đặt một cái ghế tại ô hiện tại. Tiếp theo, chúng ta chuyển sang ô bên dưới ô hiện tại nếu ô đó là I
chúng ta lại ghi đè lên để đặt một chiếc ghế hướng lên phía dưới vị trí hiện tại.
Điều kiện tiếp theo là đơn giản hơn một chút
if"|"==a[x][y]==a[x-1][y]:a[x][y]={"I":"|",A[y+1]:">",A[y-1]:"<"}["I"]
Chúng tôi kiểm tra xem ô hiện tại và ô bên trên có phải là cả hai không |
. Nếu vậy chúng tôi thiết lập một từ điển.
Cặp đầu tiên trong từ điển "I":"|"
đặt mặc định. Vì chúng ta sẽ truy cập khóa I
nếu I
không được gán lại, nó sẽ mặc định trở lại |
(ký tự đã có) và không làm gì cả.
Chúng tôi thêm hai phím A[y+1]:">",A[y-1]:"<"
Nếu một trong hai ô bên trái và bên phải I
thì nó sẽ gán lại ô hiện tại cho một cái ghế chỉ theo hướng bên ngoài.
Bây giờ chúng tôi chỉ phải đầu ra. Tuy nhiên, chúng tôi không thể chỉ in, có một vài việc dọn phòng chúng tôi phải làm trước tiên. Chúng tôi phải chuyển đổi trở lại thành một chuỗi và loại bỏ tất cả các I
s chúng tôi đã tạo. Điều này được thực hiện trong một dòng.
print "\n".join(`y`[2::5]for y in a).replace("I"," ")