정렬 시각화


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은 목록의 길이입니다.
  • 정렬은 결정론적일 필요는 없습니다.
  • 교체 된 문자는 공백을 제외한 모든 문자가 될 수 있습니다.

정수가 고유하다고 가정 할 수 있습니까?
— Jörg Hülsermann

n^4? 당신은 여기서 조금 관대합니다.
— orlp

@ JörgHülsermann No
— Loovjo

2
누군가가 정렬에 관심이 있다면 toptal.com/developers/sorting-algorithms 분
— exussum

3
입력이 양의 정수라고 말하지만 예제에는 0(0을 처리 할 수없는 응답을 무효화하지 않도록 예제 만 수정하십시오)
— Ton Hospel

답변:


10

펄, 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 교체되는 요소 아래의 문자가 공백이 아닙니다. 그들 사이에 관한 이야기는 없습니다
— Ton Hospel

완전히 확신하는 것은 아니지만 괜찮습니다. 나는 너무 빠른 downvoting했다 (그러나 나는 당신의 관심을 얻었다). 답변을 (빈) 편집하면 투표가 변경됩니다
— edc65

@ edc65 글쎄, 당신의 의견은 내가 도전을 매우 신중하게 다시 읽게 만들었다. 그는 또한 여러 자릿수의 경우에 대해 분명히 말하고 있음을 의미합니다. 예를 들어 _첫 번째 숫자 아래 에 a 를 넣으면 사실상 모든 문자가 공백이됩니다). 따라서 OP가 동의하지 않는 한 내 해석을지지합니다. Buit 그냥 당신을 행복하게하기 위해 공간이없는 버전도 추가했습니다 :-)
— Ton Hospel

9

자바 스크립트 (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, 나는 항상을 넣을 수 있습니다 -세 이하 ,다음 두 |들 항상 인접한 숫자 아래에있을 것입니다.
— Neil

아 영리하다! 감사!
— nimi

1
버블 정렬은 실제로 스왑 된 숫자의 강조 표시를 단순화하기 위해 실제로 신중한 선택입니다. 잘 했어!
— Arnauld

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

array_slice와 min을 이용한 PHP, 266 바이트

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

작동 원리

배열에서 최소값을 찾아서 첫 번째 위치에서 가져옵니다. 첫 번째 위치없이 최소값을 찾습니다 .... 등. 값이 두 배이면 첫 번째 값이 스왑됩니다

출력 예

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";하고 저장할 수 있습니다 .
— Ismael Miguel

@IsmaelMiguel 개선해야 할 점이 있으면 내 게시물을 자유롭게 편집하십시오
— Jörg Hülsermann

7
게시물의 코드 편집은 일반적으로 싫증이납니다.
— Ismael Miguel

3

하스켈 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 % clength (show s) - 2캐릭터 를 복사 하는 도우미 함수입니다 c. |한 번으로 c == ' '및 한 번으로 간격을두기 전에 사용 됩니다 c == '-'.

main 함수 #는 목록 p의 정렬 된 부분이며 x아직 정렬되지 않은 목록을 가져옵니다. 패턴 일치 (h,t:s)<-span(/=minimum x)x는 목록 x을 최소 요소로 분할 하고 최소값 h이전 부분 t, 최소값 자체 및 s최소값 이후 부분에 바인딩 합니다 . 나머지는 두 줄의 형식을 지정합니다 .1) 현재 상태의 목록 ( p++x) 및 2) |----|부분 뒤에 꼬리 부분 과 꼬리 부분 사이에 머리 #를 t추가 하고 재귀 호출 합니다.phhs .

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

파이썬 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

자바 스크립트 (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

자바 7, 256 241 282 바이트

15 바이트를 절약 한 @Geobits 및 @Axelh에게 감사합니다

 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);
— Geobits

그렇지 않으면 이것을 if(j==i|j==m)out.print(a[j]);out.print(" ");좋아 하는 경우를 줄일 수 있습니다 : 또는 삼항으로 더 나은 out.print((j==i|j==m?a[j]:" ")+" ");다음 루프 PS의 {}를 제거 할 수 있습니다 : 괜찮다면 out 인스턴스에 대해 가져 오기 정적을 사용합니다.;
— AxelH

흠, 떨어져 다른 사람의 골프 팁에서, 출력은 .. 잘못 여기에 코드를 복사 - 붙여 넣기를 가진 ideone이다 (그리고 추가 System.의 앞에 out들), 그리고 그것은을 실종 2과 3마지막 두 스왑 라인.
— Kevin Cruijssen

@KevinCruijssen 나는 버렸죠 내가이 줄 (I이어야한다) 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시작 근처 루프는 단지 입력이 정렬이되는 시점에서 종료되도록 할 필요가있다. 이것은 일반적으로 필요하지 않습니다 (하나 이상의 반복 후에 종료되기 때문에). 마지막 스왑이 처음 두 요소 (여기에서 볼 수 있듯이) 인 경우, 하나 이상의 반복이 발생하지 않고 완료 할 수 없습니다. 일관된 목록. 따라서 마지막 루프 반복에서 아무것도 바꾸지 않도록해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.