Найкоротші шляхи в графіку дільника


15

Вступ

У цьому виклику ми матимемо справу з певним нескінченним непрямим графіком, який я називаю графіком високого ділення . Її вузли є цілими числами , починаючи з 2. Існує ребро між двома вузлами A <B , якщо ділить б і в 2 ≥ б . Підграф, утворений діапазоном від 2 до 18, виглядає так:

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

Можна показати, що графік нескінченного високого дільника пов'язаний, тому ми можемо запитати про найкоротший шлях між двома вузлами.

Вхід і вихід

Ваші входи - це два цілі числа a і b . Можна припустити, що 2 ≤ a ≤ b <1000 . Ваш вихід - це довжина найкоротшого шляху між a і b в нескінченному графіку високого ділення. Це означає кількість ребер на шляху.

Наступний факт може бути корисним: завжди існує оптимальний шлях від a до b, який спочатку збільшується, а потім зменшується, і відвідує лише вузли, які суворо менші ніж 2b 2 . Зокрема, оскільки b <1000 потрібно розглядати лише вузли менше 2 000 000.

Приклади

Розглянемо вхідні дані 3та 32. Один можливий шлях між вузлами 3 та 32 - це

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

Цей шлях має чотири ребра, і, виявляється, немає коротших шляхів, тому правильний вихід є 4.

Як інший приклад, оптимальний шлях для 2і 25є

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

У мене є ідея, яка не є грубою силою, як я припускав, вона рахує найменший кратний на два числа, помножуючи поступово на потужність два, поки не з’явиться, потім поступово ділиться на sqrt, поки не з’явиться друге число, у мене немає часу реалізовувати iy зараз вже вісімнадцять: /
Abr001am

Згарб, чи FindShortestPath порушує Mathematica обмеження щодо стандартних лазів? Якщо це станеться, просто дайте мені знати, і я видалю своє подання.
DavidC

@DavidC Я не вважаю це лазівкою. Відповідний відповідь на насправді має оцінку 0.
Zgarb

Відповіді:


4

Матлаб, 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 байт довго за тобою.
Абр001ам

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 для обчислення всіх висхідних шляхів від mта nпо черзі до заданої межі, потім підсумовує контури разом і повертає найменше значення.


1

Математика 98 байт

Я припускаю, що вбудована функція FindShortestPathне порушує обмеження щодо стандартних лазів. Якщо це станеться, просто дайте мені знати, і я видалю це подання.

Груба сила, отже повільна з великими значеннями b. Я все ще думаю про способи її прискорити.

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

Це встановлює графік з відповідними краями між вузлами від aдо b^2. FindShortestPathзнаходить найкоротший шлях у графі. Lengthрахує вузли; Length -1- кількість ребер.

Thread[# <-> Range[2, #] #] &створює краї повного графа. Наприклад, Thread[# <-> Range[2, #] #]&[5]виробляються ребра {5 <-> 2*5, 5 <-> 3*5, 5 <-> 4*5, 5 <-> 5*5}, тобто {5 <-> 10, 5 <-> 15, 5 <-> 20, 5 <-> 25}.


1

Матлаб (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
  • Ця функція відрізняється від інших, вона супроводжується купою чистих математичних обчислень та факторизацій, але не має нічого спільного з шляхами чи графіками.
  • Приклад виклику функції:

     t(2,3,0)
    
     p =
    
     4
    

    Усі тестові справи задоволені

  • Пояснення:

Перш ніж почати з пояснень, давайте докажемо деякі леми "не зелені":

Лема (1): Оптимальний шлях між будь-якими двома числами (a,b)існує таким чином, що вузли спочатку збільшуються, а потім зменшуються.

Чому? Це просто доведено, тому що максимальна ціла кількість, яка ділить будь-яке число a, відповідно велика, як і саме число a, тому, як розумний підхід, ми повинні вибрати максимально помножити a, щоб зробити його достатньо великим, а потім ділити на більші значення. Якщо коли-небудь ми обійдемо навпаки, число aзменшується, тому нам не потрібно більше ітерацій, щоб помножувати його поступово, на що ми відмовляємося.

Лема (2): Від числа aдо b, якщо gcd(a,b)=1 aпомножити на b, якщо bбільший, ніж aвін буде помножений на відоме число c, якщо його gcd>1 aтреба поступово помножити на найбільший дільник b/gcdназваних, dякий перевіряє умову a >= dтакож, коли всі d, а саме мінімум більше , ніж a, aотримує a*cзнову.

Це припущення просте, щоб довести, що будь-який початковий вузол aповинен бути помножений до тих пір, поки він не досягне найменшого кратного числа, aі bтому ми помножимо на пропорції b*gcdпочатку на максимум, який підтверджує головну умову, що гарантує завжди найкоротший шлях до smp до початку процесу поділу, або коли dнемає, число cпомножується на, aщоб скласти дійсну умову a>=dдля цього першого етапу.

Лемма (3): від графа-кінцевого кратного aдо b, gcd цього числа і bє bсамим собою

Ну це лише наслідок попередніх маніпуляцій, а останні залишилися кроки також робляться поступово діленням на найбільший дільник, який не перевищує його квадратний корінь.

Дилема: Яке оптимальне число, cяке слід ітераційно помножити на aтаке, привело б прямо до умови відкриття для стадії 1, а потім до кінцевої?

Добре запитання, для будь-якої простої ситуації існує простий парир, тому припустимо, що приклад двох цілей розподілений (a,b)=(4,26)так:

  2 | 2
  2 | 13

Крім gcd=2найменше ціле яким повинна бути помножена 2на охоплення 13це 7, але це, очевидно , виключається, Тому що це більше , ніж 2, тому в квадраті.

  2 | 2 
  5 | 13

Appearenlty в другому прикладі (a,b)=(10,26)вище , cвимірюють як найнижче ціле число від 1до 5якого перевищує 13/5отже , він задовольняє умові граф-масштабування, який є 3, тому наступний крок тут множачи на3

  2 | 2 
  5 | 13
  3 |

Чому? це тому, що, як тільки ми повинні помножити 2*13/gcd=13на відповідність другій стороні таблиці, сума непотрібної, яку ми додали раніше, є оптимально мінімальною, і переміщення по графіку зводиться до мінімуму, якщо коли-небудь ми помножимо на більшу величину, як 10шанс поділу на найменше разів скорочується, і його було б збільшено ще на 1-й роздільний крок для досягнення нашої мети 2*13. які перераховуються до: 13*2*5*10/2*5тоді 13*2*5/5. Хоча, очевидно, тут число, на яке слід ділитись, є5*3<13*2

і ще одна річ ........ МАЙКИ З ГОЛОВИ ...


Це мої порівняльні результати з @flawr, просто зверніть увагу, що я зробив верхню межу для виконання часу, зберігаючи алгоритм недоліків, це займає занадто багато часу!

Ви можете вставити початковий і кінцевий діапазони сканування у вигляді змінних a і b у заголовку онлайн-компільованого коду.


Ого, це дивно. Я не сподівався, що оптимальні шляхи можуть бути побудовані прямо. Чекаємо пояснення ...
Згарб

@Zgarb Я зробив тривіальне пояснення в основних коментарях до публікації, я буду докладно пояснювати, коли закінчу гольф, btw, яка унікальна приємна проблема!
11001

@Zgarb доказ свіжий з духовки !!!!
грудня 16-16
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.