Thực hiện thuật toán sắp xếp Thanos


93

Thuật toán sắp xếp như sau:

Trong khi danh sách không được sắp xếp, hãy chụp một nửa tất cả các mục (xóa chúng khỏi danh sách). Tiếp tục cho đến khi danh sách được sắp xếp hoặc chỉ còn một mục (được sắp xếp theo mặc định). Thuật toán sắp xếp này có thể cho kết quả khác nhau dựa trên việc thực hiện.

Quy trình loại bỏ vật phẩm tùy thuộc vào việc thực hiện để quyết định, nhưng danh sách nên dài hơn một nửa so với trước khi vượt qua quy trình loại bỏ vật phẩm. Thuật toán của bạn có thể quyết định xóa nửa đầu hoặc danh sách, nửa cuối của danh sách, tất cả các mục lẻ, tất cả các mục chẵn, mỗi lần một danh sách cho đến khi danh sách dài bằng một nửa hoặc bất kỳ mục nào không được đề cập.

Danh sách đầu vào có thể chứa một lượng vật phẩm tùy ý (theo lý do, giả sử có tới 1000 mặt hàng), không chỉ danh sách chia hết cho 2 ^ n mặt hàng. Bạn sẽ phải xóa (n + 1) / 2 hoặc (n-1) / 2 mục nếu danh sách là số lẻ, được mã hóa cứng hoặc được quyết định ngẫu nhiên trong thời gian chạy. Tự quyết định: Thanos sẽ làm gì nếu vũ trụ chứa một lượng sinh vật kỳ lạ?

Danh sách được sắp xếp nếu không có mục nào nhỏ hơn bất kỳ mục nào trước đó. Sự trùng lặp có thể xảy ra ở đầu vào và có thể xảy ra ở đầu ra.

Chương trình của bạn sẽ lấy một mảng các số nguyên (thông qua stdin hoặc dưới dạng tham số, các mục riêng lẻ hoặc tham số mảng) và trả về mảng đã sắp xếp (hoặc in nó ra thiết bị xuất chuẩn).

Ví dụ:

// A sorted list remains sorted
[1, 2, 3, 4, 5] -> [1, 2, 3, 4, 5]

// A list with duplicates may keep duplicates in the result
[1, 2, 3, 4, 3] -> [1, 3, 3] // Removing every second item
[1, 2, 3, 4, 3] -> [3, 4, 3] -> [4, 3] -> [3] // Removing the first half
[1, 2, 3, 4, 3] -> [1, 2] // Removing the last half

[1, 2, 4, 3, 5] có thể cho kết quả khác nhau:

// Removing every second item:
[1, 2, 4, 3, 5] -> [1, 4, 5]

hoặc là:

// Removing the first half of the list
[1, 2, 4, 3, 5] -> [3, 5] // With (n+1)/2 items removed
[1, 2, 4, 3, 5] -> [4, 3, 5] -> [3, 5] // With (n-1)/2 items removed

hoặc là:

// Removing the last half of the list
[1, 2, 4, 3, 5] -> [1, 2] // With (n+1)/2 items removed
[1, 2, 4, 3, 5] -> [1, 2, 4] // With (n-1)/2 items removed

hoặc là:

// Taking random items away until half (in this case (n-1)/2) of the items remain
[1, 2, 4, 3, 5] -> [1, 4, 3] -> [4, 3] -> [4]

Có một trường hợp thử nghiệm thực sự đòi hỏi nhiều snaps cho nhiều thuật toán chụp khác nhau sẽ rất hữu ích.
Chuỗi không liên quan

22
Đừng cần sắp xếp và loại bỏ một nửa câu trả lời ...
Sumner18

4
Trường hợp thử nghiệm đề xuất : [9, 1, 1, 1, 1]. Thuật toán của riêng tôi đã thất bại với đầu vào này
Conor O'Brien

Câu trả lời:





12

Brachylog (v2), 6 byte

≤₁|ḍt↰

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

Đây là một đệ trình chức năng. Đầu vào từ bên trái, đầu ra bên phải, như thường lệ. (Liên kết TIO sử dụng đối số dòng lệnh tự động bao hàm hàm thành một chương trình đầy đủ để bạn có thể thấy nó hoạt động.)

Giải trình

≤₁|ḍt↰
≤₁       Assert that {the input} is sorted {and output it}
  |      Handler for exceptions (e.g. assertion failures):
   ḍ     Split the list into two halves (as evenly as possible)
    t    Take the last (i.e. second) half
     ↰   Recurse {and output the result of the recursion}

