Hình dung sắp xếp


20

Giả sử tôi có một danh sách như [3, 0, 4, 2, 1], và tôi sử dụng sắp xếp lựa chọn để sắp xếp nó, tôi có thể hình dung nó như thế này:

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

Thử thách này là về hình dung sắp xếp như thế này.

Đầu vào

Đầu vào của bạn sẽ là một danh sách các số nguyên dương, ở bất kỳ định dạng nào bạn muốn.

Bài tập

Nội dung gửi của bạn nên sắp xếp danh sách đầu vào bằng cách chỉ hoán đổi hai yếu tố tại một thời điểm và tại mỗi lần hoán đổi, nội dung gửi sẽ hiển thị danh sách và một ký tự bên dưới mỗi thành phần được hoán đổi. Nếu một số được hoán đổi có nhiều hơn một chữ số, ký tự có thể ở bất cứ đâu bên dưới nó. Cuối cùng, bài nộp sẽ hiển thị danh sách đã sắp xếp.

Các quy tắc khác

  • Việc sắp xếp phải sử dụng ít giao dịch hoán đổi hơn n 4 , trong đó n là độ dài của danh sách.
  • Việc sắp xếp không nhất thiết phải mang tính quyết định.
  • Các nhân vật dưới tráo đổi có thể là bất kỳ char ngoại trừ không gian.

Tôi có thể cho rằng các số nguyên là duy nhất?
Jörg Hülsermann

n^4? Bạn có một chút hào phóng ở đây.
orlp

@ JörgHülsermann Không
Loovjo

2
Nếu bất cứ ai quan tâm đến việc sắp xếp toptal.com/developers/sorting-alacticms
exussum

3
Bạn nói đầu vào là số nguyên dương nhưng ví dụ của bạn có 0(vui lòng chỉ sửa ví dụ để không làm mất hiệu lực các câu trả lời không thể xử lý 0)
TonMedel

Câu trả lời:


10

Perl, 62 byte

Bao gồm +3 cho -p

Cung cấp đầu vào dưới dạng một dòng số trên STDIN:

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

Liên tục hoán đổi đảo ngược đầu tiên. Hoán đổi phức tạp là O(n^2), phức tạp thời gian là O(n^3). Sử dụng các số được hoán đổi làm dấu:

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

Chương trình cũng hỗ trợ các giá trị âm và số dấu phẩy động

Nếu bạn nhấn mạnh vào một ký tự kết nối, mã sẽ trở thành 66 byte:

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

Nhưng bây giờ nó không hỗ trợ số âm và 0 nữa (nhưng chương trình chỉ phải hỗ trợ số nguyên dương. Dù sao, 0trong ví dụ này là một lỗi)


Cho rằng The characters under the swapped can be any char except space. bạn không nên có khoảng trắng giữa các số trong dòng đánh dấu
edc65

@ edc65 Các ký tự bên dưới các phần tử được hoán đổi không phải là khoảng trắng. Không có gì được nói về các nhân vật giữa họ
TonMedel

Không hoàn toàn thuyết phục, nhưng ok. Tôi đã quá nhanh xuống (nhưng tôi đã nhận được sự chú ý của bạn). Nếu bạn thực hiện chỉnh sửa (trống) cho câu trả lời của mình, tôi sẽ thay đổi phiếu bầu của mình
edc65

@ edc65 Chà, bình luận của bạn khiến tôi đọc lại thử thách rất cẩn thận. Lưu ý rằng anh ta cũng nói về trường hợp số nhiều chữ số rõ ràng có nghĩa là bạn có thể ví dụ như chỉ đặt một _chữ số dưới chữ số đầu tiên, điều đó có nghĩa là tất cả các ký tự ở giữa thực tế sẽ là khoảng trắng). Vì vậy, tôi đứng trước sự giải thích của tôi (trừ khi OP không đồng ý). Buit chỉ để làm cho bạn hạnh phúc Tôi đã thêm một phiên bản không có không gian quá :-)
TonMedel

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

Sắp xếp bong bóng. Đầu ra mẫu:

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 Vì tôi luôn hoán đổi các phần tử liền kề, tôi luôn có thể đặt bên -dưới ,và sau đó hai |s sẽ luôn ở dưới các số liền kề.
Neil

aah, thông minh! Cảm ơn!
nimi

1
Bubble sort là một lựa chọn thực sự khôn ngoan thực sự để đơn giản hóa việc làm nổi bật các con số hoán đổi. Làm tốt!
Arnauld

9

PHP, 248 byte

Chiến thắng nhàm chán của Bubbledort

<?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 Byte một cách với mảng_slice và min

đầu ra sửa đổi I Xthay vì*~~*

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

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

Làm thế nào nó hoạt động

