Візуалізуйте сортування


20

Скажіть, у мене є такий список, як [3, 0, 4, 2, 1]і я сортую виділення, щоб сортувати його, я міг би його візуалізувати так:

3,0,4,2,1
|-|
0,3,4,2,1
  |-----|
0,1,4,2,3
    |-|
0,1,2,4,3
      |-|
0,1,2,3,4

Ця задача полягає у візуалізації подібного сортування.

Вхідні дані

Вашим вкладом буде список натуральних чисел у будь-якому форматі, який вам подобається.

Завдання

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

Інші правила

  • Для сортування необхідно використовувати менше свопів, ніж n 4 , де n - довжина списку.
  • Сортування не повинно бути детермінованим.
  • Символи під місцями розміщення можуть бути будь-якими символами, крім пробілу.

Чи можу я припустити, що цілі числа є унікальними?
Йорг Гюльсерманн

n^4? Ви тут трохи щедрі.
orlp

@ JörgHülsermann Ні
Loovjo

2
Якщо когось цікавить сортування toptal.com/developers/sorting-algorithms
exussum

3
Ви говорите, що введення є цілими числами з додатним числом, але у вашому прикладі є 0(будь ласка, виправте лише приклад, щоб не визнати недійсними відповіді, на які не вдається відповісти 0)
Тон Євангелія

Відповіді:


10

Perl, 62 байти

Включає +3 для -p

Введіть введення в якості єдиного рядка чисел на STDIN:

perl -M5.010 visisort.pl <<< "3 0 4 2 1"

Неодноразово міняє першу інверсію. Складність своп - це O(n^2)складність у часі O(n^3). Використовується цифри, які заміняються як позначка:

3 0 4 2 1
3 0
0 3 4 2 1
    4 2
0 3 2 4 1
  3 2
0 2 3 4 1
      4 1
0 2 3 1 4
    3 1
0 2 1 3 4
  2 1
0 1 2 3 4

visisort.pl:

#!/usr/bin/perl -p
$&>$'&&say$_.$"x"@-".!s/(\S+) \G(\S+)/$2 $1/.$&while/\S+ /g

Програма також підтримує негативні значення та числа з плаваючою комою

Якщо ви наполягаєте на сполучному символі, код стає 66 байт:

#!/usr/bin/perl -p
$&>$'&&say$_.$"x"@-".!s/(\S+) \G(\S+)/$2 $1/.$1.-$2while/\S+ /g

Але тепер він більше не підтримує від'ємні числа і 0 (але програма все одно повинна підтримувати лише додатні цілі числа. У 0прикладі помилка)


З огляду на те, що у The characters under the swapped can be any char except space. вас не повинно бути пробілів між номером у рядку позначки
edc65

@ edc65 Символ (-ів) під елементами, що змінюються, не є пробілом. Про персонажів між ними нічого не сказано
Тон Євангелія

Не зовсім переконаний, але гаразд. Я занадто швидко звозився (але я привернув вашу увагу). Якщо ви зробите (порожнє) редагування своєї відповіді, я зміню свій голос
edc65

@ edc65 Ну, ваш коментар змусив мене дуже уважно перечитати виклик. Зауважте, що він також розповідає про випадок багатозначних чисел, що чітко означає, що ви можете, наприклад, просто поставити _під першою цифрою, що означає, що всі символи між ними насправді будуть пробілами). Тож я стою при своїй інтерпретації (якщо ОП звичайно не погоджується). Купуйте лише для того, щоб вас порадувало, я також додав версію без місця :-)
Тон Євангелія

9

JavaScript (ES6), 158 байт

a=>{for(;;){console.log(``+a);i=a.findIndex((e,i)=>e<a[i-1]);if(i<0)break;console.log(` `.repeat(`${a.slice(0,i)}`.length-1)+`|-|`);t=a[i];a[i]=a[--i];a[i]=t}}

Сорт бульбашки. Вибірка зразка:

3,0,4,2,1
|-|
0,3,4,2,1
    |-|
0,3,2,4,1
  |-|
0,2,3,4,1
      |-|
0,2,3,1,4
    |-|
0,2,1,3,4
  |-|
0,1,2,3,4

@nimi Оскільки я завжди міняю суміжні елементи, я завжди можу поставити -під, ,і тоді два |s завжди будуть під суміжними номерами.
Ніл

