Mã ngắn nhất để sắp xếp các điểm đi bộ


8

Thách thức là, đưa ra một danh sách các điểm, sắp xếp theo cách mà khi chúng được kết nối theo thứ tự này, chúng không bao giờ giao nhau.

Định dạng đầu vào (đọc từ stdin):

X Y
1 2
3 4
5 6
...

Đầu ra phải giống như đầu vào, nhưng được sắp xếp.

Quy tắc:

  • Bạn có thể bắt đầu từ bất kỳ điểm nào.
  • Điểm cuối cùng phải giống như điểm đầu tiên, tạo một mạch gần.
  • Nó nên được thực hiện xem xét lưới Cartesian.
  • Bạn có thể cho rằng các điểm đầu vào không nằm trên một dòng.
  • Điểm cuối của mỗi dòng không được tính là giao nhau.

Để được trợ giúp thêm:

biểu đồ


2
@Rizer Tại sao các mạch kín được đảm bảo giao nhau? (ví dụ của OP không)
Martin Ender

2
Nếu nó chỉ là một dòng, thì một giải pháp cơ bản được sắp xếp theo tọa độ thứ nhất và thứ hai, một loại sắp xếp mặc định cho các cặp, vì vậy nó chỉ là sắp xếp và không có gì lạ mắt hơn ở đây.
swish

3
@Rizer: Một mạch kín không nhất thiết phải tự giao nhau, ngoại trừ theo nghĩa tầm thường là điểm bắt đầu và điểm kết thúc giống nhau: hình ảnh "tốt" trong bài cho thấy một mạch kín không tự giao nhau. Hơn nữa, không có yêu cầu mạch kín, thách thức này trở nên hoàn toàn không đáng kể; Tôi có thể giải quyết nó trong sáu ký tự của GolfScript, năm trong số đó là xử lý I / O.
Ilmari Karonen

4
@Rizer: Bạn cũng có thể khẳng định rằng bất kỳ hai dòng liên tiếp nào trong đường dẫn phải luôn luôn giao nhau, vì chúng có chung một điểm cuối. Các "giao điểm" như vậy (trong đó "giao lộ" tại các điểm cuối của một vòng khép kín là một ví dụ) là không đáng kể và không thể được tính trong bất kỳ định nghĩa có ý nghĩa nào về "đường không tự giao nhau". (Dù sao, nếu bạn thực sự muốn trở thành nhà mô phạm, chỉ cần xác định từng phân đoạn dòng để bao gồm điểm bắt đầu nhưng không phải là điểm cuối của nó. Vấn đề đã được giải quyết.)
Ilmari Karonen

2
Câu hỏi như được chỉnh sửa xứng đáng được đóng lại là quá tầm thường. Chỉnh sửa không nên loại bỏ tất cả các thách thức từ một vấn đề. Do đó tôi đã cuộn nó lại. Nếu bất cứ ai không đồng ý, tôi sẽ sẵn sàng thảo luận về điều này trên meta.
Peter Taylor

Câu trả lời:


9

Toán học - 20 30 ký tự

Chỉ là phần sắp xếp

