Hoán vị ngụy trang


17

Cho một vector chiều với mục thực, hãy tìm một hoán vị gần của đối với với -distance.nvp(1,2,...,n)tôi1

Chi tiết

  • Nếu thuận tiện hơn, bạn có thể sử dụng hoán vị của thay thế. Nếu có nhiều hoán vị gần nhất, bạn có thể xuất bất kỳ một hoặc thay thế tất cả chúng.(0,1,...,n-1)
  • Các khoảng cách giữa hai vectơ được định nghĩa làtôi1bạn,v
    d(bạn,v)= =ΣTôi|bạnTôi-vTôi|.
  • Nếu bạn muốn, bạn có thể giả sử rằng đầu vào chỉ bao gồm các số nguyên.

Ví dụ

[0.5  1] -> [1 2], [2 1]
c*[1 1 ... 1] -> any permutation
[1 4 2 6 2] -> [1 4 3 5 2], [1 4 2 5 3]
[1 3 5 4 1] -> [2 3 5 4 1], [1 3 5 4 2]
[7 7 3 2 5 6 4 2] -> [8 7 3 2 5 6 4 1], [8 7 3 1 5 6 4 2], [7 8 3 2 5 6 4 1], [7 8 3 1 5 6 4 2]
[-2 4 5 7 -1 9 3] -> [1 4 5 6 2 7 3], [2 4 5 6 1 7 3], [1 4 5 7 2 6 3], [2 4 5 7 1 6 3]
[0 4 2 10 -1 10 5] -> [1 4 2 6 3 7 5], [1 4 3 6 2 7 5], [2 4 3 6 1 7 5], [3 4 2 6 1 7 5], [1 4 2 7 3 6 5], [1 4 3 7 2 6 5], [2 4 3 7 1 6 5], [3 4 2 7 1 6 5]

Kịch bản Octave để tạo thêm ví dụ.


Chúng tôi có đảm bảo rằng tất cả các yếu tố của v, sẽ lớn hơn 0? Hoặc, ít nhất, không 0?
Xù xì

1
Không, các mục của vcó thể là bất kỳ số nguyên. (Đã thêm một số ví dụ khác.)
flawr

Nếu chúng có thể là bất kỳ số thực nào thì đó [1.6 2]là một trường hợp thử nghiệm quan trọng (thuật toán tham lam / sắp xếp từ vựng cho câu trả lời sai).
lịch sử

2
Nhân bản trong ngụy trang? Tuy nhiên, tôi không chắc chắn nó nên bị đóng như vậy, vì không rõ ràng đó là nhiệm vụ tương tự (như đã được chứng minh bởi xnor).
Arnauld

1
(Trên thực tế, đó không phải là cùng một nhiệm vụ, nhưng tất cả các giải pháp của thách thức được liên kết là giải pháp của vấn đề này.)
Arnauld

Câu trả lời:


13

Python 2 , 60 byte

def f(l):z=zip(l,range(len(l)));print map(sorted(z).index,z)

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

Sử dụng chỉ mục không.

Một thuật toán nhanh với một ý tưởng đơn giản. Nếu chúng ta thay vì cần phải hoán vị trong danh sách đầu vào để làm cho nó càng gần (1,2,...,n) càng tốt, chúng ta nên chỉ sắp xếp nó, như đã được chứng minh dưới đây. Kể từ khi chúng ta thay vì hoán vị (1,2,...,n) , chúng tôi chọn hoán vị đó của lệnh theo cùng một cách như danh sách đầu vào, như trong thách thức của tôi bắt chước một trật tự (trừ đầu vào có thể phải lặp đi lặp lại). (Edit: dặm chỉ ra thách thức giống hệt nhau hơn này , nơi Dennis có câu trả lời này cùng .)

Khẳng định: Một hoán vị của danh sách tôi giảm thiểu khoảng cách của nó tới (1,2,...,n)tôi sắp xếp.

Chứng minh: Xét một số hoán vị khác tôi' của tôi . Chúng tôi sẽ chứng minh rằng nó không thể tốt hơn tôi sắp xếp.

