Calcular o antípoda de um ponto na curva

14

Uma curva é um conjunto de pontos em uma grade quadrada, de modo que cada ponto tenha exatamente dois vizinhos na vizinhança de quatro vizinhos e os pontos formem um único componente conectado. Ou seja, o gráfico induzido pelos pontos em um gráfico de grade é isomórfico para um único ciclo. "Induzido" significa que dois pontos não podem tocar na entrada sem serem vizinhos no ciclo.

Um antípode de um vértice V em um gráfico é um vértice mais distante de V. O antípode é sempre único em um ciclo de comprimento par (e todos os ciclos em um gráfico de grade são par). A distância deve ser medida como induzida pelo próprio ciclo, sem respeitar a grade quadrada subjacente.

Sua entrada deve ser uma imagem de uma curva. A curva será marcada com uma sequência de caracteres de sinal numérico ( #) em um fundo sem caracteres de espaço ( ). Um dos pontos da curva será marcado com o Pcaractere ("pode"). Sua saída deve ser a mesma que a entrada, exceto que um ponto da curva deve ser substituído por A("antipode").

Você pode assumir que os caracteres serão preenchidos em uma forma retangular. Você pode assumir que a primeira e a última linha e coluna da entrada serão compostas inteiramente de espaços (a entrada é preenchida com fundo). Como alternativa, você pode assumir que a primeira e a última linha e coluna conterão cada um ponto de curva (a entrada possui preenchimento mínimo).

Você pode inserir e gerar esta grade como uma única sequência separada por nova linha, como uma matriz de linhas ou como uma matriz 2D de caracteres individuais. Essa escolha deve ser a mesma para entrada e saída. Se o seu idioma permitir isso, você poderá produzir modificando a entrada no lugar em vez de retornar a string ou matriz modificada.

Entradas possíveis:

P#    P##   #P#   #####      #####P# #######   #####P#########   #####P#########
##    # #   # #   #   #      #     # #     #   #             #   #             #
      ###   ###   ## ##      # ### # # ### #   # ### ### ### #   #             #
###                # # ###   # # # # # # # #   # # # # # # # #   #             #
# P#    ### ###    # ### #   # # ### ### # #   # # ### ### # #   #             #
## #    # ### #    #     #   # #         # #   # #         # #   #             #
 # #    P     #    ##### P   # ########### #   # ##### ##### #   #             #
 ###    #######        ###   #             #   #     # #     #   #             #
                             ###############   ####### #######   ###############

Saídas correspondentes:

P#    P##   #P#   #A###      #####P# #A#####   #####P#########   #####P#########
#A    # #   # #   #   #      #     # #     #   #             #   #             #
      ##A   #A#   ## ##      # ### # # ### #   # ### ### ### #   #             #
###                # # ###   # # # # # # # #   # # # # A # # #   #             #
# P#    ### ##A    # ### #   # # ### ### # #   # # ### ### # #   #             #
## #    # ### #    #     #   # #         # #   # #         # #   #             #
 A #    P     #    ##### P   # ########### #   # ##### ##### #   #             #
 ###    #######        ###   #             #   #     # #     #   #             #
                             ###############   ####### #######   #########A#####

Distâncias de vértice do podes (módulo 10) (não as produza):

P1    P12   1P1   5A543      54321P1 9A98765   54321P123456789   54321P123456789
1A    1 3   2 2   4   2      6     2 8     4   6             0   6             0
      23A   3A3   32 01      7 109 3 7 109 3   7 901 789 543 1   7             1
321                1 9 543   8 2 8 4 6 2 8 2   8 8 2 6 A 6 2 2   8             2
4 P1    234 89A    0 876 2   9 3 765 543 7 1   9 7 345 987 1 3   9             3
56 2    1 567 9    9     1   0 4         6 0   0 6         0 4   0             4
 A 3    P     8    87654 P   1 56789012345 9   1 54321 56789 5   1             5
 654    1234567        321   2             8   2     0 4     6   2             6
                             345678901234567   3456789 3210987   345678901A10987
John Dvorak
fonte

Respostas:

4

JavaScript (ES6), 193 181 bytes

f=s=>s==(`P#1P#21#12#221A`[r=`replace`](/.../g,([n,f,t])=>s=s[r](eval(`/([${n+=f}])([^]{${s.search`\n`}})?(?!\\1)[${n}]/`),m=>m[r](eval(`/^${f}|${f}$/`),t))),s)?s[r](/\d/g,`#`):f(s)

Versão que fornece uma animação em loop:

f=s=>s==(`#A#1#12#221AP#1P#2`[r=`replace`](/.../g,([n,f,t])=>s=s[r](eval(`/([${n+=f}])([^]{${s.search`\n`}})?(?!\\1)[${n}]/`),m=>m[r](eval(`/^${f}|${f}$/`),t))),s)?s[r](/\d/g,`#`):s
;setInterval(_=>i.value=f(i.value),1e3)
<textarea rows=10 cols=20 id=i style="font-family:monospace"></textarea>

Neil
fonte
4

Python 2 , 333 221 215 bytes

-17 bytes graças a @JanDvorak

g=input()
y=map(max,g).index('P')
x=g[y].index('P')
m=[k[:]for k in g]
v=x;w=y
while'#'in sum(m,[]):x,y,(v,w)=v,w,[(x+a,y+b)for a,b in((1,0),(-1,0),(0,1),(0,-1))if'#'==m[y+b][x+a]][0];m[w][v]='_'
g[w][v]='A'
print g

Experimente online!


Python 3 , 402 288 282 bytes, String IO

g=[[*k]for k in open(0).read().split('\n')]
y=[max(k)for k in g].index('P')
x=g[y].index('P')
m=[k[:]for k in g]
v=x;w=y
while'#'in sum(m,[]):x,y,(v,w)=v,w,[(x+a,y+b)for a,b in((1,0),(-1,0),(0,1),(0,-1))if'#'==m[y+b][x+a]][0];m[w][v]='_'
g[w][v]='A'
print('\n'.join(map(''.join,g)))

Experimente online!


Animação do código em execução:

Animação do código em execução

ovs
fonte
4

MATL , 43 42 bytes

32-I#fbbJ*+!w3>y"&)yy-|&X<]vJQ2/)G65b&Zj&(

O código aceita uma quantidade arbitrária de preenchimento de espaço na primeira e na última linha e coluna. Input é uma matriz retangular de caracteres, usando ;como separador de linhas. Por exemplo, a entrada

#####   
#   #   
## ##   
 # # ###
 # ### #
 #     #
 ##### P
     ###

é representado como

['#####   ';
 '#   #   ';
 '## ##   ';
 ' # # ###';
 ' # ### #';
 ' #     #';
 ' ##### P';
 '     ###']

ou, em uma linha (para que possa ser digitada através do STDIN),

['#####   '; '#   #   '; '## ##   '; ' # # ###'; ' # ### #'; ' #     #'; ' ##### P'; '     ###']

Experimente online! Ou verifique os quatro últimos casos: 1 , 2 , 3 , 4 (estes foram escolhidos por terem as curvas mais complicadas; o último possui preenchimento de espaço).

Explicação

TL; WR: números complexos, muita indexação, sem convolução.

32-     % Implicitly input char matrix. Subtract 32. Space becomes zero
I#f     % 3-output find: pushes nonzero values, their row indices,
        % and their column indices, as column vectors
bb      % Bubble up twice, so row and column indices are on top
J*+     % Times 1j, add. This transforms row and column indices into
        % complex numbers, where real is row and imaginary is column
!       % Transpose into a row vector
w       % Swap, so vector of nonzero values is on top
3>      % Logical index of elements exceeding 3. ASCII codes of space,
        % '#' and 'P0 are 32, 35 and 80 respectively. Since 32 was
        % subtracted these became 0, 3 and 48. So the only entry with
        % value exceeding 3 is that corresponding to the original 'P'.
y"      % Do this as many times as the number of complex positions
        %   The stack now contains the vector of complex positions and an
        %   index into that vector. The index points to the complex position 
        %   to be processed next.
  &)    %   Two-output reference indexing: pushes the indexed entry and
        %   a vector with the remaining entries. This pulls off the
        %   current complex position, which is initially that of 'P'
  yy    %   Duplicate top two elements, i.e. current position and vector
        %   of remaining positions
  -|    %   Absolute differences
  &X<   %   Index of minimum. Gives the index of the complex position
        %   that is closest to the current one. In case of tie (which
        %   only happens in the first iteration) it picks the first. The 
        %   result is the index of the complex position to be processed in 
        %   the next iteration. This index will be empty if this is the last
        %   iteration.
]       % End
        % The stack now contains the complex positions as individual
        % values, starting from 'P' and sorted as per the curve; plus two 
        % empty arrays. These empty arrays have been produced by the last
        % iteration as the index for the "next" iteration and the array of
        % "remaining" complex positions
