二维气泡排序


17

排序对于二维数组没有意义...还是吗?

您的任务是获取一个输入网格,并对它应用类似于冒泡排序的算法,直到网格中的所有值沿每一行和每一列从左到右,从上到下不递减。

该算法的工作原理如下:

  • 每次遍历都从上到下逐行进行,比较/交换每个单元格及其右侧和下方的邻居。
    • 如果该单元格仅大于其右侧和邻域之一,则与该单元格大于
    • 如果该单元格大于其右侧邻居和下方邻居,请与较小的邻居交换
    • 如果单元格大于其右侧和下方的邻居(均为相同值),则与下方的邻居交换。
    • 如果该单元格不大于其右侧和相邻单元格中的任何一个,则不执行任何操作
  • 继续进行此操作,直到整个过程中没有进行交换为止。这是每行和每列从左到右,从上到下按顺序排列的时间。

4 2 1
3 3 5
7 2 1

通过的第一行将交换4和2,然后将4与1交换。

2 1 4
3 3 5
7 2 1

当我们得到中间的3时,它将与下面的2交换

2 1 4
3 2 5
7 3 1

然后将5与下面的1交换

2 1 4
3 2 1
7 3 5

第一遍的最后一行将7一直移到右侧

2 1 4
3 2 1
3 5 7

然后,我们再次回到第一行

1 2 1
3 2 4
3 5 7

并继续逐行...

1 2 1
2 3 4
3 5 7

...直到网格被“排序”

1 1 2
2 3 4
3 5 7

另一个例子

3 1 1
1 1 1
1 8 9

变成

1 1 1
1 1 1
3 8 9

而不是

1 1 1
1 1 3
1 8 9

因为当一个小区的右邻居和下邻居相等时,向下交换优先。

可在此处找到分步参考实施。

测试用例

5 3 2 6 7 3 1 0
3 2 1 9 9 8 3 0
3 2 2 8 9 8 7 6

变成

0 0 1 1 2 2 3 6
2 2 3 3 6 7 8 8
3 3 5 7 8 9 9 9

2 1 2 7 8 2 1 0
2 2 2 2 3 2 1 0
1 2 3 4 5 4 3 2
9 8 7 6 5 4 3 6
6 5 4 3 2 2 1 0

变成

0 0 0 1 1 1 2 2
1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3
3 4 4 4 4 5 6 6
5 5 6 7 7 8 8 9

规则

  • 您可以采用任何方便的格式输入网格
  • 您可以假定网格值是16位无符号范围(0-65535)中的所有非负整数。
  • 您可以假设网格是一个完美的矩形,而不是一个锯齿状的数组。网格将至少为2x2。
  • 如果您使用其他排序算法,则必须提供证明,无论输入什么内容,它都将始终产生与该特定品牌的2D气泡排序相同的结果顺序。我希望这是不平凡的证明,因此您最好使用上述算法。

高尔夫快乐!


我们是否必须执行挑战中指定的确切算法?
无知的体现,

1
阵列至少为2x2吗?
5:50

3
@EmbodimentofIgnorance:仅当您证明在所有情况下其结果均相同时。我希望这是一个重要的证明。
Beefster '19

4
谁投票赞成以“过于广泛”来结束这一点,您介意解释您的理由吗?这是在沙盒中进行的一周,有3票赞成票,没有任何纠正意见,因此先前的共识是这是一个不错的挑战。
Beefster '19

Answers:




1

Wolfram语言(Mathematica),183个字节

