Скільки кроків проходить від n до 1, віднімаючи найбільший дільник?


50

Натхненник цим питанням над математикою .


Проблема

Нехай nбуде натуральне число ≥ 2. Візьміть найбільший дільник, nякий відрізняється від nсебе, і відніміть його n. Повторюйте, поки не отримаєте 1.

Питання

Скільки кроків потрібно, щоб досягти 1певного числа n ≥ 2.

Детальний приклад

Нехай n = 30.

Найбільший дільник:

1.   30 is 15  -->  30 - 15 = 15
2.   15 is  5  -->  15 -  5 = 10
3.   10 is  5  -->  10 -  5 =  5
4.    5 is  1  -->   5 -  1 =  4
5.    4 is  2  -->   4 -  2 =  2
6.    2 is  1  -->   2 -  1 =  1

Щоб дістатися, потрібно 6 кроків1 .

Вхідні дані

  • Введення - ціле число n, де n ≥ 2.
  • Ваша програма повинна підтримувати введення до максимального цілого значення мови.

Вихід

  • Просто виведіть кількість кроків, наприклад 6.
  • Провідні / слідові пробіли або нові рядки - це добре.

Приклади

f(5)        --> 3
f(30)       --> 6
f(31)       --> 7
f(32)       --> 5
f(100)      --> 8
f(200)      --> 9
f(2016^155) --> 2015

Вимоги

  • Ви можете отримати дані з STDINаргументів командного рядка як параметрів функції або з найближчого еквівалента.
  • Можна написати програму або функцію. Якщо це анонімна функція, додайте приклад, як викликати її.
  • Це тому найкоротша відповідь у виграші байтів.
  • Стандартні лазівки заборонені.

Цю серію можна знайти і на OEIS: A064097

Квазі-логарифм, визначений індуктивно через a(1) = 0і, a(p) = 1 + a(p-1)якщо pє простим, і a(n*m) = a(n) + a(m)якщо m,n > 1.


уточнити вимогу введення в мовах з натуральними цілими числами довільної точності?
Спарр

@Sparr Я б сказав, ви повинні хоча б підтримати 2^32 - 1. Решта залежить від вас та вашої системи. Сподіваюся, саме це ви мали на увазі під своїм запитанням.
Вставтекористувач туди

3
Мені подобається, як це підсумовує заголовок
Луїс Мендо

Відповіді:


20

Желе , 9 байт

ÆṪÐĿÆFL€S

Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Фон

Визначення послідовності A064097 означає, що це

визначення

За формулою продукту Ейлера

Формула продукту Ейлера

де φ позначає тотієнтську функцію Ейлера, а p змінюється лише за простими числами.

Поєднуючи обидва, ми виводимо майно

перше майно

де ω позначає кількість виразних простих факторів n .

Застосовуючи отриману формулу k + 1 раз, де k досить великий, щоб φ k + 1 (n) = 1 , отримуємо

друге майно

З цієї властивості отримуємо формулу

формула

де виконується остання рівність, оскільки ω (1) = 0 .

Як це працює

ÆṪÐĿÆFL€S  Main link. Argument: n

  ÐĿ       Repeatedly apply the link to the left until the results are no longer
           unique, and return the list of unique results.
ÆṪ           Apply Euler's totient function.
           Since φ(1) = 1, This computes φ-towers until 1 is reached.
    ÆF     Break each resulting integer into [prime, exponent] pairs.
      L€   Compute the length of each list.
           This counts the number of distinct prime factors.
        S  Add the results.

Тепер це надзвичайно розумний підхід!
грудня

15

05AB1E , 13 11 байт

Код:

[DÒ¦P-¼D#]¾

Пояснення:

[        ]   # An infinite loop and...
       D#        break out of the loop when the value is equal to 1.
 D           # Duplicate top of the stack (or in the beginning: duplicate input).
  Ò          # Get the prime factors, in the form [2, 3, 5]
   ¦         # Remove the first prime factor (the smallest one), in order to get 
               the largest product.
    P        # Take the product, [3, 5] -> 15, [] -> 1.
     -       # Substract from the current value.
      ¼      # Add one to the counting variable.
          ¾  # Push the counting variable and implicitly print that value.

Використовує кодування CP-1252 . Спробуйте в Інтернеті! .


13
Видаліть перший основний фактор (найменший), щоб отримати найбільший продукт Як розумно! :-)
Луїс Мендо