ааа, розумний! Спасибі!
німі

1
Сорт бульбашок - це дійсно розумний вибір, який дійсно спрощує виділення міняються цифрами. Молодці!
Арнольд

9

PHP, 248 байт

Bubblesort нудно виграє

<?for($c=count($a=$_GET[a]);$c--;){for($s=$i=0;$i<$c;){$l=strlen($j=join(",",$a));if($a[$i]>$a[$i+1]){$t=$a[$i];$a[$i]=$a[$i+1];$a[$i+1]=$t;$m=" ";$m[$s]=I;$m[$s+strlen($a[$i].$a[$i+1])]=X;echo"$j\n$m\n";}$s+=strlen($a[$i++])+1;}}echo join(",",$a);

PHP, 266 байт шляхом з масивом_slice та min

модифікований вихід I Xзамість*~~*

<?for($c=count($a=$_GET[a]);$i<$c;){$j=join(",",$s=($d=array_slice)($a,$i));$x=array_search($m=min($s),$s);echo($o=join(",",$a));$a[$x+$i]=$a[$i];$a[$i]=$m;if($i++!=$c-1){$t=" ";$t[$z=($f=strlen)($o)-($l=$f($j))]=I;$t[$l+$z-$f(join(",",$d($s,$x)))]=X;echo"\n$t\n";}}

282 байт

<?for($c=count($a=$_GET[a]);$i<$c;){$j=join(",",$s=($d=array_slice)($a,$i));$x=array_search($m=min($s),$s);echo($o=join(",",$a));$a[$x+$i]=$a[$i];$a[$i]=$m;if($i++!=$c-1)echo"\n".str_repeat(" ",($f=strlen)($o)-($l=$f($j))).($x?str_pad("*",$l-$f(join(",",$d($s,$x))),"~"):"")."*\n";}

Як це працює

Шукає мінімум у масиві і приймає це на першій позиції Шукайте мінімум без першої позиції .... і так далі Якщо значення подвійне, перше значення буде swap

Приклад виводу

31,7,0,5,5,5,753,5,99,4,333,5,2,1001,35,1,67
*~~~~*
0,7,31,5,5,5,753,5,99,4,333,5,2,1001,35,1,67
  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*
0,1,31,5,5,5,753,5,99,4,333,5,2,1001,35,7,67
    *~~~~~~~~~~~~~~~~~~~~~~~~~*
0,1,2,5,5,5,753,5,99,4,333,5,31,1001,35,7,67
      *~~~~~~~~~~~~~~*
0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67
        *
0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67
          *
0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67
            *~~~*
0,1,2,4,5,5,5,753,99,5,333,5,31,1001,35,7,67
              *~~~~~~*
0,1,2,4,5,5,5,5,99,753,333,5,31,1001,35,7,67
                *~~~~~~~~~~*
0,1,2,4,5,5,5,5,5,753,333,99,31,1001,35,7,67
                  *~~~~~~~~~~~~~~~~~~~~~*
0,1,2,4,5,5,5,5,5,7,333,99,31,1001,35,753,67
                    *~~~~~~*
0,1,2,4,5,5,5,5,5,7,31,99,333,1001,35,753,67
                       *~~~~~~~~~~~*
0,1,2,4,5,5,5,5,5,7,31,35,333,1001,99,753,67
                          *~~~~~~~~~~~~~~~*
0,1,2,4,5,5,5,5,5,7,31,35,67,1001,99,753,333
                             *~~~~*
0,1,2,4,5,5,5,5,5,7,31,35,67,99,1001,753,333
                                *~~~~~~~~*
0,1,2,4,5,5,5,5,5,7,31,35,67,99,333,753,1001
                                    *
0,1,2,4,5,5,5,5,5,7,31,35,67,99,333,753,1001

Замість цього echo$t."\n";можна використовувати echo"$t\n";та зберігати байт.
Ісмаїл Мігель

@IsmaelMiguel Не соромтесь редагувати мої повідомлення, якщо ви знайдете щось для покращення
Jörg Hülsermann

7
Редагування коду в публікаціях, як правило, нахмурюється, з чим я повністю згоден.
Ісмаїл Мігель

3

Haskell, 165 164 162 байт

