Sortierung visualisieren

20

Angenommen, ich habe eine Liste wie [3, 0, 4, 2, 1]und ich benutze Auswahlsortierung, um sie zu sortieren. Ich könnte sie folgendermaßen visualisieren:

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

Bei dieser Herausforderung geht es darum, das Sortieren so zu visualisieren.

Eingang

Ihre Eingabe besteht aus einer Liste positiver Ganzzahlen in einem beliebigen Format.

Aufgabe

Ihre Übermittlung sollte die Eingabeliste so sortieren, dass nur zwei Elemente gleichzeitig ausgetauscht werden. Bei jedem Austausch sollte die Übermittlung die Liste und ein Zeichen unter jedem der auszutauschenden Elemente anzeigen. Wenn eine getauschte Nummer mehr als eine Ziffer enthält, kann sich das Zeichen an einer beliebigen Stelle darunter befinden. Am Ende sollte die Einreichung die sortierte Liste anzeigen.

Andere Regeln

  • Die Sortierung muss weniger Auslagerungen als n 4 verwenden , wobei n die Länge der Liste ist.
  • Die Sortierung muss nicht deterministisch sein.
  • Die Zeichen unter dem getauschten Zeichen können alle Zeichen außer Leerzeichen sein.
Loovjo
quelle
Kann ich davon ausgehen, dass die ganzen Zahlen eindeutig sind?
Jörg Hülsermann
n^4? Du bist hier ein bisschen großzügig.
orlp
@ JörgHülsermann No
Loovjo
2
Wenn jemand daran interessiert ist, toptal.com/developers/sorting-algorithms zu
exussum 10.10.16
3
Sie sagen, die Eingabe ist positive ganze Zahlen, aber Ihr Beispiel hat eine 0(bitte korrigieren Sie nur das Beispiel, um Antworten, die nicht mit 0 umgehen können, nicht ungültig zu machen)
Ton Hospel

Antworten:

10

Perl, 62 Bytes

Beinhaltet +3 für -p

Geben Sie in STDIN eine einzelne Zeile mit Zahlen ein:

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

Tauscht wiederholt die erste Inversion aus. Swap-Komplexität ist O(n^2), Zeitkomplexität ist O(n^3). Verwendet die getauschten Zahlen als Markierung:

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

Das Programm unterstützt auch negative Werte und Gleitkommazahlen

Wenn Sie auf einem verbindenden Zeichen bestehen, wird der Code zu 66 Byte:

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

Aber jetzt werden negative Zahlen und 0 nicht mehr unterstützt (aber das Programm muss sowieso nur positive Ganzzahlen unterstützen. Das 0im Beispiel ist ein Fehler)

Tonne Hospel
quelle
Vorausgesetzt, The characters under the swapped can be any char except space. Sie sollten keine Leerzeichen zwischen den Zahlen in der Markierungslinie haben
edc65
@ edc65 Die Zeichen unter den auszutauschenden Elementen sind keine Leerzeichen. Über die Charaktere zwischen ihnen wird nichts gesagt
Ton Hospel
Nicht ganz überzeugt, aber ok. Ich habe zu schnell abgewählt (aber ich habe Ihre Aufmerksamkeit bekommen). Wenn du eine (leere) Änderung an deiner Antwort
vornimmst, ändere
@ edc65 Nun, Ihr Kommentar hat mich veranlasst, die Herausforderung noch einmal sehr sorgfältig durchzulesen. Beachten Sie, dass er auch über den Fall von mehrstelligen Zahlen spricht, _was bedeutet, dass Sie z. B. einfach eine unter die erste Ziffer setzen können, was bedeutet, dass alle dazwischen liegenden Zeichen tatsächlich Leerzeichen wären. Ich stehe also zu meiner Interpretation (es sei denn, das OP ist natürlich anderer Meinung). Aber nur um dich glücklich zu machen, habe ich auch eine Version ohne Leerzeichen hinzugefügt :-)
Ton Hospel
9

JavaScript (ES6), 158 Byte

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

Blase sortieren. Beispielausgabe:

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
Neil
quelle
@nimi Da ich immer benachbarte Elemente vertausche, kann ich immer die -unter die ,und dann die beiden |s immer unter die benachbarten Zahlen setzen.
Neil
aah, schlau! Vielen Dank!
nimi
1
Die Blasensortierung ist in der Tat eine vernünftige Wahl, um das Hervorheben der vertauschten Nummern zu vereinfachen. Gut gemacht!
Arnauld
9

PHP, 248 Bytes

Bubblesort langweilig gewinnt

<?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 Bytes a way mit array_slice und min

modifizierte Ausgabe I Xstatt*~~*

<?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 Bytes

<?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";}

Wie es funktioniert

