Kılık Değiştirme Permütasyonları


17

Bir göz önüne alındığında n boyutlu vektör v gerçek girişleri ile, bir yakın permütasyon bulmak p arasında (1,2,...,n) ile ilgili olarak l1 -uzaklık.

ayrıntılar

  • Daha uygun ise, PERMÜTASYON kullanabilirsiniz (0,1,...,n1) yerine. En yakın çoklu permütasyon varsa, bunlardan herhangi birini veya alternatif olarak hepsini çıktı alabilirsiniz.
  • l1 , iki vektör arasındaki mesafe u,v olarak tanımlanır
    d(u,v)=i|uivi|.
  • İsterseniz, girdinin yalnızca tamsayılardan oluştuğunu varsayabilirsiniz.

Örnekler

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

Daha fazla örnek oluşturmak için oktav komut dosyası .


Tüm öğelerinin vdaha büyük olacağı garanti ediliyor 0mu? Ya da en azından değil 0mi?
Shaggy

1
Hayır, girişleri vherhangi bir tamsayı olabilir. (Birkaç örnek daha eklendi.)
flawr

Herhangi bir gerçek sayı olabilirlerse [1.6 2]önemli bir test durumudur (açgözlü algoritma / sözlükbilimsel sıralama yanlış cevap verir).
histokrat

2
Kılık değiştirmiş misin? Yine de bu şekilde kapatılması gerektiğinden emin değilim, çünkü aynı görev olduğu açık değil (şimdi xnor tarafından kanıtlandığı gibi).
Arnauld

1
(Aslında, aynı görev değildir, ancak bağlantılı mücadelenin tüm çözümleri bu çözümdür.)
Arnauld

Yanıtlar:


13

Python 2 , 60 bayt

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

Çevrimiçi deneyin!

Sıfır indeksleme kullanır.

Basit bir fikir ile hızlı bir algoritma. Bunun yerine girdi listesini sırasını değiştirmek amacıyla gerekirse için yakın olarak bunu yapmak için (1,2,...,n) aşağıda kanıtlanmış mümkün olduğunca, biz, sadece bir çeşit olması gerektiği. Bunun yerine NN ediyoruz yana (1,2,...,n) , biz benim meydan gibi, girdi listesiyle aynı şekilde emrettiğini permütasyon seçmek bir sipariş taklit (tekrarlarını olabilir girdi hariç). (Düzenleme: Miles , Dennis'in aynı cevaba sahip olduğu bu daha özdeş zorluğa dikkat çekti .)

İddia: liste permütasyonu l olan mesafe en aza indirir (1,2,...,n) bir l kriteri.

Kanıt: diğer bazı permütasyon düşünün l ait l . Biz daha iyi olamaz kanıtlamak edeceğiz l sıralanmış.

İki endeksleri al i,j bu l olduğu, dışı düzeni vardır burada i<j ama li>lj . Onları takas etmek mesafeyi artırmak olamayacağını göstermektedir (1,2,...,n) . Takasın bu iki unsurun katkısını şu şekilde değiştirdiğini not ediyoruz:

|lii|+|ljj||lij|+|lji|.

Here's a neat way to show this can't be an increase. Consider two people walking on a number line, one going from li to i and the other from lj to j. The total distance they walk is the expression on the left. Since i<j but li>lj, they switch who is higher on the number line, which means they must cross at some point during their walks, call it p. But when they reach pdaha sonra hedeflerini değiştirebilir ve aynı toplam mesafeyi yürüyebilirler. Ve sonra, takas edilen varış yerlerine p kullanmak yerine en başından beri yürümeleri daha kötü olamazp sağ taraftaki toplam mesafeyi veren bir yol noktası olarak .

Bu nedenle, iki-dışı amacıyla elemanları sıralama l olan mesafesini sağlar (1,2,...,n) küçük ya da aynı. Bu işlemi tekrarlamak sonunda l sıralayacaktır . Yani, l sıralanmış olan en az şekilde iyi olarak l herhangi bir seçim için l hangi vasıta bunu optimum olarak veya optimum için bağladılar.

Not bu tek özelliği (1,2,...,n) aynı algoritma herhangi bir sabit listeye mesafeyi en aza indirmek için belirli bir listesini permüte için çalışacak bu yüzden, kriteri olmasıdır kullanılan.

Kodda tek amaç, z=zip(l,range(len(l)))eşit olmayan elemanlar arasında aynı karşılaştırmaları korurken, giriş elemanlarını ayrı yapmak, yani bağlardan kaçınmaktır. Eğer girişin tekrarlanmasını garanti etmediysek, bunu kaldırabilir ve edinebiliriz lambda l:map(sorted(l).index,l).


parlak bir fikir
Jonah

Bunu siparişi bulmak için basitleştirdiniz .
mil

@miles Bu oldukça komik, bir cevap yazmamıza rağmen bu meydan okumayı tamamen unuttum ve Dennis'in golfe yardım ettiğim tam Python cevabı var.
xnor

Bu "görsel kanıt" temiz. Aynı fikri aldım ama bunu kanıtlamak için bu formülün her bir vakasını ortaya koymak zorundaydım. Bir yan not olarak, üçüncü taraf kütüphanelerini kullanarak Python elde sıralarında birkaç alternatifleri gösterilmektedir bu yazı .
Joel

5

05AB1E , 7 bayt

āœΣαO}н

Çevrimiçi deneyin!


açıklama

ā              # 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
Ben bu hayret ediyorum her şey, 05AB1E ne edemez mi?
Rastgele adam

