変装の順列


17

実数のエントリを持つ次元のベクトルが与えられた、距離に関して最も近い順列を見つけます。nvp12nl1

詳細

  • より便利な場合は、代わりに順列を使用できます。最も近い順列が複数ある場合は、いずれか1つまたはすべてを出力できます。01n1
  • 2つのベクトル間の距離は、として定義されl1あなたはv
    dあなたはv=|あなたはv|
  • 必要に応じて、入力が整数のみで構成されていると想定できます。

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

より多くの例を生成するためのオクターブスクリプト


のすべての要素vがより大きいことを保証されてい0ますか?または、少なくとも、そうではありません0か?
シャギー

1
いいえ、のエントリはv任意の整数にすることができます。(いくつかの例を追加しました。)
flawr

それらが実数になる可能性がある場合、それ[1.6 2]は重要なテストケースです(貪欲なアルゴリズム/辞書式ソートは間違った答えを与えます)。
ヒストクラート

2
変装して重複していますか?しかし、それが同じタスクであることは明らかではないので、そのように閉じる必要があるかどうかはわかりません(現在xnorによって証明されています)。
アーナルド

1
(実際、同じタスクではありませんが、リンクされた課題のすべてのソリューションはこの課題のソリューションです。)
Arnauld

回答:


13

Python 2、60バイト

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

オンラインでお試しください!

ゼロインデックスを使用します。

シンプルなアイデアの高速アルゴリズム。代わりに、可能な限りに近づけるために入力リストを並べ替える必要がある場合は、以下に示すように並べ替えるだけです。代わりにを並べ替えているので、私の挑戦のように、入力リストと同じ方法で並べ替えられた並べ替えを選択します(順序を模倣する(入力に繰り返しがある場合を除く)。(編集:マイルは、この同じ課題を指摘しましたが、デニスは同じ答えを持っています。)(1,2,...,n12n

クレーム:への距離を最小化するリスト順列はソートされます。 l12nl

証明:他のいくつかの並べ替えを検討の。ソートされたよりも良くないことを証明します。 lll

が異常な2つのインデックスを選択しますが、 です。それらを交換しても距離を増やすことができないことを示します。スワップは、これら2つの要素の寄与を次のように変更することに注意してください。 jl<jl>lj12n

|l|+|ljj||lj|+|lj|

これが増加することはないことを示すきちんとした方法があります。数直線上を歩く2人の人を考えてみましょう。1人はlからに、もう1人はljからjます。彼らが歩く合計距離は、左の式です。以来<jけどl>lj、彼らは、彼らの散歩中にいくつかの点で交差それを呼び出す必要があります手段数直線、上の高い方に切り替えるp。しかし、それらがpに達したときp、彼らは目的地を交換し、同じ合計距離を歩くことができます。そして、右端の合計距離を示すpをウェイポイントとして使用するのではなく、交換された目的地まで最初から歩いた方が悪いことはありません。

それで、二つアウトオブオーダ要素をソーティングlまでの距離を行う12nより小さい又は同じ。このプロセスを繰り返すと、最終的にlがソートされます。だから、lソートされた少なくともとして良いようであるlのいずれかの選択のためl最適または最適のために結ばれて、それを意味し、。

なお、の唯一のプロパティ12n私たちは同じアルゴリズムが任意の固定リストにその距離を最小限に抑えるために、任意のリストを置換するために働くだろうので、それは、ソートされたということです使用していること。

コードでの唯一の目的はz=zip(l,range(len(l)))、入力要素を区別することです。つまり、不一致の要素間で同じ比較を維持しながら、結びつきを回避することです。入力に繰り返しがないことが保証されている場合、これを削除して単にを使用することができますlambda l:map(sorted(l).index,l)


素晴らしい洞察力
ジョナ

これで順序付けが簡単になりました。
マイル

かなり面白いです@milesは、私は完全に私は答えを書いていてもその挑戦を忘れ、そしてデニスがあり、この正確なPythonの答え私はゴルフを助けました。
xnor

その「視覚的証拠」はきちんとしている。私は同じ考えを得ましたが、それを証明するためにその式の各ケースをレイアウトしなければなりませんでした。副次的な発言として、サードパーティのライブラリを使用してPythonでランクを取得するいくつかの代替方法がこの投稿に示されています。
ジョエル

5

05AB1E、7バイト

āœΣαO}н

オンラインでお試しください!


説明

ā              # 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
これに驚くたびに、05AB1E ができないことは何ですか?
ランダムな男

5
@Therandomguy 05AB1Eでできることはそれほど多くありませんが、それはかなり下手です:正規表現ベースの課題。マトリックスベースの課題(ただし、これはいくつかの新しいビルトイン後に改善されました); 虚数の欠如; 日時に関連する課題。など。しかし、難しいが、それはまだ通常行うことができます。2つの例を挙げます。就業日カウントダウン(次の日に移動し、曜日を取得するのは手動で行われます)。Quineはそれ自体をバイナリで出力します(UTF-8変換は手動で行われます)。
ケビンクルーッセン

@Grimyは今修正する必要があります:)
有効期限

