除数グラフの最短経路


15

前書き

この課題では、特定の無限の無向グラフを扱います。これを高除数グラフと呼びます。そのノードは、2つのノード間のエッジがある2から始まる整数である<Bであれば分割のB及び2 ≥bは。2〜18の範囲で形成されるサブグラフは次のようになります。

16-8 12 18
  \|/ |/|
   4  6 9 10 15 14
   |  |/   |/   |
   2  3    5    7  11 13 17

無限大除数グラフが接続されていることを示すことができるため、2つのノード間の最短経路について尋ねることができます。

入出力

入力は2つの整数abです。2≤a≤b <1000と仮定できます。あなたの出力との間の最短経路の長さであり、そしてB無限高い除数のグラフです。これは、パス内のエッジの数を意味します。

あなたは次のことが役立つことがあります。常にから最適なパスが存在するB最初に増加し、その後減少し、かつ厳密に未満のみの訪問ノードだ2bの2。特に、b <1000なので、2 000 000未満のノードのみを考慮する必要があります。

入力3とを考慮してください32。ノード3と32の間の1つの可能なパスは

3 -- 6 -- 12 -- 96 -- 32

このパスには4つのエッジがあり、短いパスはないため、正しい出力は4です。

別の例として、のための最適な経路225なります

2 -- 4 -- 8 -- 40 -- 200 -- 25

したがって、正しい出力は5です。この場合、ノードを含む最適パスはありません50 = lcm(2, 25)

ルールとスコアリング

完全なプログラムまたは関数を作成できます。最小のバイトカウントが優先され、標準の抜け穴は許可されません。時間やメモリの制限はないため、ブルートフォーシングは許可されます。

テストケース

2 2 -> 0
2 3 -> 4
2 4 -> 1
2 5 -> 5
3 5 -> 4
6 8 -> 2
8 16 -> 1
12 16 -> 2
16 16 -> 0
2 25 -> 5
3 32 -> 4
2 256 -> 3
60 77 -> 3
56 155 -> 3
339 540 -> 2
6 966 -> 4
7 966 -> 2
11 966 -> 4
2 997 -> 7
991 997 -> 4

私は想定したブルートフォースではないアイデアを持っています.2つの数字の最小の倍数をカウントし、表示されるまで徐々に累乗2を掛け、次に2番目の数字が表示されるまで徐々にsqrtで除算します今でもiyを実装するには:/
Abr001am

Zgarb、Mathematica FindShortestPath は標準的な抜け穴に関する制約に違反していますか?もしそうなら、私に知らせてください、そして、私は提出物を削除します。
DavidC

@DavidC抜け穴とは思わない。関連する答えは、実際には0のスコアがある
Zgarb

回答:


4

Matlabの、218の 190 175バイト

function f(a,b);q=a;l(b)=0;l(a)=1;while~l(b);x=q(1);q=q(2:end);l(end+1:x^2)=0;g=x+1:x^2;s=2:x-1;u=[g(~mod(g,x)),s(~mod(x,s)&s.^2>=x)];u=u(~l(u));q=[q,u];l(u)=l(x)+1;end;l(b)-1

@beaker、リストの延長手順のショートカットをありがとう!

これは、比較的単純なdijkstraの実装です。

q=a;                  %queue
l(b)=0;       %list of path lengths
l(a)=1;
while~l(b);         %if there is no predecessor to b
    x=q(1);         %get first queue element
    q=q(2:end);
    %add edges 
    l(end+1:x^2)=0;% lengthen predecessor list if too short
    g=x+1:x^2;      % g=greater neighbours
    s=2:x-1;        % s=smaller neighbours %keep only valid/unvisited neighbours 
    u=[g(~mod(g,x)),s(~mod(x,s)&s.^2>=x)]; %-1byte
    u=u(~l(u));
    q=[q,u];      %add only hte valid nodes edges to queue
    l(u)=l(x)+1;       %mark x as predecessor  
end;
l(b)-1 %output length to the end of the path

今日は畳み込みなし


2
代わりに、同じl=zeros(1,a*b);ことを行うを使用できますl(a*b)=0;
ルイスメンドー

悲しいかな....まだあなたの後ろに10バイトの長さ。
Abr001am

1

JavaScript(ES6)、186バイト

(m,n)=>(g=i=>{for(q=[i],r=[],r[i]=j=0;i=q[j++];)for(k=i+i;k<=i*i&(k<m*m*2|k<n*n*2);k+=i)r[k]-r[i]<2?0:r[q.push(k),k]=r[i]+1},g(m),s=r,g(n),Math.min(...r.map((i,j)=>i+s[j]).filter(i=>i)))

ヘルパー関数を使用してgからのすべての上昇経路計算するmn提供限界ターンアップにし、その後、一緒にパスを合計し、最小値を返します。


1

Mathematica 98バイト

私は、組み込み関数FindShortestPathが標準的な抜け穴に関する制約に違反しないと仮定しています。存在する場合はお知らせください。この投稿を削除します。