Chọn hai chỉ số Tôi,jtôi' có thứ tự, đó là nơi Tôi<j nhưng tôiTôi'>tôij' . Chúng tôi thấy rằng trao đổi họ không thể tăng khoảng cách đến (1,2,...,n) . Chúng tôi lưu ý rằng hoán đổi thay đổi sự đóng góp của hai yếu tố này như sau:

|tôiTôi'-Tôi|+|tôij'-j||tôiTôi'-j|+|tôij'-Tôi|.

Đây là một cách gọn gàng để cho thấy điều này không thể tăng. Hãy xem xét hai người đi trên một dãy số, một người đi từ tôiTôi' đến Tôi và người kia từ tôij' đến j . Tổng khoảng cách họ đi bộ là biểu thức bên trái. Vì Tôi<j nhưng tôiTôi'>tôij' , họ chuyển đổi người cao hơn trên dòng số, có nghĩa là họ phải vượt qua tại một số điểm trong khi đi bộ, gọi nó là p . Nhưng khi họ đạt đến p, sau đó họ có thể trao đổi điểm đến của mình và đi bộ cùng một khoảng cách. Và sau đó, không thể tệ hơn khi họ đi bộ đến các điểm đến đã hoán đổi của họ ngay từ đầu thay vì sử dụng p làm điểm tham chiếu, điều này mang lại tổng khoảng cách ở phía bên tay phải.

Vì vậy, phân loại hai out-of-trật tự các yếu tố trong tôi' làm cho khoảng cách của nó tới (1,2,...,n) nhỏ hơn hoặc giống nhau. Lặp đi lặp lại quá trình này sẽ sắp xếp tôi cuối cùng. Vì vậy, tôi sắp xếp ít nhất là tốt như tôi' cho bất kỳ lựa chọn nào của tôi' , có nghĩa là nó là tối ưu hoặc gắn cho tối ưu.

Lưu ý rằng tài sản duy nhất của (1,2,...,n) mà chúng tôi sử dụng là nó sắp xếp, vì vậy cùng một thuật toán sẽ làm việc để hoán vị bất kỳ danh sách trao cho giảm thiểu khoảng cách của mình cho bất kỳ danh sách cố định.

Trong mã, mục đích duy nhất z=zip(l,range(len(l)))là làm cho các yếu tố đầu vào trở nên khác biệt, đó là để tránh các mối quan hệ, trong khi vẫn giữ các so sánh giống nhau giữa các yếu tố không đồng đều. Nếu đầu vào chúng tôi đảm bảo không có sự lặp lại, chúng tôi có thể loại bỏ điều này và chỉ cần có lambda l:map(sorted(l).index,l).


cái nhìn sâu sắc
Jonah

Bạn đã đơn giản hóa việc này để tìm kiếm thứ tự .
dặm

@miles Điều đó khá buồn cười, tôi hoàn toàn quên mất thử thách đó mặc dù tôi đã viết một câu trả lời và Dennis có câu trả lời Python chính xác này mà tôi đã giúp chơi golf.
xnor

Đó là "bằng chứng trực quan" là gọn gàng. Tôi có cùng một ý tưởng nhưng phải đưa ra từng trường hợp của công thức đó để chứng minh nó. Như một nhận xét phụ, một vài lựa chọn thay thế để đạt được thứ hạng trong Python bằng thư viện của bên thứ ba được hiển thị trong bài viết này .
Joel

5

05AB1E , 7 byte

āœΣαO}н

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


Giải trình

ā              # get the numbers 1 to len(input) + 1
 œ             # Permutations of this
  Σ  }         # Sort by ...
   α           # Absolute difference
    O          # Sum these
      н        # And get the first one 
               # implicitly print

1
Mỗi khi tôi ngạc nhiên về điều này, 05AB1E không thể làm gì?
chàng ngẫu nhiên

5
@Therandomguy Không có nhiều thứ không thể thực hiện được trong 05AB1E, nhưng nó khá tệ ở: những thách thức dựa trên regex; các thách thức dựa trên ma trận (mặc dù điều này đã được cải thiện sau một số nội dung mới); thiếu số tưởng tượng; thử thách liên quan đến ngày / giờ; vv Tuy nhiên, mặc dù khó khăn, nó vẫn có thể được thực hiện thường xuyên. Để đưa ra hai ví dụ: Đếm ngược ngày làm việc (sang ngày hôm sau và nhận ngày trong tuần được thực hiện thủ công); Quine tự xuất ra ở dạng nhị phân (chuyển đổi UTF-8 được thực hiện thủ công).
Kevin Cruijssen