s%c=drop 2$show s>>c
p#x|(h,t:s)<-span(/=minimum x)x=id=<<[show$p++x,"\n ",[' '|p>[]],p%" ","|",h%"-",['|'|h>[]],"\n",(p++[t])#(drop 1h++take 1h++s)]|1<2=""
([]#)

Це візуалізує сортування вибору. Приклад використання:

*Main> putStr $ ([]#) [31,7,0,5,5,5,753,5,99,4,333,5,2,1001,35,1,67]
[31,7,0,5,5,5,753,5,99,4,333,5,2,1001,35,1,67]
 |----|
[0,7,31,5,5,5,753,5,99,4,333,5,2,1001,35,1,67]
   |-------------------------------------|
[0,1,31,5,5,5,753,5,99,4,333,5,2,1001,35,7,67]
     |-------------------------|
[0,1,2,5,5,5,753,5,99,4,333,5,31,1001,35,7,67]
       |--------------|
[0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67]
         |
[0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67]
           |
[0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67]
             |---|
[0,1,2,4,5,5,5,753,99,5,333,5,31,1001,35,7,67]
               |------|
[0,1,2,4,5,5,5,5,99,753,333,5,31,1001,35,7,67]
                 |----------|
[0,1,2,4,5,5,5,5,5,753,333,99,31,1001,35,7,67]
                   |---------------------|
[0,1,2,4,5,5,5,5,5,7,333,99,31,1001,35,753,67]
                     |------|
[0,1,2,4,5,5,5,5,5,7,31,99,333,1001,35,753,67]
                        |-----------|
[0,1,2,4,5,5,5,5,5,7,31,35,333,1001,99,753,67]
                           |---------------|
[0,1,2,4,5,5,5,5,5,7,31,35,67,1001,99,753,333]
                              |----|
[0,1,2,4,5,5,5,5,5,7,31,35,67,99,1001,753,333]
                                 |--------|
[0,1,2,4,5,5,5,5,5,7,31,35,67,99,333,753,1001]
                                     |
[0,1,2,4,5,5,5,5,5,7,31,35,67,99,333,753,1001]
                                         |

Як це працює:

s % c- це допоміжна функція, яка робить length (show s) - 2копії символів c. Він використовується для проміжків перед обома |, один раз з c == ' 'і один раз з c == '-'.

Основна функція #займає список, pякий є відсортованою частиною списку і xякий ще належить сортувати. Збіг шаблонів (h,t:s)<-span(/=minimum x)xрозбиває список xна його мінімальний елемент і прив'язується hдо частини перед мінімумом, tдо самого мінімуму та sдо частини після мінімуму. Решта - це форматування двох рядків: 1) список у його поточному стані ( p++x) та 2) |----|частина з подальшим рекурсивним викликом #із tдоданою до pта головою hвставленої між хвостом hта s.

PS: також працює з негативними та / або числами з плаваючою комою:

*Main> putStr $ ([]#) [-3,-1,4e33,-7.3]
[-3.0,-1.0,4.0e33,-7.3]
 |----------------|
[-7.3,-1.0,4.0e33,-3.0]
      |-----------|
[-7.3,-3.0,4.0e33,-1.0]
           |------|
[-7.3,-3.0,-1.0,4.0e33]
                |

Редагувати: @BlackCap збережено 2 байти. Спасибі!


id=<<[show$p++x,"\n ",[' '|p>[]],p%" ","|",h%"-",['|'|h>[]],"\n",(p++[t])#(drop 1h++take 1h++s)]
BlackCap

1

Python 2, 267 байт

Він також працює з десятковими і від’ємними числами.

p=1
while p!=len(a):    
 q=p-1;k=a[p:];m=min(k);n=k.index(m)+p;b=map(str,a)
 if a[q]>m:print','.join(b)+'\n'+''.join(' '*len(i)for i in b[:q])+' '*q+'*'+'-'*(len(b[n])+n-q-2)+''.join('-'*len(i)for i in b[q:n])+'*';a[q],a[n]=[a[n],a[q]]
 p+=1
print','.join(map(str,a))

Приклад:

7,2,64,-106,52.7,-542.25,54,209,0,-1,200.005,200,3,6,1,0,335,-500,3.1,-0.002
*----------------------*
-542.25,2,64,-106,52.7,7,54,209,0,-1,200.005,200,3,6,1,0,335,-500,3.1,-0.002
        *-------------------------------------------------------*
-542.25,-500,64,-106,52.7,7,54,209,0,-1,200.005,200,3,6,1,0,335,2,3.1,-0.002
             *-----*
-542.25,-500,-106,64,52.7,7,54,209,0,-1,200.005,200,3,6,1,0,335,2,3.1,-0.002
                  *-------------------*
-542.25,-500,-106,-1,52.7,7,54,209,0,64,200.005,200,3,6,1,0,335,2,3.1,-0.002
                     *-----------------------------------------------------*
-542.25,-500,-106,-1,-0.002,7,54,209,0,64,200.005,200,3,6,1,0,335,2,3.1,52.7
                            *--------*
-542.25,-500,-106,-1,-0.002,0,54,209,7,64,200.005,200,3,6,1,0,335,2,3.1,52.7
                              *-----------------------------*
-542.25,-500,-106,-1,-0.002,0,0,209,7,64,200.005,200,3,6,1,54,335,2,3.1,52.7
                                *------------------------*
-542.25,-500,-106,-1,-0.002,0,0,1,7,64,200.005,200,3,6,209,54,335,2,3.1,52.7
                                  *-------------------------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,64,200.005,200,3,6,209,54,335,7,3.1,52.7
                                    *--------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,200.005,200,64,6,209,54,335,7,3.1,52.7
                                      *-------------------------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,200,64,6,209,54,335,7,200.005,52.7
                                          *------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,64,200,209,54,335,7,200.005,52.7
                                            *-----------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,200,209,54,335,64,200.005,52.7
                                              *----------------------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,209,54,335,64,200.005,200
                                                   *----*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,54,209,335,64,200.005,200
                                                      *--------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,54,64,335,209,200.005,200
                                                         *-----------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,54,64,200,209,200.005,335
                                                             *---------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,54,64,200,200.005,209,335

1

JavaScript (ES6), 147 155

Використовуючи n * n порівнює, але (я вважаю) мінімальну кількість свопів. І позиції підкачки є більш змінними порівняно з нудним сортом бульбашок.

l=>l.reduce((z,v,i)=>l.map((n,j)=>s+=`${j>i?n<l[i]?l[p=j,t=s,i]=n:0:u=s,n},`.length,s=p=0)|p?z+`
${l[p]=v,' '.repeat(u)}^${Array(t-u)}^
`+l:z,''+l)

Менше гольфу і, сподіваємось, більш зрозумілого

l=>
  l.reduce( (z,v,i) => // update z for each list element v at position i
    ( // begin outer loop body
      // loop to find the least value that is to be placed at pos i
      l.map( (n,j) => // for each list element n at position j
        ( // begin inner loop body
          j > i ? // check if at position after i
            n < l[i] && // check if lower value 
            (
              p = j, // remember position in p 
              l[i] = n, // store value in l[i] (could change later)
              t = s // in t, string length of list elements up element preciding j
            )
          : // else, position up to i
            u = s, // in u, string length of list elements up element preciding i
          s += `${n},`.length, // string length of list elements up to this point (value length + comma)
        ) // end inner loop body
        , s = p = 0 // init s and p at start of inner loop
      ), 
      p ? (// if found a lower value, complete the swap and update output
          l[p] = v, // complete swap, l[i] was assigned before
          z + '\n' + ' '.repeat(u) + // spaces to align 
               '^' + // left marker
               Array(t-u) + // swap highlight, using sequence of commas
               '^\n' + // right marker, newline
               l + // list values after the swap, newline
      )
      : z // else output is unchanged
    ) // end outer loop body
    , ''+l // init string output at start of outer loop
  ) // output is the result of reduce

Тест

f=
l=>l.reduce((z,v,i)=>l.map((n,j)=>s+=`${j>i?n<l[i]?l[p=j,t=s,i]=n:0:u=s,n},`.length,s=p=0)|p?z+`
${l[p]=v,' '.repeat(u)}^${Array(t-u)}^
`+l:z,''+l)

function sort()
{
  var list=I.value.match(/-?[\d.]+/g).map(x=>+x)
  O.textContent = f(list)
}

sort()
#I { width:80% }
<input id=I value='3, 0, 4, 2, 1'>
<button onclick='sort()'>Sort</button>
<pre id=O></pre>


0

Java 7, 256 241 282 байт

Завдяки @Geobits та @Axelh за збереження 15 байт

 void f(int[]a){int m,i,j,l=a.length;for(i=0;i<l;j=a[i],a[i]=a[m],a[m]=j,i++){for(int k:a)System.out.print(k+" ");System.out.println();for(j=i+1,m=i;j<l;m=a[j]<a[m]?j:m,j++);for(j=0;j<=m&i!=l-1;j++)System.out.print(j==i|j==m?a[j]+" ":"  ");System.out.println();}}

Безумовно

 void f(int[]a){
    int m,i,j,l=a.length;
for(i=0;i<l;j=a[i],a[i]=a[m],a[m]=j,i++){
    for(int k:a)
        System.out.print(k+" ");
    System.out.println();
     for(j=i+1,m=i;j<l;m=a[j]<a[m]?j:m,j++);
      for(j=0;j<=m&i!=l-1;j++)
      System.out.print(j==i|j==m?a[j]+" ":"  ");
      System.out.println();        

}
}

вихід

3 0 1 4 2 
3 0 
0 3 1 4 2 
  3 1 
0 1 3 4 2 
    3   2 
0 1 2 4 3 
      4 3 
0 1 2 3 4 

4
У цьому декларації все ще відсутня out, вам потрібно щось помістити PrintStream out=System.out;десь у своєму коді.
Loovjo

2
Після виправлення імпорту / декларації outслід використовувати термінал замість того, if/elseякщо ви збираєтесь друкувати на обох гілках. Щось на кшталт out.print(a>b?a:b);замістьif(a>b)out.print(a);else out.print(b);
Геобіц

Ви можете зменшити if if liek цього: if(j==i|j==m)out.print(a[j]);out.print(" ");а ще краще за допомогою потрійного, out.print((j==i|j==m?a[j]:" ")+" ");а потім ви можете видалити {} з циклу PS: я використовую статику імпорту для екземпляра out, якщо це нормально;)
AxelH

Хм, окрім підказки для гольфу від інших, вихід невірний. Ось ідеон з вашим кодом, вставленим кодом (і доданим System.перед outs), і в ньому пропущено 2і 3два, і два останні рядки заміни.
Кевін Кройсейсен

@KevinCruijssen я виправив це. Фактично я змішую змінну з змінною j (має бути я) у цьому рядкуfor(j=0;j<=m&i!=l-1;j++)
Numberknot

0

Желе , 36 байт

I;0CMḢ;L‘ṬCœṗ¹UF©µÐĿ,n+32Ọ$¥¥2\;/®ṭG

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

Пояснення

I;0CMḢ;L‘ṬCœṗ¹UF©µÐĿ,n+32Ọ$¥¥2\;/®ṭG
                 µÐĿ                 Repeat until we see a previously seen value:
I;0                                    Take differences of adjacent inputs, and 0
   CM                                  Find the indices (M) of the smallest (C) 
           œṗ                          Split {the input} into pieces
        ‘Ṭ                               that end
      ;L  C                              everywhere except
     Ḣ                                 the first of the chosen deltas
             ¹                         Resolve parser ambiguity
              U                        Reverse each piece
               F                       Concatenate the pieces back into a list
                ©                      Store the value in a register
                                     Then, on the accumulated list of results:
                             2\        Look at each consecutive pair of results
                    ,       ¥  ;/      and return the first element, followed by
                      +32Ọ$            the character with code 32 plus
                     n     ¥           1 (if unequal), 0 (if equal)
                                 ®ṭ  Append the value of the register
                                   G Output in grid form

Приклад, показаний у посиланні TIO, є особливо важким для цієї програми; ;0поблизу початку необхідно переконатися , що цикл закінчується як раз в той момент , коли вхід стає відсортоване. Зазвичай це не потрібно (тому що воно закінчиться після ще однієї ітерації), але якщо останній своп складається з перших двох елементів (як це бачимо тут), то ще одна ітерація не відбудеться і унеможливить її закінчення список послідовно. Таким чином, нам потрібно забезпечити, щоб ми нічого не поміняли під час останньої ітерації циклу.

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