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 salvos graças a Riley
6 bytes salvos graças a Adnan
Como essa pergunta tem mais de um ano e ainda não tem respostas, pensei em tentar.
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)
Experimente online!
O programa lê na tabela um arquivo nomeado I
e imprime a tabela com suas cadeiras std::out
. Eu não tinha certeza de muitos dos casos extremos, por isso tomei meu melhor julgamento (o que foi menos trabalhoso), mas parece passar em todos os casos de teste. Algumas das saídas não correspondem exatamente, mas todas têm o mesmo número de cadeiras.
Explicação
A primeira linha simplesmente configura algumas definições que nos economizarão bytes no futuro:
(Vou descompactar essas macros para facilitar a leitura em linhas futuras)
n,i,o="\nI ";R=lambda x:range(1,x-1)
Em seguida, abriremos um arquivo nomeado I
porque já temos uma variável que é curta para isso, e salva alguns bytes.
b=open("I").read().split("\n")
Dividimos ao longo de novas linhas para criar uma lista de strings (As linhas da imagem)
s=b.split(n)
Em seguida, encontro o comprimento da linha mais longa para poder preencher todas as linhas nesse comprimento. (Também adiciono 3 porque precisamos de um pouco de preenchimento adicional)
z=max(map(len,s))+3
Em seguida, executamos o preenchimento real e criamos uma borda de I
caracteres ao redor da borda. Isso ocorre porque precisaremos distinguir a diferença entre o interior e o exterior da forma mais tarde. Também mudaremos o tipo de dados de uma lista de strings para uma lista de caracteres (comprimento 1).
a=[list("I"+x.ljust(z,"I"))for x in["I"]+s+["I"]]
A próxima linha é apenas outra definição de economia de bytes.
(Eu também vou descompactar este)
B=R(len(a))
Agora, queremos espalhar I
caracteres para todos os lugares fora da forma. Podemos fazer isso com um autômato pseudo-celular. Cada um I
se espalhará para qualquer
caractere adjacente . Poderíamos fazer loop até que o autômato se estabilize, no entanto, isso não pode levar mais iterações do que os caracteres b
.
for _ in b:
Para cada iteração, queremos passar sobre cada caractere da lista 2D (excluindo o preenchimento mais 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 posição, executamos o seguinte 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 quebrar isso.
Temos um if com duas condições separadas por um &
(bit a bit and
)
A primeira simplesmente verifica se existe uma I
em qualquer uma das células adjacentes e a segunda apenas verifica se a célula atual é a " "
. Se passarmos por essas condições, definimos a célula atual como um I
.
Agora que determinamos o exterior e o interior da forma, podemos começar a colocar as cadeiras ao redor da mesa.
Mais uma vez, percorremos todas as células (e definimos mais algumas abreviações)
for x in range(1,len(a)-1):
A=a[x]
for y in range(1,z-1):
k=a[x+1][y]
Agora, aqui está a minha parte favorita. Se você se intrometeu no meu golfe chato, principalmente baseado em definições, até agora, vou recompensá-lo com um bom petisco de golfe inteligente (se é o que digo).
Um pouco de fundo em python:
No Python, se você tentar atribuir uma chave de dicionário duas vezes, ela atribui a última. Por exemplo
>>> {1:"a",1:"b"}[1]
'b'
Abusaremos essa propriedade para atribuir a célula atual a um caractere específico.
A primeira condição é
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"]
Se a célula estiver no meio de uma aresta de 3 _
caracteres, reatribuiremos a célula atual e a célula abaixo dela. Nós o atribuiremos ao resultado da indexação de um dicionário sobrecarregado por I
. Primeiro, definimos nosso padrão com o par. "I":"_"+a[x+1][y]
Isso significa que, se não houver alteração, atribuiremos as duas células aos seus valores originais. Em seguida, adicionamos o par a[x-1][y]:"^ "
. Isso não fará nada (importante), a menos que a célula acima da atual ( a[x-1][y]
) seja preenchida com um I
. Se houver um I
, ele substituirá o padrão, dizendo para colocar uma cadeira na célula atual. Em seguida, passamos para a célula abaixo da célula atual, se essa célula for I
novamente substituída para colocar uma cadeira voltada para cima abaixo do local atual.
A próxima condição é um pouco mais simples
if"|"==a[x][y]==a[x-1][y]:a[x][y]={"I":"|",A[y+1]:">",A[y-1]:"<"}["I"]
Verificamos se a célula atual e a célula acima são ambas |
. Nesse caso, criamos um dicionário.
O primeiro par no dicionário "I":"|"
define o padrão. Como vamos acessar a chave, I
se I
não for reatribuída, ela retornará ao padrão |
(o caractere que já é) e não fará nada.
Nós adicionamos as duas teclas A[y+1]:">",A[y-1]:"<"
Se qualquer uma das duas células à esquerda e à direita estiver I
, ela reatribuirá a célula atual a uma cadeira apontando na direção do lado de fora.
Agora nós apenas temos que produzir. No entanto, não podemos apenas imprimir, há algumas coisas de limpeza que precisamos fazer primeiro. Temos que converter novamente em uma string e remover todos os I
s que criamos. Isso é feito em uma linha.
print "\n".join(`y`[2::5]for y in a).replace("I"," ")