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 bytes
6 bytes guardados gracias a Riley
6 bytes guardados gracias a Adnan
Como esta pregunta tiene más de un año y todavía no tiene respuestas, pensé en intentarlo.
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)
Pruébalo en línea!
El programa lee la mesa en un archivo llamado Ie imprime la mesa con sus sillas std::out. No estaba seguro acerca de un montón de casos límite, así que tomé mi mejor juicio (lo que tomó el menor esfuerzo) pero parece pasar todos los casos de prueba. Algunas de las salidas no coinciden exactamente, pero todas tienen el mismo número de sillas.
Explicación
La primera línea simplemente establece algunas definiciones que nos ahorrarán bytes en el futuro:
(Descomprimiré estas macros para facilitar la lectura en líneas futuras)
n,i,o="\nI ";R=lambda x:range(1,x-1)
Luego abriremos un archivo llamado Iporque ya tenemos una variable que es la abreviatura de eso, por lo que ahorra algunos bytes.
b=open("I").read().split("\n")
Nos dividimos a lo largo de las nuevas líneas para crear una lista de cadenas (las filas de la imagen)
s=b.split(n)
Luego encuentro la longitud de la línea más larga para poder rellenar todas las líneas a esa longitud. (También agrego 3 porque necesitamos un poco de relleno adicional)
z=max(map(len,s))+3
Luego realizamos el relleno real y creamos un borde de Icaracteres alrededor del borde. Esto se debe a que más adelante tendremos que diferenciar entre el interior y el exterior de la forma. También cambiaremos el tipo de datos de una lista de cadenas a una lista de caracteres (cadenas de longitud 1).
a=[list("I"+x.ljust(z,"I"))for x in["I"]+s+["I"]]
La siguiente línea es solo otra definición para guardar bytes.
(También desempacaré este)
B=R(len(a))
Ahora queremos difundir los Ipersonajes a todas partes fuera de la forma. Podemos hacer esto con un autómata pseudocelular. Cada uno Ise extenderá a cualquier personaje adyacente . Podríamos repetir hasta que el autómata se estabilice, sin embargo, esto no puede tomar más iteraciones de las que hay caracteres, por lo que simplemente recorremos cada carácter en b(la entrada original)
for _ in b:
Para cada iteración, queremos pasar sobre cada carácter en la lista 2D (excluyendo el relleno más externo)
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):
Para cada posición ejecutamos el siguiente código:
if("I" in[a[x+1][y],a[x-1][y]]+a[x][y-1:y+2])&(a[x][y]==" "):a[x][y]=" "
Vamos a romper esto.
Tenemos un if con dos condiciones separadas por un &(bit a bit and)
El primero simplemente verifica si hay un Ien cualquiera de las celdas adyacentes y el segundo simplemente verifica si la celda actual es a " ". Si pasamos esas condiciones, establecemos que la celda actual sea an I.
Ahora que hemos determinado el exterior y el interior de la forma, podemos comenzar a colocar las sillas alrededor de la mesa.
Una vez más, recorremos todas las celdas (y establecemos algunas más shorthands)
for x in range(1,len(a)-1):
A=a[x]
for y in range(1,z-1):
k=a[x+1][y]
Ahora aquí está mi parte favorita. Si hasta ahora has recorrido mi aburrido golf, principalmente basado en la definición, te recompensaré con un buen truco de golf inteligente (si lo digo yo mismo).
Un poco de historia en python:
En Python, si intenta asignar una clave de diccionario dos veces, asigna la última. Por ejemplo
>>> {1:"a",1:"b"}[1]
'b'
Abusaremos de esta propiedad para asignar la celda actual a un personaje en particular.
La primera condición es
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"]
Si la celda está en el medio de un borde de 3 _caracteres, reasignaremos la celda actual y la celda debajo de ella. Lo asignaremos al resultado de indexar un diccionario sobrecargado por I. Primero establecemos nuestro valor predeterminado con el par, "I":"_"+a[x+1][y]esto significa que si no hay cambio, asignaremos las dos celdas a sus valores originales. A continuación agregamos el par a[x-1][y]:"^ ". Esto no hará nada (importante) a menos que la celda sobre la actual ( a[x-1][y]) esté llena de un I. Si tiene una entrada I, anulará el valor predeterminado que nos indica que coloquemos una silla en la celda actual. A continuación, pasamos a la celda debajo de la celda actual si esa celda se Ianula nuevamente para colocar una silla hacia arriba debajo del punto actual.
La siguiente condición es un poco más simple
if"|"==a[x][y]==a[x-1][y]:a[x][y]={"I":"|",A[y+1]:">",A[y-1]:"<"}["I"]
Verificamos si la celda actual y la celda superior son ambas |. Si es así, creamos un diccionario.
El primer par en el diccionario "I":"|"establece el valor predeterminado. Dado que vamos a acceder a la clave Isi Ino se reasigna, volverá por defecto a |(el carácter que ya es) y no hará nada.
Luego, agregamos las dos teclas. A[y+1]:">",A[y-1]:"<"Si cualquiera de las dos celdas a la izquierda y a la derecha lo son I, reasignará la celda actual a una silla que apunte en la dirección del exterior.
Ahora solo tenemos que dar salida. Sin embargo, no podemos simplemente imprimir, hay un par de cosas de limpieza que tenemos que hacer primero. Tenemos que convertir de nuevo a una cadena y eliminar todos los Icorreos electrónicos que creamos. Esto se hace en una línea.
print "\n".join(`y`[2::5]for y in a).replace("I"," ")