Sucht nach dem Minimum in einem Array und nimmt dieses auf die erste Position. Sucht nach dem Minimum ohne erste Position. Usw. Wenn ein Wert doppelt so groß ist, wird der erste Wert getauscht

Ausgabebeispiel

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
Jörg Hülsermann
quelle
Stattdessen echo$t."\n";können Sie echo"$t\n";ein Byte verwenden und speichern.
Ismael Miguel
@IsmaelMiguel Fühlen Sie sich frei, meine Beiträge zu bearbeiten, wenn Sie etwas zu verbessern finden
Jörg Hülsermann
7
Code-Änderungen an Beiträgen sind normalerweise verpönt, dem stimme ich voll und ganz zu.
Ismael Miguel
3

Haskell, 165 164 162 Bytes

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=""
([]#)

Dies visualisiert die Auswahlsortierung. Anwendungsbeispiel:

*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]
                                         |

Wie es funktioniert:

s % cist eine Hilfsfunktion, die length (show s) - 2Kopien von Charakteren erstellt c. Es wird für den Abstand vor beiden verwendet |, einmal mitc == ' ' und einmal mitc == '-' .

Die Hauptfunktion #nimmt eine Liste an, pdie der sortierte Teil der Liste und xder noch zu sortierende Teil ist. Die Musterübereinstimmung (h,t:s)<-span(/=minimum x)xteilt die Liste xan ihrem Minimalelement und bindet han das Teil vor dem Minimum, tan das Minimum selbst und san das Teil nach dem Minimum. Der Rest formatiert zwei Zeilen: 1) die Liste in ihrem aktuellen Zustand ( p++x) und 2) den |----|Teil, gefolgt von einem rekursiven Aufruf von #mit tangehängt an pund dem Kopf von heingefügt zwischen dem Ende von hund s.

PS: funktioniert auch mit negativen und / oder Gleitkommazahlen:

*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]
                |

Edit: @BlackCap speicherte 2 Bytes. Vielen Dank!

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

Python 2, 267 Bytes

Es funktioniert auch mit Dezimalstellen und negativen Zahlen.

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

Beispiel:

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
Peter
quelle
1

JavaScript (ES6), 147 155

Die Verwendung von n * n vergleicht aber (glaube ich) die minimale Anzahl von Swaps. Und die Swap-Positionen sind im Vergleich zur langweiligen Bubble-Sorte variabler.

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)

Weniger Golf und hoffentlich verständlicher

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

Prüfung

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>

edc65
quelle
0

Java 7, 256 241 282 Bytes

Vielen Dank an @Geobits und @Axelh für das Speichern von 15 Bytes

 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();}}

Ungolfed

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

}
}

Ausgabe

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 
Zahlenknoten
quelle
4
Hier fehlt noch die Deklaration von out, Sie müssen so etwas wie PrintStream out=System.out;irgendwo in Ihren Code einfügen.
Loovjo
2
Nach dem Korrigieren des Imports / der Deklaration von outsollten Sie einen Ternären verwenden, anstatt if/elseauf beiden Zweigen zu drucken. So etwas wie out.print(a>b?a:b);stattif(a>b)out.print(a);else out.print(b);
Geobits
Sie können das if else wie folgt reduzieren: if(j==i|j==m)out.print(a[j]);out.print(" ");oder noch besser mit einem ternären out.print((j==i|j==m?a[j]:" ")+" ");und dann können Sie {} der Schleife entfernen PS: Ich verwende eine Importstatik für die out-Instanz, wenn das in
Ordnung ist
Hmm, abgesehen von den Golf - Tipps von den anderen, ist der Ausgang falsch .. Hier ist ein ideone mit Ihrem Code kopieren kleistert (und hinzugefügt System.vor dem outs), und es ist das fehlende 2und 3auf den beiden letzten Swap-Linien.
Kevin Cruijssen
@ KevinCruijssen Ich habe es korrigiert. Eigentlich mische ich i Variable mit j Variable (sollte i sein) in dieser Zeilefor(j=0;j<=m&i!=l-1;j++)
Numberknot
0

Gelee , 36 Bytes

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

Probieren Sie es online!

Erläuterung

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

Das in der TIO-Verknüpfung gezeigte Beispiel ist für dieses Programm besonders schwierig. Die ;0Option in der Nähe des Starts ist erforderlich, um sicherzustellen, dass die Schleife genau an dem Punkt endet, an dem die Eingabe sortiert wird. Dies ist normalerweise nicht erforderlich (da es nach einer weiteren Iteration endet), aber wenn der letzte Swap aus den ersten beiden Elementen besteht (wie hier zu sehen), wird die nochmalige Iteration nicht durchgeführt und macht es unmöglich, den Vorgang abzuschließen die Liste konsistent. Als solches müssen wir sicherstellen, dass wir bei der letzten Schleifeniteration nichts austauschen.


quelle