Я бачу, ви розробник мови
Sarge Borsch,

@SargeBorsch Так, це правильно :)
Аднан

[¼Ñü-¤ÄD#]¾- Я був близький до того, щоб поголити байт попарно, ой добре ...
Чарівний восьминіг Урн

-1 байт: [Ð#Ò¦P-¼]¾. Ðкраще, ніж DD.
Гріммі

11

Pyth, 11 байт

fq1=-Q/QhPQ

Тестовий набір

Прямий цикл повторення до повної дійсності.

Пояснення:

fq1=-Q/QhPQ
               Implicit: Q = eval(input())
f              Apply the following function until it is truthy,
               incrementing T each time starting at 1:
         PQ    Take the prime factorization of Q
        h      Take its first element, the smallest factor of Q
      /Q       Divide Q by that, giving Q's largest factor
    -Q         Subtract the result from Q
   =           Assign Q to that value
 q1            Check if Q is now 1.

це дійсно приємний трюк з fілтером.
Малтісен

3
Я не розумію, чому це видає кількість разів, коли функція виконувалась. Це недокументована особливість f?
corsiKa

@corsiKa fбез другого аргументу повторює всі позитивні цілі числа, починаючи з 1і повертає перше значення, яке дає істинне значення у внутрішньому твердженні. Це значення, як правило, не використовується в цій програмі, тому воно повертає кількість запущених разів. Недокументований, просто неортодоксальний :) Якщо це допоможе, ви можете подумати про це як forцикл на зразок:for(int i=1; some_condition_unrelated_to_i; i++) { change_stuff_that_affects_condition_but_not_i;}
FryAmTheEggman

@corsiKa Це задокументовано у посиланні на символи, що знаходиться праворуч від онлайн-перекладача. Маючи лише один аргумент ( f <l:T> <none>), fце перший ввід, де A(_)надбавка[1, 2, 3, 4...] .
Денніс

Ах, я це зараз розумію. Він використовує цей вхід, але ніколи не використовує дані для обчислення . Це пояснює @Maltysen коментар "це дійсно приємний трюк", тому що ви дбаєте лише про кількість ітерацій, не використовуючи цей рахунок ніде у вашому фільтрі. Я люблю ті ах-ха моменти !
:)

7

Python 2, 50 49 байт

f=lambda n,k=1:2/n or n%(n-k)and f(n,k+1)or-~f(k)

Цей останній тестовий випадок незабаром не закінчиться ...

З іншого боку , ось 48-байт , який повертає Trueзамість 1для n=2:

f=lambda n,k=1:n<3or n%(n-k)and f(n,k+1)or-~f(k)

6

Желе , 10 байт

ÆfḊPạµÐĿi2

Спробуйте в Інтернеті! або перевірити більшість тестових випадків . Останні тестові випадки швидко закінчуються локально.

Як це працює

ÆfḊPạµÐĿi2  Main link. Argument: n (integer)

Æf          Factorize n, yielding a list of primes, [] for 1, or [0] for 0.
  Ḋ         Dequeue; remove the first (smallest) element.
   P        Take the product.
            This yields the largest proper divisor if n > 1, 1 if n < 2.
    ạ       Yield the abs. value of the difference of the divisor (or 1) and n.
     µ      Convert the chain to the left into a link.
      ÐĿ    Repeatedly execute the link until the results are no longer unique.
            Collect all intermediate results in a list.
            For each starting value of n, the last results are 2 -> 1 -> 0 (-> 1).
        i2  Compute the 1-based index of 2.

5

Сітківка , 12

  • 14 байт збережено завдяки @ MartinBüttner
(1 +) (? = \ 1 + $)

Це передбачає введення, задане унітарно, а вихідне в десяткових. Якщо це не прийнятно, ми можемо зробити це ще на 6 байт:

Сітківка , 18

  • 8 байт збережено завдяки @ MartinBüttner
. +
$ *
(1 +) (? = \ 1 + $)

Спробуйте в Інтернеті - додано 1-й рядок для запуску всіх тестів за один раз.

На жаль, для обчислень це використовується уніар, тому введення 2016 155 не є практичним.

  • Перший етап (2 рядки) просто перетворює десяткове введення в одинарне у вигляді рядка 1s
  • На другому етапі (1 рядок) обчислюється найбільший коефіцієнт n, використовуючи групи підрівнювання регулярних виразів і дивлячись позаду, і ефективно віднімає його від n. Цей регулярний вираз збігається стільки разів, скільки потрібно, щоб зменшити кількість, наскільки це можливо. Кількість збігів регулярних виразів буде кількістю кроків і виводиться на цьому етапі.

Я не думаю, що вам це потрібно \b.
Мартін Ендер

Ви можете заощадити набагато більше , як це , хоча і технічно не потрібен перший етап або .
Мартін Ендер

@ MartinBüttner Фантастичний! Дуже елегантно - дякую!
Цифрова травма

5

Pyth - 15 14 13 байт

Спеціальний корпус 1мене справді вбиває.

tl.u-N/Nh+PN2

Спробуйте його онлайн тут .

tl                One minus the length of
 .u               Cumulative fixed point operator implicitly on input
  -N              N -
   /N             N /
    h             Smallest prime factor
     +PN2         Prime factorization of lambda var, with two added to work with 1

1
Одне, що я завжди забуваю .... жорстока сила - це найголовніший підхід
Leaky Nun

Що ви маєте на увазі під спеціальним кожухом 1?
Аднан

1
@Adnan основним фактором 1є [], що викликає помилку, коли я беру перший елемент. Я маю особливий випадок, щоб він повернувся 1знову, щоб .uфіксована точка закінчилася. Я знайшов кращий спосіб, ніж .xспробувати, за винятком того, що врятувало мене ці 2 байти.
Малтісен

Потрібно лише прийняти числа> = 2 (> 1).
Соломон Учко

@SolomonUcko ви нерозумієте, .uфіксована точка зрештою досягне 1всіх вхідних даних, і в цей момент її доведеться спеціально розглянути.
Малтісен

5

JavaScript (ES6), * 44 38

Редагуйте 6 байтів, збережених завдяки @ l4m2

(* 4 страйку все ще 4)

Рекурсивна функція

f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0

Менше гольфу

f=(n, d=n-1)=>{
  if (n>1)
    if(n % d != 0)
      return f(n, d-1) // same number, try a smaller divisor
    else
      return f(n-d)+1  // reduce number, increment step, repeat
  else
    return 0
}

Тест

f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0

console.log=x=>O.textContent+=x+'\n';

[5,30,31,32,100,200].forEach(x=>console.log(x+' -> '+f(x)))
<pre id=O></pre>


Добре, але я думаю, що вам слід витратити два байти, необхідні для створення f (1) == 0.
Ніл

@Ніл знову думає: ні. "Нехай n - натуральне число ≥ 2 ..."
edc65

Мені потрібні нові окуляри.
Ніл

Чому ні f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0?
l4м2

@ l4m2 правильно, чому б і ні? Спасибі
edc65

4

Математика, 36 байт

f@1=0;f@n_:=f[n-Divisors[n][[-2]]]+1

Неназвана функція займає ті самі байти:

If[#<2,0,#0[#-Divisors[#][[-2]]]+1]&

Це дуже пряма реалізація визначення як рекурсивної функції.


4

Октава, 59 58 55 байт

function r=f(x)r=0;while(x-=x/factor(x)(1));r++;end;end

Оновлено завдяки Стюі Гріффін, заощаджуючи 1 байт

Подальше оновлення, зберігаючи ще три байти, використовуючи результат факторизації під час перевірки.

Проби:

octave:41> f(5)
ans =  3
octave:42> f(30)
ans =  6
octave:43> f(31)
ans =  7
octave:44> f(32)
ans =  5
octave:45> f(100)
ans =  8
octave:46> f(200)
ans =  9

остання endнеобхідна в октаві?
Abr001am

Це є. Я помітив, що це не було в матлабі з ваших відповідей, але Октав очікує цього (як я дізнався, пробуючи ваші в Октаві).
dcsohl

4

Haskell, 59 байт

f 1=0;f n=1+(f$n-(last$filter(\x->n`mod`x==0)[1..n`div`2]))

Використання:

Prelude> f 30
Prelude> 6

Це може бути малоефективним для великої кількості через генерування списку.


1
Перелічіть розуміння і <1замість цього ==0економить кілька байт: f 1=0;f n=1+f(n-last[a|a<-[1..ndiv2],mod n a<1])
Angs

4

Юлія, 56 50 45 39 байт

f(n)=n>1&&f(n-n÷first(factor(n))[1])+1

Це рекурсивна функція, яка приймає ціле число і повертає ціле число.

Безголівки:

function f(n)
    if n < 2
        # No decrementing necessary
        return 0
    else
        # As Dennis showed in his Jelly answer, we don't need to
        # divide by the smallest prime factor; any prime factor
        # will do. Since `factor` returns a `Dict` which isn't
        # sorted, `first` doesn't always get the smallest, and
        # that's okay.
        return f(n - n ÷ first(factor(n))[1]) + 1
    end
end

Спробуйте в Інтернеті! (включає всі тестові випадки)

Збережено 6 байт завдяки Мартіну Бюттнеру та 11 подякам Деннісу!


3

PowerShell v2 +, 81 байт

param($a)for(;$a-gt1){for($i=$a-1;$i-gt0;$i--){if(!($a%$i)){$j++;$a-=$i;$i=0}}}$j

Жорстока груба сила.

Здійснює введення $a, вводить forцикл до тих пір, поки $aце менше або дорівнює 1. Кожен цикл ми проходимо через інший forцикл, який відлічується, $aпоки не знайдемо дільник ( !($a%$i). У гіршому випадку ми знайдемо $i=1як дільник. Коли ми це робимо, збільшуємо свій лічильник $j, віднімаємо наш дільник $a-=$iі встановлюємо, $i=0щоб вирватися з внутрішньої петлі. Врешті-решт ми досягнемо умови, коли зовнішня петля помилкова (тобто $aдосягнута 1), тому виводимо $jта виходимо.

Обережно : на більшу кількість, особливо на праймери, це займе багато часу. Вхід 100 000 000 займає ~ 35 секунд на моєму ноутбуці Core i5. Редагування - щойно перевірено [int]::MaxValue(2 ^ 32-1), і це зайняло ~ 27 хвилин. Я не надто поганий, гадаю.



3

Japt , 12 байт (неконкурентоспроможний)

@!(UµUk Å×}a

Перевірте це в Інтернеті! Неконкурентований, оскільки він використовує купу функцій, які були додані після публікації виклику.

Як це працює

@   !(Uµ Uk Å  ×   }a
XYZ{!(U-=Uk s1 r*1 }a
                       // Implicit: U = input integer
XYZ{               }a  // Return the smallest non-negative integer X which returns
                       // a truthy value when run through this function:
         Uk            //   Take the prime factorization of U.
            s1         //   Slice off the first item.
                       //   Now we have all but the smallest prime factor of U.
               r*1     //   Reduce the result by multiplication, starting at 1.
                       //   This takes the product of the array, which is the
                       //   largest divisor of U.
      U-=              //   Subtract the result from U.
    !(                 //   Return !U (which is basically U == 0).
                       //   Since we started at 0, U == 1 after 1 less iteration than
                       //   the desired result. U == 0 works because the smallest
                       //   divisor of 1 is 1, so the next term after 1 is 0.
                       // Implicit: output result of last expression

Цей прийом надихнув відповідь 05AB1E . Використовувана попередня версія ²¤(натисніть 2, відріжте перші два елементи) замість того, Åщо вона на один байт коротша s1 (пробіл відмітка); Я зрозумів лише після того, що, оскільки це додає 2 до кінця масиву та фрагментів з початку , він насправді не відповідає будь-якому непарному складеному номеру, хоча це працює у всіх заданих тестових випадках.


2

Python 3, 75, 70 , 67 байт.

g=lambda x,y=0:y*(x<2)or[g(x-z,y+1)for z in range(1,x)if x%z<1][-1]

Це досить прямолінійне рекурсивне рішення. ДЛЯ ВЕЛИКОГО часу потрібно для тестових справ з великою кількістю.


2

> <>, 32 байти

<\?=2:-$@:$/:
1-$:@@:@%?!\
;/ln

Очікує номер введення,, nна стеку.

Ця програма будує повну послідовність на стеку. Як єдине число, яке може призвести до 1цього 2, побудова послідовності зупиняється, коли вона 2буде досягнута. Це також призводить до того, що розмір стека дорівнює кількості кроків, а не кількості кроків +1.


2

Рубін, 43 байти

f=->x{x<2?0:1+f[(1..x).find{|i|x%(x-i)<1}]}

Знайдіть найменше число iтаке, яке xділиться x-iі повторюється, поки ми не дійдемо 1.


2

Haskell, 67 байт

Ось код:

a&b|b<2=0|a==b=1+2&(b-1)|mod b a<1=1+2&(b-div b a)|1<2=(a+1)&b
(2&)

І ось одна з причин, чому Haskell є приголомшливим:

f = (2&)

(-->) :: Eq a => a -> a -> Bool
(-->) = (==)

h=[f(5)        --> 3
  ,f(30)       --> 6
  ,f(31)       --> 7
  ,f(32)       --> 5
  ,f(100)      --> 8
  ,f(200)      --> 9
  ,f(2016^155) --> 2015
  ]

Так, у Haskell ви можете визначити -->еквівалент ==.


2

Матлаб, 107 байт

a=input('');b=factor(a-isprime(a));c=log2(a);while(max(b)>1),b=max(factor(max(b)-1));c=c+1;end,disp(fix(c))
  • Це неконкурентний переклад мого останнього подання, лише черговий прямий алгебраїчний метод, він підсумовує всі бінарні журнали всіх простих факторів, начебто неоднозначні для ілюстрації.
  • Я буду більше займатися гольфом, коли матиму час.

2

MATL, 17 16 байт

`tttYfl)/-tq]vnq

Спробуйте в Інтернеті

Пояснення

        % Implicitly grab input
`       % Do while loop
    ttt % Make three copies of top stack element
    Yf  % Compute all prime factors
    l)  % Grab the smallest one
    /   % Divide by this to get the biggest divisor
    -   % Subtract the biggest divisor
    t   % Duplicate the result
    q   % Subtract one (causes loop to terminate when the value is 1). This
        % is functionally equivalent to doing 1> (since the input will always be positive) 
        % with fewer bytes
]       % End do...while loop
v       % Vertically concatenate stack contents (consumes entire stack)
n       % Determine length of the result
q       % Subtract 1 from the length
        % Implicitly display result

2

C99, 62 61 байт

1 байт у гольф від @Alchymist.

f(a,c,b)long*c,a,b;{for(*c=0,b=a;a^1;a%--b||(++*c,b=a-=b));}  

Викликайте як f (x, & y), де x - вхід, а y - вихід.


Якщо ви перевірите% - b, то ви можете уникнути b - наприкінці. Цілий байт збереження.
Алхімік


2

Clojure, 116 104 байт

(fn[n](loop[m n t 1](let[s(- m(last(filter #(=(rem m %)0)(range 1 m))))](if(< s 2)t(recur s (inc t))))))

-12 байт, фільтруючи діапазон, щоб знайти кратні, а потім використовувати lastодин, щоб отримати найбільший

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

Попередньо гольф і тест:

(defn great-divider [n]
  ; Filter a range to find multiples, then take the last one to get the largest
  (last
     (filter #(= (rem n %) 0)
             (range 1 n))))

(defn sub-great-divide [n]
  (loop [m n
         step 1]
    (let [g-d (great-divider m) ; Find greatest divisor of m
          diff (- m g-d)] ; Find the difference
      (println m " is " g-d " --> " m " - " g-d " = " diff)
      (if (< diff 2)
        step
        (recur diff (inc step))))))

(sub-great-divide 30)

30  is  15  -->  30  -  15  =  15
15  is  5  -->  15  -  5  =  10
10  is  5  -->  10  -  5  =  5
5  is  1  -->  5  -  1  =  4
4  is  2  -->  4  -  2  =  2
2  is  1  -->  2  -  1  =  1
6

1
@insertusernamehere Ні, на жаль, тому що це всі дійсні ідентифікатори. Я видалив усі можливі пробіли. Якщо я хочу додатково пограти в гольф, мені потрібно буде переробити алгоритм.
Carcigenicate

2

Perl 6 , 35 байт

{+({$_ -first $_%%*,[R,] ^$_}...1)}

Спробуйте в Інтернеті!

Як це працює

{                                 }   # A bare block lambda.
                    [R,] ^$_          # Construct range from arg minus 1, down to 0.
        first $_%%*,                  # Get first element that is a divisor of the arg.
    $_ -                              # Subtract it from the arg.
   {                        }...1     # Do this iteratively, until 1 is reached.
 +(                              )    # Return the number of values generated this way.

1

Pyth, 17 16 байт

L?tbhy-b*F+1tPb0

Спробуйте в Інтернеті! y.vкінці призначено для виклику функції)


Оригінальний 17 байт:

L?tb+1y-b*F+1tPb0

Спробуйте в Інтернеті! y.vкінці призначено для виклику функції)

(Насправді я відповів на це питання за допомогою цієї програми Pyth.)


Я насправді не переймався вашою програмою, але якщо ви використовуєте рекурсивне визначення в ОП, uце, мабуть, коротше, ніж фактична рекурсія.
Малтісен

1

Пайк, 11 байт (неконкурентоспроможний)

D3Phf-oRr;o

Це використовує нову поведінку, коли, якщо є виняток, піднятий після goto, він відновлює стан до goto (за винятком змінних визначень) і продовжується. У цьому випадку він еквівалентний наступному коду python:

# Implicit input and variable setup
inp = input()
o = 0
# End implicit
try:
    while 1:
        inp -= factors(inp)[0] # If factors is called on the value 1, it returns an empty
                               # list which when the first element tries to be accessed
                               # raises an exception
        o += 1 # Using `o` returns the current value of `o` and increments it
except:
    print o # This in effect gets the number of times the loop went

Це все можливо, використовуючи Pyke без певної побудови циклу - yay goto!

Спробуйте тут!


1

JavaScript (ES6), 70 54 байт

f=(n,i=2)=>n<i?0:n%i?f(n,i+1):n>i?f(i)+f(n/i):1+f(n-1)

Реалізація наданої рекурсивної формули, але тепер оновлена ​​для використання рекурсії і для пошуку дільника.


1

Perl, 57 + 1 ( -pпрапор) = 58 байт

$n=$_;$n-=$n/(grep!($n%$_),2..$n/2,$n)[0],$\++while$n>1}{

Використання:

> echo 31 | perl -pe '$n=$_;$n-=$n/(grep!($n%$_),2..$n/2,$n)[0],$\++while$n>1}{'

Безголівки:

while (<>) {
# code above added by -p
    # $_ has input value
    # $\ has undef (or 0)
    my $n = $_;
    while ($n > 1) {
        my $d = 1;
        for (2 .. ($n / 2)) {
            if ($n % $_ == 0) {
                $d = $n / $_;
                last;
            }
        }
        $n -= $d;
        $\++;
    }
} {
# code below added by -p
    print;  # prints $_ (undef here) and $\
}

1

Clojure, 98 96 байт

#(loop[n % i -1](if n(recur(first(for[j(range(dec n)0 -1):when(=(mod n j)0)](- n j)))(inc i))i))

використовує for :whenдля пошуку найбільшого дільника, циклів, поки не знайдеться таке значення, яке перевищує одне.

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