5
@Therandomguy 05AB1E'de yapılamayan pek çok şey yok, ancak şu adreste oldukça kötü: regex tabanlı zorluklar; matris temelli zorluklar (bazı yeni yerleşimlerden sonra iyileştirilmiş olmasına rağmen); hayali sayıların eksikliği; tarih / saatle ilgili zorluklar; Ancak, zor olmasına rağmen, yine de genellikle yapılabilir. İki örnek vermek gerekirse: İş Günü Geri Sayımı (ertesi güne gidin ve haftanın gününü manuel olarak yapın); Quine kendisini ikili olarak çıkarır (UTF-8 dönüşümü manuel olarak yapılır).
Kevin Cruijssen

@Grimy şimdi düzeltilmelidir :)
Süresi Dolmuş Veri

3

Perl 6 , 44 bayt

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

Çevrimiçi deneyin!

0 dizinleme ile ilk minimum permütasyon döndüren anonim kod bloğu.

Açıklama:

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

Ben de .sumsadece mutlak değerler listesine göre kurtulmak ve sıralamak mümkün olabilir , ama mevcut test vakaları geçmesine rağmen, aslında corret olduğundan emin değilim.


1
Bu da beynimi kırıyordu (ya da "buna karşı açgözlü bir algoritma işe yarıyor mu?"). En basit karşı örnek [0.6 1](0 endeksli olduğumuzu varsayarsak), burada ilk değer [1,0]için optimize ederseniz 1,4 puan alırsınız , ancak tüm vektör için optimize ederseniz 1 puan için ikinci pozisyonda daha değerlidir 0.6.
histokrat


2

Jöle , 5 bayt

Œ¿œ?J

Tamsayıların bir listesini veren bir sayı listesini kabul eden bir monadik Bağlantı.

Çevrimiçi deneyin! Veya bakın test takımına bakın .

Nasıl?

Œ¿œ?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(uzunluğu) yerine çalışacak Jberi œ?, bir tamsayı verilen nsağdaki aralığını yapmak örtülü olurdu [1..n]ile işe ama Jaçık olduğunu.


2

Yakut , 63 60 bayt

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

Çevrimiçi deneyin!

Burada diğer cevaplarda da yardımcı olabilecek bir matematik hilesi var - farklılıkların mutlak değerlerinin toplamını en aza indirmek yerine , ürünlerin toplamını en üst düzeye çıkarıyoruz . Neden çalışıyor?

Toplamını en aza indirme (x-y) squared aza indirmek,|x-y| , ancak her zaman geçerli bir cevap verecektir, sadece küçük olanlara göre büyük farklılıkların azaltılmasına öncelik verirken, asıl zorluk ikisi arasında kayıtsızdır.

Ancak (x-y)*(x-y)= x*x+y*y-2*x*y. Kare terimler her zaman herhangi bir permütasyon için toplamda bir yerde görüneceğinden, sonucu etkilemezler, böylece basitleştirebiliriz -2*x*y. 2Faktörler göz, bu yüzden hiç kolaylaştırabilirsiniz -x*y. Eğer minimizasyonu maksimuma çıkarmaya değiştirirsek, basitleştirebiliriz x*y.

Sezgisel olarak, bu, bir dizi yatay duvar ve bir dizi dikey duvar kullanarak kare çekimleri en üst düzeye çıkarmaya çalışıyorsanız, mümkün olduğunca kareye yakın. 3*3 + 4*4 = 25, süre3*4 + 4*3 = 24 .

Düzenleme: Zip ve sum kullanmak yerine bir biçim dizesi oluşturup değerlendirerek üç bayt kaydetti.


2
(Xy) kare toplamının en aza indirilmesi | xy | toplamının en aza indirilmesine eşdeğer değildir, ancak her zaman geçerli bir yanıt verecektir. Neden böyle? Yok muy en aza indirir Σ|x-y| Ama değil Σ(x-y)2?
Joel

1

Gaia , 13 bayt

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

Çevrimiçi deneyin!

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 bayt

Dayanarak XNOR en içgörü .

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

Çevrimiçi deneyin!

Yorumlananlar

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 bayt

Orada  olmalı  kesinlikle daha doğrudan bir yol ...

0 endeksli.

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

Çevrimiçi deneyin! (1 dizinli çıktı ile)

Nasıl?

Yardımcı işlevi g tüm permütasyonlarını hesaplar (0,...,n-1), nerede n girdi dizisinin örtülü uzunluğu bir[].

Her permütasyon için p, hesaplıyoruz:

k=n-1+Σben=0n-1(pben-birben)2
Liderliğin tek nedeni n-1 iç sayacını tekrar kullanmamız g birkaç bayt tasarruf etmek, ancak nihai sonuç üzerinde hiçbir etkisi yoktur.

Sonunda en küçük boyuta götüren permütasyonu iade ediyoruz. k.



1

Piton 2 , 149 126 112 bayt

Bay Xcoder sayesinde -23 bayt

Xnor sayesinde -14 bayt

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

Çevrimiçi deneyin!

(0 ... n-1) permütasyonlarını kullanır.


Python 2'ye geçebilirsiniz, böylece functoolsartık ihtiyacınız kalmaz .
Bay Xcoder

reducegenellikle aşırıya kaçıyor, özellikle burada şeyler eklediğiniz yerde. Bence sadece yapabilirsin sum(abs(p-q)for p,q in zip(x,a)).
xnor

0

herhangi bir permütasyon paketi olmadan

Python 3 , 238 bayt

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]

Çevrimiçi deneyin!



0

Japt -g , 12 bayt

Êõ á ñÈíaU x

Dene

0 dizinli için, m,diziyi dizinleriyle eşleştirmek için ilk 2 baytı değiştirin .

Êõ á ñÈí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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.