2-мірне сортування бульбашок


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).
  • Ви можете припустити, що сітка - це ідеальний прямокутник, а не зубчастий масив. Сітка буде не менше 2х2.
  • Якщо ви використовуєте інший алгоритм сортування, ви маєте надати доказ того, що він завжди створюватиме такий самий порядок, що й отриманий, як цей конкретний бренд 2D сортування міхурів, незалежно від того, який вхід є. Я очікую, що це буде нетривіальним доказом, тому вам, мабуть, краще скористатися описаним алгоритмом.

Щасливого гольфу!


Чи потрібно реалізовувати точний алгоритм, вказаний у вашому виклику?
Втілення

1
Чи буде масив принаймні 2х2?
Οurous

3
@EmbodimentofIgnorance: лише якщо ви докажете, що це призводить до еквівалентного сортування у всіх випадках . Я очікую, що це буде нетривіальним доказом.
Beefster

4
Хто б не проголосував за те, щоб закрити це як "занадто широкий", ви б не хотіли пояснити свої міркування? Протягом тижня це було в пісочниці з 3 оновленнями і жодних коментарів щодо виправлення, тому попередній консенсус полягав у тому, що це гідне завдання.
Beefster

Відповіді:




1

Мова Вольфрама (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)&

Спробуйте в Інтернеті!

Я не експерт з математики, я впевнений, що це можна зробити коротше. Особливо я думаю, що подвійний, якщо твердження можна скоротити за допомогою, Transposeале я не знаю як.



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

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

Вугілля деревне , 118 байт

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Я також витратив кілька байт на гарне форматування. Пояснення:

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

JavaScript має зручне властивість, яке a[i]>a[i+1]є помилковим, якщоi є останнім елементом масиву. Щоб наслідувати це у вугільному вугіллі, я обчислюю а nan, відкинувши його 9.e999до плаву, а потім віднявши його від себе. (Вугільне вугілля не підтримує експоненціальні константи поплавця.) Потім я прокладаю оригінальний масив праворуч з, nanа також додаю додатковий рядок, що містить просто nan. (Циклічне індексування деревного вугілля означає, що мені потрібен лише один елемент у цьому рядку.)

FΣEθLι«

Цикл для кожного елемента масиву. Це повинно бути більше ніж достатньо циклів, щоб виконати роботу, оскільки я включаю і всі зайві nan.

FLθ«≔§θκι

Переведіть петлю на кожен індекс рядка і отримайте рядок у цьому індексі. (Деревне вугілля може робити як з виразом, але не з командою.) Це включає рядки манекена, але це не проблема, тому що всі порівняння не зможуть.

FLι«≔§ιλζ

Переведіть петлю над індексом кожного стовпця і отримайте значення цього індексу. Знову ж таки, це перетвориться на фіктивні значення, але порівняння просто знову не вдасться.

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

Також отримайте значення праворуч і нижче.

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

Якщо комірка більша за значення нижче, і це неправда, що значення внизу перевищує значення праворуч, тоді поміняйте цю клітинку на значення нижче.

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

В іншому випадку, якщо комірка більша за значення праворуч, тоді поміняйте їх.

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

Видаліть nanзначення та відформатуйте масив для неявного виводу.


0

Котлін , 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)}

Спробуйте в Інтернеті!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.