総当たり。したがって、の値が大きいと遅くなりますb。私はまだそれをスピードアップする方法を考えています。

h@{a_,b_}:=Length@FindShortestPath[Graph[Apply[Join,Thread[#<->Range[2,#] #]&/@Range[b^2]]],a,b]-1

これにより、ノード間の適切なエッジを持つグラフが設定さab^2ます。FindShortestPathグラフ内の最短経路を見つけます。Lengthノードをカウントします。Length -1はエッジの数です。

Thread[# <-> Range[2, #] #] &完全なグラフのエッジを生成します。たとえば Thread[# <-> Range[2, #] #]&[5]、edges {5 <-> 2*5, 5 <-> 3*5, 5 <-> 4*5, 5 <-> 5*5}、つまりを生成します{5 <-> 10, 5 <-> 15, 5 <-> 20, 5 <-> 25}


1

Matlab (195)(185)(181)(179)(173)

注:私はユーザーAgawa001を個人的に使用して、ユーザー@flawr が彼の支援を利用して勝ったことを証明しています

 function t(a,b,p),for r=0:1,d=(b*~r+r*a)/gcd(a,b);while(d>1)p=p+1;e=find(~rem(d,1:d));f=max(e(a^(1-r/2)>=e));a=a*min([find(1:a*a>=b) a])^~(f-1);d=d/f;a=a*f^(1-2*r);end,end,p

説明を始める前に、いくつかの補題を「緑のものではない」ことを証明しましょう。

補題(1):任意の2つの数値間の最適なパスは(a,b)、ノードが最初に増加してから減少する方法で存在します。

どうして ?これは、任意の数値を分割する最大整数量aがそれぞれ数値a自体と同じであるため、単純に証明されています。そのため、賢明なアプローチとして、a可能な限り乗算して十分に大きくしてから、より大きい値で除算することを選択する必要があります。ラウンドを実行する場合、数aが縮小するため、不要な反復を徐々に増やして不要になります。

Lemma(2):数値aからbgcd(a,b)=1 aが乗算されるb場合、が既知の数値bより大きくなる場合a、がすべての場合、条件を検証する名前付きの最大除数で徐々に乗算される必要があるc場合最小値がより大きい場合、再度受信します。gcd>1 ab/gcdda >= ddaaa*c

この仮定は、任意の開始ノードを証明するのは簡単ですa、それは最小の倍数に到達するまで掛けなければなりませんaし、bそのいずれかを我々の乗算の割合でb*gcd分割処理が始まる前に保証が常に最短パスがSMPすることを、主な条件を確認し、最大で始まり、または、d使用可能でない場合、この最初の段階で有効な条件を作成するために数値cが乗算さaa>=dます。

補題(3):のグラフウルティマム複数からab、この数の最大公約数とbなるb自体

さて、これは前の操作の結果であり、最後の残りのステップも、平方根を超えない最大の除数で除算して徐々に行われます。

ジレンマ:ステージ1のオープニング条件に直行し、最後に到達cするまでに繰り返し乗算される最適な数は何aですか?

良い質問です。どんな単純な状況でも単純な受け流しがあるので、次のように(a,b)=(4,26)因数分解された2つの端の例を想定します。

  2 | 2
  2 | 13

別にからgcd=2で乗算する必要がありますウィッヒ最小の整数2リーチは13ある7が、それは2よりも大きいcuzを、それは明らかに、除外されているので、乗されています。

  2 | 2 
  5 | 13

第2の例でAppearenltyは、(a,b)=(10,26)上記cの最小の整数として測定さ15超える13/5それゆえに満足であるグラフスケーリングの状態3次のステップは、ここで乗算されるように、3

  2 | 2 
  5 | 13
  3 |

どうして ?これは2*13/gcd=13、テーブルの2番目の側に一致するように乗算する必要がある場合、前に追加したジャンク量が最適に最小になり10、除算の機会のような大きな値を乗算すると、グラフに沿った移動が最小になるためです最小時間は減少し、目標を達成するためにさらに1分割ステップずつ増加していました2*13。これに列挙されている:13*2*5*10/2*5そして13*2*5/5。一方、明らかにここで除算される数は5*3<13*2

そしてもう一つ........ HAIL MATHS ...


これらは@flawrのものとの比較結果であり、 flawrのアルゴリズムを考慮して時間実行の上限を設定したことに注意してください、時間がかかりすぎます!

オンラインコンパイル可能コードのヘッダーに変数aおよびbとして開始および終了スキャン範囲を挿入できます。


うわー、これは驚くべきことです。最適なパスが簡単な方法で構築できるとは思っていませんでした。説明を楽しみにして
...-Zgarb

@Zgarb私はメインの投稿のコメント内でささいな説明をしました。
Abr001am

@Zgarb証拠はオーブンから新鮮です!!!!
Abr001am
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.