Vòng thưởng

≤₁|⊇ᵇlᵍḍhtṛ↰

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

Ảnh chụp có nghĩa là ngẫu nhiên, phải không? Đây là phiên bản của chương trình chọn ngẫu nhiên các yếu tố sống sót (trong khi đảm bảo rằng một nửa tồn tại ở mỗi vòng).

≤₁|⊇ᵇlᵍḍhtṛ↰
≤₁            Assert that {the input} is sorted {and output it}
  |           Handler for exceptions (e.g. assertion failures):
   ⊇ᵇ         Find all subsets of the input (preserving order)
     lᵍ       Group them by length
       ḍht    Find the group with median length:
         t      last element of
        h       first
       ḍ        half (split so that the first half is larger)
          ṛ   Pick a random subset from that group
           ↰  Recurse

Điều này sẽ khá ngắn hơn nếu chúng ta có thể sắp xếp lại các yếu tố, nhưng tại sao một thuật toán sắp xếp lại muốn làm điều đó ?


12
Một byte cho mỗi viên đá vô cực.
djechlin

@djechlin byte vô cực là lý do tại sao bạn phải đi đầu và đặc biệt là hàm.
Vịt lớn

10

Perl 6 , 30 byte

$!={[<=]($_)??$_!!.[^*/2].&$!}

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

Hàm đệ quy loại bỏ nửa sau của danh sách cho đến khi danh sách được sắp xếp.

Giải trình:

$!={                         }    # Assign the function to $!
    [<=]($_)??                    # If the input is sorted
              $_                  # Return the input
                !!                # Else
                  .[^*/2]         # Take the first half of the list (rounding up)
                         .&$!     # And apply the function again


8

Java 10, 106 97 byte

L->{for(;;L=L.subList(0,L.size()/2)){int p=1<<31,f=1;for(int i:L)f=p>(p=i)?0:f;if(f>0)return L;}}

-9 byte nhờ @ OlivierGrégoire .

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

Chỉ để lại một nửa đầu tiên của danh sách mỗi lần lặp và xóa n+12 mục nếu kích thước danh sách là số lẻ.

Giải trình:

L->{               // Method with Integer-list as both parameter and return-type
  for(;;           //  Loop indefinitely:
      L=L.subList(0,L.size()/2)){
                   //    After every iteration: only leave halve the numbers in the list
    int p=1<<31,   //   Previous integer, starting at -2147483648
        f=1;       //   Flag-integer, starting at 1
    for(int i:L)   //   Inner loop over the integer in the list:
      f=p>(p=i)?   //    If `a>b` in a pair of integers `a,b`:
         0         //     Set the flag to 0
        :          //    Else (`a<=b`):
         f;        //     Leave the flag the same
    if(f>0)        //   If the flag is still 1 after the loop:
      return L;}}  //    Return the list as result

n->{for(;n.reduce((1<<31)+0d,(a,b)->a==.5|b<a?.5:b)==.5;n=n.skip(n.count()/2));return n;} sử dụng các luồng ngắn hơn, nhưng tôi chưa thể tìm ra cách tránh java.lang.IllegalStateException: stream has already been operated upon or closedlỗi sau khi trả lại luồng
Hiện thân của sự thờ ơ

@EmbodimentofIgnorance điều này xảy ra vì reducelà một hoạt động đầu cuối đóng luồng. Bạn sẽ không bao giờ có thể gọi reducehai lần trên cùng một luồng. Bạn có thể tạo một luồng mới, mặc dù.
Olivier Grégoire


@ OlivierGrégoire Thứ tự đó bây giờ trông đơn giản đến mức tôi thấy nó .. Đôi khi phải nhìn từ một góc độ khác để thấy những người khác rõ ràng ban đầu tôi nhớ. :) Cảm ơn!
Kevin Cruijssen

1
Đừng lo lắng, điều đó không rõ ràng: tôi đã làm việc để đến đó. Tôi đã thử nghiệm ít nhất 10 phiên bản trước khi tìm thấy phiên bản đó;)
Olivier Grégoire

8

Ngôn ngữ Wolfram (Mathicala) , 30 byte

#//.x_/;Sort@x!=x:>x[[;;;;2]]&

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

@Doorknob đã lưu 12 byte


1
Thay vì lấy nửa đầu, bạn có thể lưu một số byte bằng cách lấy mọi phần tử khác ( x[[;;;;2]]).
Doorknob