3

Perl 6、44バイト

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

オンラインでお試しください!

インデックスが0の最初の最小順列を返す匿名コードブロック。

説明:

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

私はまた.sum、絶対値のリストだけを取り除き、ソートすることもできると思いますが、現在のテストケースに合格していますが、これが実際に正しいかどうかはわかりません。


1
それは私の脳を壊していました(または「貪欲なアルゴリズムはこれで動作しますか?」というほぼ同等の質問です)。最も単純な反例は[0.6 1](インデックスが0であると仮定します)、最初の値を最適化[1,0]するとスコア1.4になりますが、ベクトル全体を最適化すると1はスコアの2番目の位置でより価値があります0.6の。
ヒストクラート


2

ゼリー、5 バイト

Œ¿œ?J

整数のリストを生成する数値のリストを受け入れる単項リンク。

オンラインでお試しください!または、テストスイートを参照してください。

どうやって?

Œ¿œ?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(の長さが)の代わりに働くだろうJので、œ?整数を与えられ、n右側には暗黙のうちに範囲になるだろう[1..n]と仕事に、しかし、J明示的です。


2

ルビー63 60バイト

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

オンラインでお試しください!

ここには、他の答えにも役立つ数学のトリックがあります。差の絶対値の合計を最小化する代わりに、積の合計を最大化します。なぜそれが機能するのですか?

合計を最小化(x-y) squaredすることはの合計を最小化する|x-y|こととは異なりますが、常に有効な答えが得られます。実際の課題は2つの間で無関心ですが、小さな差よりも大きな差を減らすことを優先します。

しかし(x-y)*(x-y)= x*x+y*y-2*x*y。二乗項は順列の合計のどこかに常に現れるため、結果に影響を与えないため、に簡略化でき-2*x*yます。2要因出て、私たちはに簡素化することができます-x*y。その後、最小化を最大化に変更すると、に簡略化できx*yます。

直観的には、これは、水平の壁のセットと垂直の壁のセットを使用して平方フッテージを最大化しようとしている場合、サイズが互いに近い壁をペアリングして、可能な限り正方形に近い。3*3 + 4*4 = 25、一方3*4 + 4*3 = 24

編集:zipおよびsumを使用する代わりに、フォーマット文字列を生成および評価して、3バイトを保存しました。


2
y|バツy|バツy2


1

JavaScript(ES6)、61バイト

xnorの洞察に基づく。

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

オンラインでお試しください!

コメント済み

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バイト

間違いなくもっと直接的な方法がある はず  です...

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

オンラインでお試しください!(1インデックス付き出力付き)

どうやって?

g0n1na[]

p

k=n1+=0n1pa2
n1g

k



1

パイソン2149の 126 112バイト

Xcoder氏のおかげで-23バイト

xnorのおかげで-14バイト

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

オンラインでお試しください!

(0 ... n-1)の順列を使用します。


Python 2に切り替えると、functoolsもう必要なくなります。
Xcoder氏

reduce特にここでは、ものを追加しているところが過剰です。私はあなたができると思うsum(abs(p-q)for p,q in zip(x,a))
xnor

0

順列パッケージなし

Python 3、238バイト

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]

オンラインでお試しください!



0

Japt -g、12 バイト

Êõ á ñÈíaU x

それを試してみてください

インデックスが0の場合、最初の2バイトをで置き換えて、m,代わりに配列をそのインデックスにマッピングします。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.