Tìm kiếm mức tối thiểu trong một mảng và thực hiện điều này ở vị trí đầu tiên Tìm kiếm mức tối thiểu không có vị trí đầu tiên .... và cứ thế Nếu một giá trị gấp đôi, giá trị đầu tiên sẽ được hoán đổi

Ví dụ đầu ra

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

Thay vì echo$t."\n";, bạn có thể sử dụng echo"$t\n";và lưu một byte.
Ismael Miguel

@IsmaelMiguel Hãy thoải mái chỉnh sửa bài viết của tôi nếu bạn tìm thấy điều gì đó cần cải thiện
Jörg Hülsermann

7
Chỉnh sửa mã trên bài viết thường được tán thành, mà tôi hoàn toàn đồng ý với.
Ismael Miguel

3

Haskell, 165 164 162 byte

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

Điều này hình dung sắp xếp lựa chọn. Ví dụ sử dụng:

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

Làm thế nào nó hoạt động:

s % clà một chức năng trợ giúp tạo ra các length (show s) - 2bản sao của nhân vật c. Nó được sử dụng để tạo khoảng cách trước cả hai |, một lần với c == ' 'và một lần với c == '-'.

Hàm chính #lấy một danh sách plà phần được sắp xếp của danh sách và xlà phần chưa được sắp xếp. Khớp mẫu sẽ (h,t:s)<-span(/=minimum x)xphân chia danh sách xở phần tử tối thiểu của nó và liên kết hvới phần trước mức tối thiểu, tđến mức tối thiểu và svới phần sau mức tối thiểu. Phần còn lại là định dạng hai dòng: 1) danh sách ở trạng thái hiện tại ( p++x) và 2) |----|phần tiếp theo là một cuộc gọi đệ quy #với phần được tnối vào pvà phần đầu hđược chèn giữa đuôi hs.

PS: cũng hoạt động với số negativ và / hoặc dấu phẩy động:

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

Chỉnh sửa: @BlackCap đã lưu 2 byte. Cảm ơn!


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

1

Python 2, 267 byte

Nó hoạt động với số thập phân và số âm là tốt.

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

Thí dụ:

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

Sử dụng so sánh n * n, nhưng (tôi tin) số lần hoán đổi tối thiểu. Và các vị trí hoán đổi có nhiều thay đổi so với loại bong bóng nhàm chá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)

Ít chơi gôn hơn và hy vọng dễ hiểu hơn

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

Kiểm tra

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 byte

Cảm ơn @Geobits và @Axelh vì đã lưu 15 byte

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

Ung dung

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

}
}

đầu ra

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
Điều này vẫn còn thiếu khi khai báo out, bạn cần đặt một cái gì đó giống như PrintStream out=System.out;ở đâu đó trong mã của bạn.
Loovjo

2
Sau khi sửa lỗi nhập / khai báo out, bạn nên sử dụng một ternary thay vì if/elsenếu bạn sẽ in trên cả hai nhánh. Một cái gì đó giống như out.print(a>b?a:b);thay vìif(a>b)out.print(a);else out.print(b);
Geobits

Bạn có thể giảm if if liek this: if(j==i|j==m)out.print(a[j]);out.print(" ");hoặc thậm chí tốt hơn với một ternary out.print((j==i|j==m?a[j]:" ")+" ");và sau đó bạn có thể xóa {} của vòng lặp PS: Tôi sử dụng một tĩnh nhập cho ví dụ out, nếu điều đó ổn;)
AxelH

Hmm, ngoài các mẹo chơi gôn từ những người khác, đầu ra không chính xác .. Đây là một ideone với mã được sao chép của bạn (và được thêm System.vào trước outs), và nó thiếu 23trên hai dòng hoán đổi cuối cùng.
Kevin Cruijssen

@KevinCruijssen Tôi đã sửa nó. Thực tế, tôi trộn lẫn biến i với biến j (nên là i) trong dòng nàyfor(j=0;j<=m&i!=l-1;j++)
Numberjack

0

Thạch , 36 byte

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

Hãy thử trực tuyến!

Giải trình

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

Ví dụ hiển thị trong liên kết TIO là một ví dụ đặc biệt khó đối với chương trình này; việc ;0bắt đầu gần là cần thiết để đảm bảo rằng vòng lặp kết thúc tại điểm đầu vào được sắp xếp. Điều này thường không cần thiết (vì nó sẽ kết thúc sau một lần lặp nữa), nhưng nếu lần hoán đổi cuối cùng là hai yếu tố đầu tiên (như được thấy ở đây), thì việc lặp lại nhiều lần sẽ không xảy ra và khiến nó không thể kết thúc danh sách nhất quán. Như vậy, chúng ta cần đảm bảo rằng chúng ta không trao đổi bất cứ điều gì trên vòng lặp cuối cùng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.