@Grimy nên được sửa ngay bây giờ :)
Dữ liệu hết hạn

3

Perl 6 , 44 byte

{permutations(+$_).min((*[]Z-$_)>>.abs.sum)}

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

Codeblock ẩn danh trả về hoán vị tối thiểu đầu tiên với 0 chỉ mục.

Giải trình:

{                                          }   # Anonymous code block
 permutations(+$_)                             # From the permutations with the same length
                  .min(                   )    # Find the minimum by
                                      .sum       # The sum of
                                >>.abs           # The absolute values of
                       (*[]Z-$_)                 # The zip subtraction with the input

Tôi nghĩ rằng tôi cũng có thể loại bỏ .sumvà sắp xếp chỉ bằng danh sách các giá trị tuyệt đối, nhưng tôi không chắc đây thực sự là lỗi, mặc dù nó vượt qua các trường hợp thử nghiệm hiện tại của tôi.


1
Điều đó cũng đã phá vỡ bộ não của tôi (hoặc câu hỏi gần như tương đương với "thuật toán tham lam có hoạt động cho việc này không?"). Ví dụ đơn giản nhất là [0.6 1](giả sử chúng tôi được lập chỉ mục 0), trong đó nếu bạn tối ưu hóa cho giá trị đầu tiên, bạn sẽ nhận được [1,0]điểm 1,4, nhưng nếu bạn tối ưu hóa cho toàn bộ vectơ thì 1 có giá trị hơn ở vị trí thứ hai cho điểm 0,6.
lịch sử


2

Thạch , 5 byte

Œ¿œ?J

Một liên kết đơn được chấp nhận một danh sách các số mang lại một danh sách các số nguyên.

Hãy thử trực tuyến! Hoặc xem bộ thử nghiệm .

Làm sao?

Œ¿œ?J - Link: list of numbers, X
Œ¿    - Index of X in a lexicographically sorted list of
         all permutations of X's items
    J - range of length of X
  œ?  - Permutation at the index given on the left of the
         items given on the right

NB L(độ dài) sẽ hoạt động thay Jvì kể từ œ?một số nguyên, nbên phải sẽ ngầm định phạm vi [1..n]để làm việc với, nhưng Jrõ ràng.


2

Ruby , 63 60 byte

->v{[*1..v.size].permutation.max_by{|p|eval [p,0]*'*%p+'%v}}

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

Có một mẹo toán học ở đây cũng có thể hữu ích trong các câu trả lời khác - thay vì giảm thiểu tổng giá trị tuyệt đối của các khác biệt, chúng tôi tối đa hóa tổng của các sản phẩm. Tại sao nó hoạt động?

Tối thiểu hóa tổng (x-y) squaredkhông tương đương với tối thiểu hóa tổng |x-y|, nhưng nó sẽ luôn đưa ra câu trả lời hợp lệ, nó chỉ ưu tiên giảm sự khác biệt lớn so với nhỏ trong khi thách thức thực tế là không phân biệt giữa hai bên.

Nhưng (x-y)*(x-y)= x*x+y*y-2*x*y. Vì các số hạng vuông sẽ luôn hiển thị ở đâu đó trong tổng số cho bất kỳ hoán vị nào, chúng không ảnh hưởng đến kết quả, vì vậy chúng tôi có thể đơn giản hóa -2*x*y. Các 2yếu tố ra, vì vậy chúng ta có thể đơn giản hóa -x*y. Sau đó, nếu chúng ta thay đổi tối thiểu hóa thành tối đa hóa, chúng ta có thể đơn giản hóa x*y.

Theo trực giác, điều này tương tự như việc quan sát rằng nếu bạn đang cố gắng tối đa hóa cảnh vuông bằng cách sử dụng một bộ tường ngang và một bộ dọc, tốt nhất bạn nên ghép các bức tường có kích thước gần nhau để tạo ra các phòng càng gần vuông càng tốt. 3*3 + 4*4 = 25, trong khi 3*4 + 4*3 = 24.