@Doorknob tất nhiên rồi ...
J42161217

nghĩ rằng có thể có một số tiền tiết kiệm bằng cách sử dụng OrderedQ, nhưng không thể làm cho nó hoạt động
Greg Martin

@GregMartin Tôi đã sử dụng OrderedQtheo cách tiếp cận đầu tiên của mình (xem các chỉnh sửa)
J42161217



6

05AB1E , 8 7 byte

[Ð{Q#ιн

-1 byte nhờ @Emigna .

viết sai rồi-12 mục nếu kích thước danh sách là số lẻ.

Dùng thử trực tuyến hoặc xác minh thêm một số trường hợp kiểm tra (hoặc xác minh các trường hợp kiểm tra đó từng bước cho mỗi lần lặp ).

7 byte thay thế bởi @Grimy :

ΔÐ{Ê>äн

Xóa cái cuối cùng viết sai rồi2viết sai rồi-12 mục nếu kích thước danh sách là số lẻ) mỗi lần lặp.

Dùng thử trực tuyến hoặc xác minh thêm một số trường hợp kiểm tra (hoặc xác minh các trường hợp kiểm tra đó từng bước cho mỗi lần lặp ).

Giải trình:

[        # Start an infinite loop:
 Ð       #  Triplicate the list (which is the implicit input-list in the first iteration)
  {Q     #  Sort a copy, and check if they are equal
    #    #   If it is: Stop the infinite loop (and output the result implicitly)
  ι      #  Uninterweave: halve the list into two parts; first containing all even-indexed
         #  items, second containing all odd-indexed items (0-indexed)
         #   i.e. [4,5,2,8,1] → [[4,2,1],[5,8]]
   н     #  And only leave the first part

Δ        # Loop until the result no longer changes:
 Ð       #  Triplicate the list (which is the implicit input-list in the first iteration)
       #  Sort a copy, and check if they are NOT equal (1 if truthy; 0 if falsey)
    >    #  Increase this by 1 (so 1 if the list is sorted; 2 if it isn't sorted)
     ä   #  Split the list in that many parts
      н  #  And only leave the first part
         # (and output the result implicitly after it no longer changes)

3
Bạn có thể sử dụng ιthay vì nếu bạn chuyển sang giữ mọi chiến lược yếu tố khác .
Emigna

1
Giải pháp thay thế 7 sử dụng chiến lược "xóa nửa cuối":ΔÐ{Ê>äн
Grimy

@Grimy Đó cũng là một cách tiếp cận khá hay. Tôi sẽ thêm nó vào bài viết của mình (tất nhiên là ghi có cho bạn), hoặc bạn muốn đăng nó dưới dạng một câu trả lời riêng biệt?
Kevin Cruijssen

Hãy thêm nó vào.
Grimy

6

TI-BASIC (TI-84), 47 42 45 44 byte

-1 byte nhờ @SolomonUcko!

Ans→L1:Ans→L2:SortA(L1:While max(L1≠Ans:iPart(.5dim(Ans→dim(L2:L2→L1:SortA(L1:End:Ans

Danh sách đầu vào là trong Ans.
Đầu ra là trong Ansvà được in ra.

Giải trình:

Ans→L1                  ;store the input into two lists
Ans→L2
SortA(L1                ;sort the first list
                        ; two lists are needed because "SortA(" edits the list it sorts
While max(L1≠Ans        ;loop until both lists are strictly equal
iPart(.5dim(Ans→dim(L2  ;remove the latter half of the second list
                        ; removes (n+1)/2 elements if list has an odd length
L2→L1                   ;store the new list into the first list (updates "Ans")
SortA(L1                ;sort the first list
End
Ans                     ;implicitly output the list when the loop ends

Lưu ý: TI-BASIC là ngôn ngữ được mã hóa. Số lượng ký tự không bằng số byte.


Tôi nghĩ bạn có thể thay thế not(min(L1=Ansbằng max(L1≠Ansđể tiết kiệm một byte.
Solomon Ucko



3

Octave , 49 byte

l=input('');while(~issorted(l))l=l(1:2:end);end;l

Hãy thử trực tuyến!Đây là một hành trình mà nhàm chán hơn là tốt hơn. Lưu ý hai mục thú vị hơn nhiều dưới đây:

50 byte

function l=q(l)if(~issorted(l))l=q(l(1:2:end));end

Hãy thử trực tuyến!Thay vì giải pháp mệnh lệnh không thú vị, chúng ta có thể thực hiện một giải pháp đệ quy, chỉ với một byte bổ sung.

53 byte

f(f=@(g)@(l){l,@()g(g)(l(1:2:end))}{2-issorted(l)}())

Hãy thử trực tuyến! Vâng. Một hàm ẩn danh đệ quy, nhờ câu trả lời xuất sắc của @ Barecat về câu hỏi của tôi . Hàm ẩn danh trả về hàm ẩn danh đệ quy bằng cách định nghĩa chính nó trong danh sách đối số của nó. Tôi thích chức năng ẩn danh. Mmmmm.


2

MATL , 11 byte

tv`1L)ttS-a

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

Điều này hoạt động bằng cách loại bỏ mọi mục thứ hai.

Giải trình

t      % Take a row vector as input (implicit). Duplicate
v      % Vertically concatenate the two copies of the row vector. When read with
       % linear indexing (down, then across), this effectively repeats each entry
`      % Do...while
  1L)  %   Keep only odd-indexed entries (1-based, linear indexing)
  t    %   Duplicate. This will leave a copy for the next iteration
  tS   %   Duplicate, sort
  -a   %   True if the two arrays differ in any entry
       % End (implicit). A new iteration starts if the top of the stack is true
       % Display (implicit). Prints the array that is left on the stack

2
Bị hỏng cho danh sách được sắp xếp ban đầu: [1, 2, 3, 4, 5] sẽ vẫn còn [1, 2, 3, 4, 5]
Falco

@Falco Cảm ơn! Sửa ngay
Luis Mendo

2

Japt , 10 byte

eUñ)?U:ßUë

Thử nó

eUñ)?U:ßUë     :Implicit input of array U
e              :Compare equality with
 Uñ            :  U sorted
   )           :End compare
    ?U:        :If true then return U else
       ß       :Run the programme again with input
        Uë     :  Every second element of U



2

Chồng , 6 5 byte

Lưu 1 byte nhờ Zgarb

ΩΛ<Ċ2

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

Giải trình

ΩΛ<Ċ2
Ω         Repeat until
 Λ<         all adjacent pairs are sorted (which means the list is sorted)
   Ċ2         drop every second element from the list

Đây là 11 byte, không phải 6. echo echo -n "ΩΛ <(←" | wc --bytes 11
Mike Holler


@MikeHoller Cũng như nhiều ngôn ngữ chơi gôn khác, Husk sử dụng trang mã tùy chỉnh để có quyền truy cập vào nhiều ký tự khác nhau: github.com/barbuz/Husk/wiki/Codepage
Leo

Cảm ơn bạn, tôi đã học được điều gì đó ngày hôm nay :)
Mike Holler

1
Sử dụng Ċ2thay vì (←½để lưu một byte.
Zgarb


2

Julia 1.0 , 30 byte

-x=x>sort(x) ? -x[1:2:end] : x

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

Mất mọi phần tử thứ hai của mảng nếu không được sắp xếp.


sử dụng toán tử ASCII như -cho 20 byte. Ngoài ra, chúng tôi hầu như không luôn đếm số ký tự: | vì vậy thật tuyệt nếu điều đó bị xóa khỏi tiêu đề
ASCII - chỉ

Thay đổi điều đó. Cảm ơn vì 2 byte!
niczky12

2

C ++ (gcc) , 103 byte

Tôi không thể nhận xét, nhưng tôi đã cải thiện phiên bản từ Movatica bằng cách giảm bao gồm và sử dụng tự động.

-2 byte: trần mèo
-2 byte: chỉ ASCII

#include<regex>
auto f(auto l){while(!std::is_sorted(l.begin(),l.end()))l.resize(l.size()/2);return l;}

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


1
lý do nào bạn không thể sử dụng l.size()/2?
ASCII - chỉ

Vâng, nó không hoạt động theo cách đó :)
peterzuger

1
Ý anh là gì? trả về một danh sách kích thước (n+1)/2hoặc (n-1)/2cả hai hợp lệ. hmm ....
ASCII-chỉ

Ohh oops không thấy lời cảm ơn đó
peterzuger

1

VDM-SL , 99 byte

f(i)==if forall x in set inds i&x=1or i(x-1)<=i(x) then i else f([i(y)|y in set inds i&y mod 2=0]) 

Không bao giờ gửi trong vdm trước, vì vậy không chắc chắn về các quy tắc ngôn ngữ cụ thể. Vì vậy, tôi đã gửi như một định nghĩa chức năng trong đó có mộtseq of int và trả vềseq of int

Một chương trình đầy đủ để chạy có thể trông như thế này:

functions
f:seq of int +>seq of int
f(i)==if forall x in set inds i&x=1or i(x-1)<=i(x) then i else f([i(y)|y in set inds i&y mod 2=0]) 

1

Bình thường, 10 byte

.W!SIHhc2Z

Hãy thử trực tuyến tại đây . Điều này loại bỏ nửa thứ hai trên mỗi lần lặp, làm tròn xuống. Để thay đổi nó để loại bỏ nửa đầu, làm tròn lên, thay đổi hthành e.

.W!SIHhc2ZQ   Q=eval(input())
              Trailing Q inferred
  !SIH        Condition function - input variable is H
   SIH          Is H invariant under sorting?
  !             Logical not
      hc2Z    Iteration function - input variable is Z
       c2Z      Split Z into 2 halves, breaking ties to the left
      h         Take the first half
.W        Q   With initial value Q, execute iteration function while condition function is true

Lấy tất cả các yếu tố khác của danh sách là ngắn hơn. Thay thế hcbằng %. Điều này cũng cho phép bạn xóa biến lambda trailing Zvà để Pyth điền nó hoàn toàn, với tổng số 2 byte được lưu.
hakr14

1

C ++ (gcc) , 139 137 116 byte

-2 byte sox đến trần, -21 byte sox với PeterZuger

#include<regex>
auto f(std::vector<int>l){while(!std::is_sorted(l.begin(),l.end()))l.resize(-~l.size()/2);return l;}

Thay đổi kích thước vectơ thành nửa đầu của nó cho đến khi nó được sắp xếp.

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


1
Nhập khẩu được yêu cầu để được bao gồm trong số byte, vì vậy bạn phải thêm includes
Hiện thân của sự thiếu hiểu biết

Thanx, tôi sẽ thêm chúng.
Movatica

1

K (oK) , 22 20 byte

Giải pháp:

{(*2 0N#x;x)x~x@<x}/

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

Lặp lại đầu vào cho đến khi nó được sắp xếp ... nếu nó không được sắp xếp, hãy lấy n / 2 mục đầu tiên.

{(*2 0N#x;x)x~x@<x}/ / the solution
{                 }/ / lambda that iterates
                <x   / indices that sort x ascending (<)
              x@     / apply (@) these indices back to x
            x~       / matches (~) x? returns 0 or 1
 (       ; )         / 2-item list which we index into
          x          / original input (ie if list was sorted)
       #x            / reshape (#) x
   2 0N              / as 2 rows
  *                  / take the first one      

Chỉnh sửa:

  • -2 byte nhờ ngn

1
(.5*#x)#x->*2 0N#x
ngn

Tôi đã cân nhắc thực hiện 2 0Nnhưng cho rằng nó sẽ dài hơn (không cần kiểm tra), cảm ơn!
streetster


0

Võng mạc , 38 byte

\d+
*
/(_+),(?!\1)/+`,_+(,?)
$1
_+
$.&

Hãy thử trực tuyến! Có các số được phân tách bằng dấu phẩy. Giải trình:

\d+
*

Chuyển đổi sang unary.

/(_+),(?!\1)/+`

Lặp lại trong khi danh sách chưa được sắp xếp ...

,_+(,?)
$1

... Xóa mọi phần tử chẵn.

_+
$.&

Chuyển đổi thành số thập phân.


0

C (gcc) , 66 byte

Tách ra nửa sau của danh sách mỗi lần lặp ( n/2+1các phần tử nếu độ dài là số lẻ).

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

Đưa đầu vào như một con trỏ đến điểm bắt đầu của một mảng inttheo sau bởi chiều dài của nó. Đầu ra bằng cách trả về độ dài mới của mảng (sắp xếp tại chỗ).

t(a,n,i)int*a;{l:for(i=0;i<n-1;)if(a[i]>a[++i]){n/=2;goto l;}a=n;}

Phiên bản bị đánh cắp:

t(a, n, i) int *a; { // take input as a pointer to an array of int, followed by its length; declare a loop variable i
  l: // jump label, will be goto'ed after each snap
  for(i = 0; i < n - 1; ) { // go through the whole array …
    if(a[i] > a[++i]) { // … if two elements are in the wrong order …
      n /= 2; // … snap off the second half …
      goto l; // … and start over
    }
  }
  a = n; // implicitly return the new length
}

Đề xuất ~i+nthay vìi<n-1
trần mèo
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.