v       % Concatenate into a column vector. The empty arrays have no effect.
        % The resulting vector contains the sorted complex positions
JQ      % Push 1j and add 1
2/      % Divide by 2. This gives (1+1j)/2. When used as an index this is
        % interpreted as (1+end)/2. Since the length of the curve is even
        % this gives a non-integer number, which will be implicitly
        % rounded up (because of .5 fracctional part). As an example, for
        % length 32 this gives 16.5, which rounded becomes 17. Position 17
        % along the curve is the antipode of position 1
)       % Reference indexing. Gives the complex position of the antipode
G       % Push input char matrix again
65      % Push 65 (ASCII for 'A')
b       % Bubble up, so complex position is on top
&Zj     % Separate into real and imagimary parts, corresponding to row and
        % column indices
&(      % 4-input assignment indexing. This writes 'A' at the specified row
        % and column of the char matrix. Implicitly display
Luis Mendo
fonte
0

Python 3 , 421 bytes

l,e=len,enumerate
r=open(0).read()
n=lambda x:[(x[0]-1,x[1]),(x[0]+1,x[1]),(x[0],x[1]-1),(x[0],x[1]+1)]
p=a={(i,j):y for i,x in e(r.split('\n'))for j,y in e(x)}
t=l(r.split('\n'));s=l(r.split('\n')[0])
for i in a:p=[p,i][a[i]=='P']
w=[p]
while l(w)!=r.count('#')+1:
 for x in a:
  if x in n(w[-1])and a[x]!=' 'and x not in w:w+=[x]
a[w[(l(w)+1)//2]]='A';print('\n'.join(''.join(a[j,i]for i in range(s))for j in range(t)))

Experimente online!

officialaimm
fonte
0

Mathematica, 234 223 bytes

(p=Position;v=p[#,"#"|"P"];n=Length@v;q=v[[#]]&;h=FindCycle[Graph[v,Join@@Table[If[Norm[q@i-q@j]==1,q@i<->q@j,Nothing],{i,n},{j,i-1}]]][[1,#,1]]&;ReplacePart[#,h@Mod[p[Table[h@x,{x,n}],p[#,"P"][[1]]][[1,1]]+n/2,n,1]->"A"])&

Este código faz com que vseja a lista de vértices para o gráfico: os índices de "#"e "P"s. Então né o comprimento (necessariamente par) e qextrai o vértice de entrada-th (ignorando a forma do loop).

Então hé uma função que constrói o gráfico com vértices ve arestas não direcionadas entre vértices quando o comprimento da diferença de seus pares de índices é exatamente 1 (portanto, a diferença é algo parecido com {-1,0}ou {0,1}) e, em seguida, localiza uma lista de todos os ciclos e fornece o primeiro (somente) faça o ciclo (como uma lista de arestas) e, em seguida, pegue a entrada-ésima aresta e pegue o primeiro vértice que compõe essa aresta.

Usando h, podemos encontrar o índice de "P"no ciclo e percorrer a metade do caminho (usando Mod para contornar se ultrapassarmos os limites da lista de ciclos) para encontrar o antípode e, em seguida, podemos substituir a entrada correspondente do original entrada mcom"A"

Você pode experimentá-lo on-line colando o seguinte na Wolfram Cloud Sandbox e clicando em "avaliar célula" ou pressionando Shift + Enter ou Numpad Enter:

(p=Position;v=p[#,"#"|"P"];n=Length@v;q=v[[#]]&;h=FindCycle[Graph[v,Join@@Table[If[Norm[q@i-q@j]==1,q@i<->q@j,Nothing],{i,n},{j,i-1}]]][[1,#,1]]&;ReplacePart[#,h@Mod[p[Table[h@x,{x,n}],p[#,"P"][[1]]][[1,1]]+n/2,n,1]->"A"])&@{{"#","#","#","#","#"," "," "," "},{"#"," "," "," ","#"," "," "," "},{"#","#"," ","#","#"," "," "," "},{" ","#"," ","#"," ","#","#","#"},{" ","#"," ","#","#","#"," ","#"},{" ","#"," "," "," "," "," ","#"},{" ","#","#","#","#","#"," ","P"},{" "," "," "," "," ","#","#","#"}}//MatrixForm

Idéia alternativa, 258 bytes

Um pouco inspirado pelas soluções Python da ovs , tentei escrever um código que não usasse nenhum recurso da teoria dos grafos do Mathematica e apenas calculasse cegamente as distâncias. Não consegui obtê-lo tão curto, mas suspeito que alguém possa melhorá-lo:

f[m_]:=(x="#";t=ReplacePart;p=Position;l=t[m,p[m,"P"][[1]]->0];v=p[l,x|0];n=Length[v];q=v[[#]]&;r=l[[q[#][[1]],q[#][[2]]]]&;y=t[l,q@#->(r@#2+1)]&;Do[If[Norm[q@i-q@j]==1&&Xor[r@i==x,r@j==x],If[r@i==x,l=y[i,j],l=y[j,i]]],n,{i,n},{j,n}];t[m,p[l,n/2][[1]]->"A"])`

Este código é muito ineficiente. Basicamente, ele substitui "P"por 0e depois procura "#"algo próximo de algo que não é um "#", repetindo a coisa toda duas vezes e os substitui por números que representam a distância "P"e, para garantir que ele termine, isso é feito com o ntempo de processamento . Na verdade, isso nem calcula as distâncias corretamente, pois uma ramificação pode ultrapassar o antípoda, mas apenas um local será numerado, n/2independentemente de qual seja.

Mark S.
fonte