Chỉnh sửa: Đã lưu ba byte bằng cách tạo và đánh giá chuỗi định dạng thay vì sử dụng zip và sum.


2
Tối thiểu hóa tổng (xy) bình phương không tương đương với tối thiểu hóa tổng của | xy |, nhưng nó sẽ luôn đưa ra câu trả lời hợp lệ. Tại sao lại như vậy? Có nào giảm thiểu | x - y | nhưng không phải ( x - y ) 2 ? yΣ|x-y|Σ(x-y)2
Joel

1

Gaia , 13 byte

e:l┅f⟪D†Σ⟫∫ₔ(

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

e:		| eval and dup input
l┅f		| push permutations of [1..length(input)]
⟪   ⟫∫ₔ		| iterate over the permutations, sorting with minimum first
 D†Σ		| the sum of the absolute difference of the paired elements
       (	| and select the first (minimum)

1

JavaScript (ES6), 61 byte

Dựa trên cái nhìn sâu sắc của xnor .

a=>[...a].map(g=n=>g[n]=a.sort((a,b)=>a-b).indexOf(n,g[n])+1)

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

Đã bình luận

a =>                    // a[] = input array
  [...a]                // create a copy of a[] (unsorted)
  .map(g = n =>         // let g be in a object; for each value n in the copy of a[]:
    g[n] =              //   update g[n]:
      a.sort(           //     sort a[] ...
        (a, b) => a - b //       ... in ascending order
      ).indexOf(        //     and find the position
        n,              //       of n in this sorted array,
        g[n]            //       starting at g[n] (interpreted as 0 if undefined)
      ) + 1             //     add 1
  )                     // end of map()

JavaScript (ES6),  130  128 byte

 phải  chắc chắn là một cách trực tiếp hơn ...

Chỉ số 0.

a=>(m=g=(k,p=[])=>1/a[k]?(h=i=>i>k||g(k+1,b=[...p],b.splice(i,0,k),h(-~i)))``:p.map((v,i)=>k+=(v-=a[i])*v)|k>m||(R=p,m=k))(0)&&R

Hãy thử trực tuyến! (với đầu ra 1 chỉ mục)

Làm sao?

g(0,...,n-1)nmột[]

p

k= =n-1+ΣTôi= =0n-1(pTôi-mộtTôi)2
n-1g

k



1

Python 2 , 149 126 112 byte

-23 byte nhờ ông Xcoder

-14 byte nhờ xnor

from itertools import*
f=lambda a:min(permutations(range(len(a))),key=lambda x:sum(abs(a-b)for a,b in zip(x,a)))

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

Sử dụng hoán vị của (0 ... n-1).


Bạn có thể chuyển sang Python 2, do đó bạn không cần functoolsnữa.
Ông Xcoder

reducethường là quá mức cần thiết, đặc biệt là ở đây nơi bạn đang thêm công cụ. Tôi nghĩ bạn có thể làm sum(abs(p-q)for p,q in zip(x,a)).
xnor

0

w / o bất kỳ gói hoán vị

Python 3 , 238 byte

def p(a,r,l):
 if r==[]:l+=[a];return
 for i in range(len(r)):
  p(a+[r[i]],r[:i]+r[i+1:],l)
def m(l):
 s=(float("inf"),0);q=[];p([],list(range(len(l))),q)
 for t in q:D=sum(abs(e-f)for e,f in zip(l,t));s=(D,t)if D<s[0]else s
 return s[1]

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



0

Japt -g , 12 byte

Êõ á ñÈíaU x

Thử nó

Đối với chỉ mục 0, thay thế 2 byte đầu tiên bằng m,ánh xạ mảng tới các chỉ mục của nó.

Êõ á ñÈíaU x     :Implicit input of array U
Ê                :Length
 õ               :Range [0,Ê]
   á             :Permutations
     ñÈ          :Sort by
       í U       :  Interleave with U
        a        :  Reduce each pair by absolute difference
           x     :  Reduce resulting array by addition
                 :Implicit output of first sub-array

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.