SortBy[%, ArcTan @@ # &]

Toàn bộ mã kiểm tra, bao gồm tạo 100 điểm ngẫu nhiên và vẽ đường thẳng

RandomReal[{-10, 10}, {100, 2}];
SortBy[%, ArcTan @@ # &];
ListPlot@% /. 
 Point[p_] :> {EdgeForm[Dashed], FaceForm[White], Polygon[p], 
   PointSize -> Large, Point[p]}

+26 ký tự

Nếu bạn yêu cầu đầu vào / đầu ra thích hợp, thì

"0 0
 4 4
 0 4
 4 0";
Grid@SortBy[%~ImportString~"Table", ArcTan @@ # &]

+2 ký tự

Chỉ cần thêm N@

Grid@SortBy[%~ImportString~"Table", ArcTan @@ N @ # &]

bởi vì mã ở trên chỉ hoạt động trên các số thực chứ không phải trên các số nguyên do hành vi kỳ lạ của Mathicala khi sắp xếp các biểu thức tượng trưng

N@Sort[{ArcTan[1], ArcTan[-2]}]
Sort[N@{ArcTan[1], ArcTan[-2]}]

{0.785398, -1.10715}
{-1.10715, 0.785398}

EDIT Tôi mới nhận ra nếu các điểm không xoay quanh điểm gốc thì nó sẽ không hoạt động, vì vậy nó cũng yêu cầu chuyển sang trung tâm của các điểm

SortBy[%, ArcTan @@ N[# - Mean@%] &]

nhập mô tả hình ảnh ở đây


Tôi đã cố gắng tìm một ví dụ ngược trong đó bạn có ba điểm phù hợp với "trung tâm của khối lượng". Tất cả chúng đều có cùng một arctangent, do đó, thứ tự không được xác định bởi mã của bạn, điều này có thể dẫn đến các kết nối của chúng chồng chéo. Tuy nhiên, đoạn mã của bạn dường như luôn sắp xếp các trường hợp đó từ trong ra ngoài, mặc dù ArcTankết quả của chúng thực sự giống hệt nhau đến bit cuối cùng. bạn có biết tại sao như vậy không? (đây là một trường hợp như vậy nếu bạn muốn chơi xung quanh nó {{1, 2}, {2, 4}, {3, 6}, {-5, 5}, {-6, -12}, {5, -5}}).
Martin Ender

1
@ m.buettner Từ SortBytài liệu: Nếu một số f [e_i] giống nhau, thì thứ tự chính tắc của e_i tương ứng được sử dụng.
swish

Tiện như thế nào! :)
Martin Ender

5

Câu hỏi đã thay đổi, do đó câu trả lời này chứa các phiên bản khác nhau, có và không có đường dẫn khép kín.

Perl, đường dẫn mở, 69 byte

print"@$_$/"for sort{$$a[0]<=>$$b[0]||$$a[1]<=>$$b[1]}map{[/\S+/g]}<>

Mỗi điểm được dự kiến ​​trong STDIN là đường thẳng, với tọa độ được phân tách bằng khoảng trắng.

Bất kỳ định dạng số nào đều được hỗ trợ mà Perl diễn giải thành số (bao gồm cả số dấu phẩy động).

Thí dụ:

0 0
4 4
0 4
4 0
-2 1
2 -2
2 4
3.21 .56
.035e2 -7.8
0 2

Đầu ra:

-2 1
0 0
0 2
0 4
2 -2
2 4
3.21 .56
.035e2 -7.8
4 0
4 4

Kết quả

Ung dung:

print "@$_$/" for            # print output line      
    sort {                   # sort function for two points $a and $b
        $$a[0] <=> $$b[0]    # compare x part                           
        || $$a[1] <=> $$b[1] # compare y part, if x parts are identical
    }
    map { [/\S+/g] }         # convert input line to point as array reference
    <>                       # read input lines               

Các biến thể mạch

Trong phiên bản câu hỏi đầu tiên, có một kết nối giữa điểm cuối cùng và điểm đầu tiên để tạo ra một mạch.

Trung tâm không phải là điểm hiện có, 253 byte

Biến thể này có thể thất bại, nếu trung tâm là một trong những điểm, xem ví dụ 3.

Chỉnh sửa:

  • Trong câu trả lời của mình, Swish nhận thấy rằng các điểm nên tập trung xung quanh gốc tọa độ để đảm bảo mạch không có chéo:

    • Sắp xếp nhu cầu biến đổi tọa độ.
    • Biểu diễn chuỗi gốc của các số cần được giữ cho đầu ra.
  • Sửa lỗi: trường hợp đặc biệt cho trục x âm đã bao gồm trục x dương.

print"$$_[2] $$_[3]$/"for sort{($X,$Y)=@$a;($x,$y)=@$b;(!$X&&!$Y?-1:0)||!$x&&!$y||!$Y&&!$y&&$X<0&&$x<0&&$X<=>$x||atan2($Y,$X)<=>atan2($y,$x)||$X**2+$Y**2<=>$x**2+$y**2}map{[$$_[0]-$M/$n,$$_[1]-$N/$n,@$_]}map{$n++;$M+=$$_[0];$N+=$$_[1];$_}map{[/\S+/g]}<>

Ví dụ 1:

4 4
-2 0
2 0
1 1
4 0
-2 -2
-3 -1
1 -2
3 0
2 -4
0 0
-1 -2
3 3
-3 0
2 3
-5 1
-6 -1

Đầu ra 1:

0 0
-6 -1
-3 -1
-2 -2
-1 -2
1 -2
2 -4
2 0
3 0
4 0
1 1
3 3
4 4
2 3
-5 1
-3 0
-2 0

Kết quả mạch 1

Ví dụ 2:

Kiểm tra đại diện số và chuyển đổi tọa độ.

.9e1 9
7 7.0
8.5 06
7.77 9.45

Đầu ra 2:

7 7.0
8.5 06
.9e1 9
7.77 9.45

Kết quả mạch 2

Ung dung:

print "$$_[2] $$_[3]$/" for sort { # print sorted points
    ($X, $Y) = @$a;                # ($X, $Y) is first point $a
    ($x, $y) = @$b;                # ($x, $y) is second point $b
    (!$X && !$Y ? -1 : 0) ||       # origin comes first, test for $a
    !$x && !$y ||                  # origin comes first, test for $b
    !$Y && !$y && $X < 0 && $x < 0 && $X <=> $x ||
        # points on the negative x-axis are sorted in reverse order
    atan2($Y, $X) <=> atan2($y, $x) ||
        # sort by angles; the slope y/x would be an alternative,
        # then the x-axis needs special treatment
    $X**2 + $Y**2 <=> $x**2 + $y**2
        # the (quadratic) length is the final sort criteria
}
map { [ # make tuple with transformed and original coordinates
        # the center ($M/$n, $N/$n) is the new origin
        $$_[0] - $M/$n,  # transformed x value
        $$_[1] - $N/$n,  # transformed y value
        @$_              # original coordinates
] }
map {
    $n++;                # $n is number of points
    $M += $$_[0];        # $M is sum of x values
    $N += $$_[1];        # $N is sum of y values
    $_                   # pass orignal coordinates through
}
map {                    # make tuple with point coordinates
    [ /\S+/g ]           # from non-whitespace in input line
}
<>                       # read input lines

Không giới hạn, 325 byte

print"$$_[2] $$_[3]$/"for sort{($X,$Y)=@$a;($x,$y)=@$b;atan2($Y,$X)<=>atan2($y,$x)||$X**2+$Y**2<=>$x**2+$y**2}map{[$$_[0]-$O/9,$$_[1]-$P/9,$$_[2],$$_[3]]}map{$O=$$_[0]if$$_[0]>0&&($O>$$_[0]||!$O);$P=$$_[1]if$$_[1]>0&&($P>$$_[1]||!$P);[@$_]}map{[$$_[0]-$M/$n,$$_[1]-$N/$n,@$_]}map{$n++;$M+=$$_[0];$N+=$$_[1];$_}map{[/\S+/g]}<>

Trong phiên bản trước, trung tâm được đặt ở điểm bắt đầu và các điểm cuối cùng trên trục âm được sắp xếp theo thứ tự ngược lại để có được chéo miễn phí đến trung tâm một lần nữa. Tuy nhiên, điều này là không đủ, bởi vì những điểm cuối cùng có thể nằm trên một dòng khác. Do đó, ví dụ 3 sau đây sẽ thất bại.

Điều này được khắc phục bằng cách di chuyển gốc tọa độ một chút lên trên cùng và bên phải. Do định tâm, phải có ít nhất một điểm có giá trị x dương và một điểm có giá trị y dương. Do đó, mức tối thiểu của các giá trị x và y dương được lấy và giảm xuống còn một phần chín (một nửa hoặc một phần ba có thể là đủ). Điểm này không thể là một trong những điểm hiện có và được tạo ra nguồn gốc mới.

Các phương pháp điều trị đặc biệt về nguồn gốc và trục x âm có thể được loại bỏ, bởi vì có bất kỳ điểm nào nằm trên nguồn gốc mới.

Ví dụ 3:

-2 -2
-1 -1
-2 2
-1 1
2 -2
1 -1
2 2
1 1
0 0

Đầu ra 3:

0 0
-1 -1
-2 -2
1 -1
2 -2
1 1
2 2
-2 2
-1 1

Kết quả 3

Ví dụ 1 bây giờ được sắp xếp khác nhau:

Kết quả 1

Ung dung:

print "$$_[2] $$_[3]$/" for sort { # print sorted points        
    ($X, $Y) = @$a;                # ($X, $Y) is first point $a 
    ($x, $y) = @$b;                # ($x, $y) is second point $b
    atan2($Y, $X) <=> atan2($y, $x) ||
        # sort by angles; the slope y/x would be an alternative,
        # then the x-axis needs special treatment
    $X**2 + $Y**2 <=> $x**2 + $y**2
        # the (quadratic) length is the final sort criteria
}  
map { [ # make tuple with transformed coordinates
    $$_[0] - $O/9, $$_[1] - $P/9,  # new transformed coordinate
    $$_[2],  $$_[3]                # keep original coordinate
] }
map {
    # get the minimum positive x and y values 
    $O = $$_[0] if $$_[0] > 0 && ($O > $$_[0] || !$O);         
    $P = $$_[1] if $$_[1] > 0 && ($P > $$_[1] || !$P);
    [ @$_ ]               # pass tuple through
}
map { [ # make tuple with transformed and original coordinates
        # the center ($M/$n, $N/$n) is the new origin
        $$_[0] - $M/$n,  # transformed x value
        $$_[1] - $N/$n,  # transformed y value 
        @$_              # original coordinates
] }  
map {
    $n++;                # $n is number of points
    $M += $$_[0];        # $M is sum of x values 
    $N += $$_[1];        # $N is sum of y values
    $_                   # pass orignal coordinates through
}
map {                    # make tuple with point coordinates
    [ /\S+/g ]           # from non-whitespace in input line
} 
<>                       # read input lines

+1 để bao gồm một biến thể mạch (Tôi nghi ngờ yêu cầu cuối cùng sẽ tìm thấy câu hỏi một lần nữa, sau khi Rizer trả lời)
Martin Ender

3

GolfScript, 6/13 ký tự (đường dẫn mở; 49 ký tự cho đường dẫn đóng)

Lưu ý: Giải pháp này dành cho phiên bản hiện tại của thử thách do Rizer chỉnh sửa. Nó không phải là một giải pháp hợp lệ cho thử thách ban đầu , đòi hỏi dòng từ điểm cuối trở lại điểm đầu tiên cũng không được giao với các dòng khác. Giải pháp 49 char dưới đây cũng hợp lệ cho thử thách ban đầu.

~]2/$`

Mã ở trên giả định rằng đầu ra có thể ở bất kỳ định dạng hợp lý. Nếu định dạng đầu ra phải khớp với đầu vào, phiên bản 13 ký tự sau sẽ thực hiện:

~]2/${" "*n}/

Giải trình:

  • ~đánh giá đầu vào, biến nó thành một danh sách các số; ]tập hợp các số này thành một mảng và 2/chia mảng này thành các khối hai số, mỗi khối đại diện cho một điểm.

  • $sắp xếp các điểm theo thứ tự từ điển, nghĩa là trước tiên theo tọa độ x và sau đó, nếu có quan hệ, theo tọa độ y. Thật dễ dàng để chỉ ra rằng điều này sẽ đảm bảo rằng các đường được vẽ giữa các điểm không giao nhau, miễn là đường dẫn không cần lặp lại từ đầu.

  • Trong phiên bản 5 ký tự, `xâu chuỗi các mảng đã sắp xếp, tạo ra biểu diễn chuỗi gốc của nó (ví dụ [[0 0] [0 4] [4 0] [4 4]]). Trong phiên bản dài hơn, {" "*n}/nối các tọa độ của từng điểm bằng một khoảng trắng và nối thêm một dòng mới.

Bản demo trực tuyến: phiên bản ngắn / phiên bản dài .


Thi thiên Đây là một giải pháp 49 char cho vấn đề ban đầu, trong đó đường dẫn bắt buộc phải đóng:

~]2/$.0=~:y;:x;{~y-\x-.+.@9.?*@(/\.!@@]}${" "*n}/

Nó hoạt động theo cách tương tự như giải pháp Perl của Heiko Oberdiek , ngoại trừ việc, thay vì sử dụng các hàm trig, mã này sắp xếp các điểm theo độ dốc ( y - y 0 ) / ( x - x 0 ), trong đó ( x 0 , y 0 ) là điểm có x-phối hợp thấp nhất (và y-phối hợp thấp nhất , nếu một số điểm được gắn cho x thấp nhất ).

Vì GolfScript không hỗ trợ điểm nổi, các độ dốc được nhân với hằng số cố định 9 9 = 387420361. (Nếu không đủ độ chính xác, bạn có thể thay thế 9bằng 99để biến hệ số nhân thành 99 99 ≈ 3,7 × 10 197. ) một số mã bổ sung để phá vỡ các mối quan hệ (theo tọa độ x ) và để đảm bảo rằng, như trong giải pháp của Heiko, các điểm có x = x 0 được sắp xếp sau cùng, theo thứ tự giảm dần theo tọa độ y .

Một lần nữa, đây là một bản demo trực tuyến .


1

Toán học, 35

Điều này làm việc cho BẤT K list danh sách các điểm duy nhất.

s=StringSplit;Grid@Sort@s@s[%,"\n"]

Bạn nói "đọc từ stdin", vì vậy đối với Mathicala, tôi giả sử "đọc từ đầu ra cuối cùng".

Đầu vào (đầu ra cuối cùng):

"0 0
4 4
0 4
4 0"

Đầu ra:

0 0
0 4
4 0
4 4

Nếu đầu vào và đầu ra không cần ở định dạng "dòng mới", điều này có thể thu nhỏ lại thành 6 ký tự:

Sort@%

lấy đầu ra cuối cùng làm đầu vào, giả sử đầu ra cuối cùng là mảng 2 chiều.

Đầu vào (đầu ra cuối cùng):

{{0,0},{4,4},{0,4},{4,0}}

Ouput:

{{0,0},{0,4},{4,0},{4,4}}

Sẽ không Sortlàm điều tương tự?
swish

@swish Tôi đang sử dụng SortByđể tôi có thể dễ dàng sắp xếp theo các giá trị "x" và giá trị "y".
kukac67

Nhưng sắp xếp làm điều tương tự, sắp xếp theo x và y.
swish

Bạn có thể lưu bảy ký tự bằng cách đổi tên StringSplitmột lần nữa và sử dụng cú pháp infix Sort@(s=StringSplit)@%~s~"\n".
Martin Ender

@swish Cảm ơn vì đã nói với tôi về 'Sắp xếp'. Điều đó đã rút ngắn mã rất nhiều ...
kukac67

1

PHP (175 109 100 ký tự)

while(fscanf(STDIN,'%d%d',$a,$b))$r[]=sprintf('%1$04d %2$04d',$a,$b);sort($r);echo implode('
',$r);

OK, tôi thừa nhận, PHP không phải là ngôn ngữ chơi golf tốt nhất, nhưng tôi đã thử.

Đây là một số đầu ra mẫu:

0000 0000
0000 0004
0004 0000
0004 0004

Những gì nó làm là đặt thông tin vào một chuỗi được định dạng bằng các số 0 trước đó.
Sau đó, nó chỉ sắp xếp các điểm văn bản.
PS Nó thất bại ở những con số trên 9999.


0

Python 2.7, 42B

import sys
print''.join(sorted(sys.stdin))

Không thể thực sự đơn giản hơn; đọc STDIN, sắp xếp các dòng, in dòng. NB Tôi đã tôn trọng các yêu cầu I / O chính xác của câu hỏi, nhưng nếu bạn tự điền STDIN, bạn cần nhấn CTRL+dđể kết thúc nhập.

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.