(R=#;{a,b}=Dimensions@R;e=1;g:=If[Subtract@@#>0,e++;Reverse@#,#]&;While[e>0,e=0;Do[If[j<b,c=R[[i,j;;j+1]];R[[i,j;;j+1]]=g@c]If[i<a,c=R[[i;;i+1,j]];R[[i;;i+1,j]]=g@c],{i,a},{j,b}]];R)&

在线尝试!

我不是Mathematica专家,我敢肯定它可以做得更短。我特别认为double if语句可以缩短使用,Transpose但我不知道如何。


1

[R 169个 165 144 132字节

function(m,n=t(m)){while(any(F-(F=n)))for(i in 1:sum(1|n)){j=(j=i+c(0,r<-nrow(n),!!i%%r))[order(n[j])[1]];n[c(i,j)]=n[c(j,i)]};t(n)}

在线尝试!


0

干净,240字节

import StdEnv
$l=limit(iterate?l)
?[]=[]
?l#[a:b]= @l
=[a: ?b]
@[[a,b:c]:t]#(t,[u:v])=case t of[[p:q]:t]=([q:t],if(a>p&&b>=p)[b,p,a]if(a>b)[a,b,p][b,a,p]);_=(t,sortBy(>)[a,b])
=[v%(i,i)++j\\i<-[0..]&j<- @[[u:c]:t]]
@l=sort(take 2l)++drop 2l

在线尝试!

完全按照说明实施算法。

链接包括输入解析以采取问题的格式。


0

Python 2中215个 208字节

m=input()
h=len(m);w=len(m[0])
while 1:
 M=eval(`m`)
 for k in range(h*w):i,j=k/w,k%w;v,b,a=min([(M[x][y],y,x)for x,y in(i,j),(i+(i<h-1),j),(i,j+(j<w-1))]);M[i][j],M[a][b]=M[a][b],M[i][j]
 M!=m or exit(M);m=M

在线尝试!

-7个字节,多亏了ovs


208个字节,输出到Debug / STDERR。
ovs '19

@ovs,谢谢:)
TF

0

C#(.NET Core),310字节

没有LINQ。仅在返回函数后使用System.Collections.Generic格式化输出。事情真是愚蠢。期待高尔夫!

a=>{int x=a.GetLength(0),y=a.GetLength(1);bool u,o;int j=0,k,l,t,z;for(;j<x*y;j++)for(k=0;k<x;k++)for(l=0;l<y;){o=l>y-2?0>1:a[k,l+1]<a[k,l];u=k>x-2?0>1:a[k+1,l]<a[k,l];z=t=a[k,l];if((u&!o)|((u&o)&&(a[k,l+1]>=a[k+1,l]))){t=a[k+1,l];a[k+1,l]=z;}else if((!u&o)|(u&o)){t=a[k,l+1];a[k,l+1]=z;}a[k,l++]=t;}return a;}

在线尝试!


0

Python 2,198字节

G=input()
O=e=enumerate
while O!=G:
 O=eval(`G`)
 for i,k in e(G):
	for j,l in e(k):v,x,y=min((G[i+x/2][j+x%2],x&1,x/2)for x in(0,1,2)if i+x/2<len(G)and j+x%2<len(k));G[i][j],G[i+y][j+x]=v,l
print G

在线尝试!

独立于TFeld的答案而开发的软件,存在一些差异。


0

木炭,118字节

≔I9.e999η≧⁻ηηFθ⊞ιη⊞θ⟦η⟧FΣEθLι«FLθ«≔§θκιFLι«≔§ιλζ≔§ι⊕λε≔§§θ⊕κλδ¿››ζδ›δ嫧≔§θ⊕κλζ§≔ιλδ»¿›ζ嫧≔ι⊕λζ§≔ιλε»»»»¿⊟θ¿Eθ⊟ιEθ⪫ι 

在线尝试!链接是详细版本的代码。我还花了一些字节进行一些漂亮的格式化。说明:

≔I9.e999η≧⁻ηηFθ⊞ιη⊞θ⟦η⟧

JavaScript具有方便的属性,a[i]>a[i+1]如果i为数组的最后一个元素,则为false 。为了在木炭中模拟这一点,我计算了a,方法nan是将其强制转换9.e999为float,然后从自身中减去。(木炭不支持指数浮点常量。)然后,我用填充右侧的原始数组,nan并添加仅包含的附加行nan。(木炭的循环索引意味着该行只需要一个元素。)

FΣEθLι«

为数组中的每个元素循环。这应该是足够多的循环来完成工作,因为我也包括了所有额外的nans。

FLθ«≔§θκι

循环遍历每个行索引,并在该索引处获取行。(木炭可以用表达式来执行,但不能用命令来执行。)这包括虚拟行,但这不是问题,因为所有比较都会失败。

FLι«≔§ιλζ

遍历每个列索引并获取该索引处的值。同样,这将遍历虚拟值,但比较将再次失败。

≔§ι⊕λε≔§§θ⊕κλδ

还要获得右边和下面的值。

¿››ζδ›δ嫧≔§θ⊕κλζ§≔ιλδ»

如果单元格大于下面的值,并且不正确,即下面的值大于右边的值,则将单元格替换为下面的值。

¿›ζ嫧≔ι⊕λζ§≔ιλε»»»»

否则,如果该单元格大于右侧的值,则将其交换。

¿⊟θ¿Eθ⊟ιEθ⪫ι 

删除nan值并格式化数组以进行隐式输出。


0

Kotlin,325字节

{m:Array<Array<Int>>->val v={r:Int,c:Int->if(r<m.size&&c<m[r].size)m[r][c]
else 65536}
do{var s=0>1
for(r in m.indices)for(c in m[r].indices)when{v(r,c)>v(r+1,c)&&v(r+1,c)<=v(r,c+1)->m[r][c]=m[r+1][c].also{m[r+1][c]=m[r][c]
s=0<1}
v(r,c)>v(r,c+1)&&v(r,c+1)<v(r+1,c)->m[r][c]=m[r][c+1].also{m[r][c+1]=m[r][c]
s=0<1}}}while(s)}

在线尝试!

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.