计算曲线上一点的对映体


14

曲线是正方形网格上的一组点,这样,每个点在四个邻居的邻域中恰好有两个邻居,并且这些点形成单个连接的组件。即,由网格图上的点所引起的图对于单个周期是同构的。“感应”是指两个点在循环中不彼此相邻就无法触摸输入。

图中顶点V的对映体是距离V最远的顶点。对映体在偶数长度的循环中总是唯一的(并且网格图上的每个循环都是偶数长度的)。距离的测量应由循环本身引起,而不考虑下面的方格。

您的输入应为曲线图像。曲线将#在背景字符()之外的背景上用一系列数字符号()标记出来。曲线上的点之一将标记有P字符(“ pode”)。您的输出应与输入相同,除了一个曲线点应替换为A(“ antipode”)。

您可能会假设字符将被填充为矩形。您可以假设输入的第一行和最后一行和列将完全由空格组成(输入由背景填充)。或者,您可以假设第一行和最后一行和每一列都将包含一个曲线点(输入具有最小的填充)。

您可以作为单个换行符分隔的字符串,行的数组或单个字符的2D数组输入和输出此网格。输入和输出的选择应相同。如果您的语言允许,则可以通过在适当位置修改输入而不是返回修改后的字符串或数组来输出。

可能的输入:

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

相应的输出:

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

距吊舱的顶点距离(模10)(不输出这些):

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

Answers:


4

的JavaScript(ES6),193个 181字节

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)

提供循环动画的版本:

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>


4

Python 2中333个 221 215字节

-17个字节,感谢@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

在线尝试!


Python 3中402个 288 282个字节,字符串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)))

在线尝试!


运行代码的动画:

运行代码的动画


4

MATL43 42字节

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

该代码在第一行和最后一行和最后一列中接受任意数量的空格填充。输入是字符的矩形数组,;用作行分隔符。例如,输入

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

表示为

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

或者,一行(因此可以通过STDIN输入),

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

在线尝试!或验证最后四种情况: 1 2 3 4(这些都被选中,是因为它们具有最复杂的曲线;最后一个有一定的空间填充)。

说明

TL; WR:复数,很多索引,没有卷积。

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

0

Python 3,421字节

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)))

在线尝试!


0

Mathematica,234 223字节

(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"])&

此代码v是图的顶点列表:在的索引"#""P"秒。然后n是长度(必要时为偶数),并q提取第输入顶点(因此忽略循环的形状)。

然后h是一个函数,v当它们的索引对的差值的长度恰好为1(因此它们的差值类似于{-1,0}{0,1})时,将在顶点之间以及顶点之间的无向边上构建图,然后查找所有循环的列表并提供第一个(仅)循环(作为边的列表),然后获取第th个输入边,并获取构成该边的第一个顶点。

使用h,我们可以找到"P"循环中的索引,然后进行一半移动(如果经过循环列表的边界,可以使用Mod进行环绕)找到对映体,然后我们可以替换原始的对应项输入m"A"

您可以 Wolfram Cloud Sandbox上粘贴以下内容,然后单击“评估单元格”,或者按Shift + Enter或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

替代方案,258个字节

受到一点启发 ovs的Python解决方案的,我试图编写不使用Mathematica的任何图论功能的代码,而只是盲目地计算距离。我不能这么简短,但怀疑有人可以改进它:

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"])`

此代码效率很低。基本上,它将替换"P"0,然后通过循环遍历整个事物两次"#"来寻找非“ a”的下一个对象"#",并用表示与的距离的数字替换它们"P",并确保完成,它完成了该过程n时间。实际上,这甚至都不能正确计算距离,因为一个分支可以越过对映体,但是只有一个位置会用n/2

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.