Уменьшение делителя


21

Делителем числа n является любое число, которое равномерно делит n , включая 1 и само n . Число делителей d (n) - это число делителей числа. Вот d (n) для первой пары n:

n    divisors    d(n)
1    1           1
2    1, 2        2
3    1, 3        2
4    1, 2, 4     3
5    1, 5        2
6    1, 2, 3, 6  4

Мы можем многократно вычитать количество делителей из числа. Например:

16                  = 16
16 - d(16) = 16 - 5 = 11
11 - d(11) = 11 - 2 = 9
 9 - d( 9) =  9 - 3 = 6
 6 - d( 6) =  6 - 4 = 2
 2 - d( 2) =  2 - 2 = 0

В этом случае потребовалось 5 шагов, чтобы добраться до 0.


Напишите программу или функцию, которая с неотрицательным числом n возвращает количество шагов, необходимых для ее уменьшения до 0, путем повторного вычитания числа делителей.

Примеры:

0, 0
1, 1
6, 2
16, 5
100, 19
100000, 7534

5
Обязательная ссылка OEIS: A155043
Sp3000

Ответы:



6

Python, 49 байт

f=lambda n:n and-~f(sum(n%~x<0for x in range(n)))

orlp помог сохранить байт! И Sp3000 сохранил еще два. Благодарность!


1
Должны быть в состоянии сократить вещи, перемещая -~в n%-~kи удаляя нижнюю границу диапазона.
orlp


4

Pyth, 10 байт

tl.ulf%NTS

Тестирование.

объяснение

tl.ulf%NTS
tl.ulf%NTSNQ  implicit variables at the end
           Q  obtain the input number
  .u      N   repeat the following until result no longer unique:
         S        generate range from 1 to N
     f            filter for:
      %NT             T in that range, which N%T is truthy (not zero)
    l             length of that list
                  that means, we found the number of "non-divisors" of N
tl            number of iterations, minus 1.

3

Юлия, 31 байт

f(n)=n<1?0:f(sum(n%(1:n).>0))+1

Простая рекурсивная реализация.


2

MATL , 14 байтов

`t~?x@q.]t:\zT

Попробуйте онлайн!

объяснение

`            T  % Infinite loop
 t~?    ]       % Duplicate number. Is it non-zero?
    x@q.        % If so: delete number, push iteration index minus 1, break loop
         t:\    % Duplicate, range, modulo (remainder). Divisors give a 0 remainder
            z   % Number of non-zero elements; that is, of non-divisors

2

JavaScript (ES6), 64 51 байт

f=n=>n&&[...Array(m=n)].map((_,i)=>m-=n%++i<1)|f(m)+1

Не спрашивайте меня, почему я без необходимости использовал хвостовую рекурсию.



1

05AB1E, 12 10 байт

Код:

[Ð>#Ñg-¼]¾

Объяснение:

[           # start infinite loop
 Ð          # triplicate current number
  >#        # increase by 1 and break if true
    Ñg      # get number of divisors
      -     # subtract number of divisors from number
       ¼    # increase counter
        ]   # end loop
         ¾  # print counter

Попробуйте онлайн

Редактировать: 2 байта сохранены и ошибка с вводом 0 исправлена ​​благодаря @Adnan


Очень хорошо! Я попытался немного поиграть в гольф, и уменьшил до 10 байтов [Ð>#Ñg-¼]¾. Должен быть способ сделать это короче, хотя ...
Аднан

@ LuisMendo Да, это потому, что D0Q#часть после увеличения счетчика. [Ð>#Ñg-¼]¾Код должен работать , 0хотя :).
Аднан

@Adnan: я попробовал версию, основанную на генерации всех подсчетов до n и переходе от индекса к значению при индексировании и подсчете, но мне не удалось сократить его таким образом.
Эминья


1

Mathcad, [tbd] байт

введите описание изображения здесь


Схема эквивалентности байтов Mathcad еще не определена. Используя грубую эквивалентность нажатий клавиш, программа использует около 39 «байтов». Обратите внимание, что операторы while и for программируют только одну операцию на клавиатуре для ввода (ctl-] и ctl-shft- # соответственно) - действительно, они могут быть введены таким образом только с клавиатуры.

То, что вы видите, это именно то, что записано на листе Mathcad. Mathcad оценивает уравнения / программы и размещает выходные данные на одном листе (например, после оператора оценки '=' или на графике).


1

MATL, 13 байт

tX`t:\ztt]Nq&

Попробуйте онлайн

Объяснение:

t               % Duplicate input
 X`      ]      % while loop, consumes 1 input
   t:\z         % calculates n-d(n), by counting number non-divisors
       tt       % dupe twice, for while loop condition, next iteration and to keep in stack
          Nq&   % get stack size, decrement, display that value

1

Mathematica, 35 байт

If[#<1,0,#0[#-0~DivisorSigma~#]+1]&

Использование старого доброго DivisorSigma. @ MartinBüttner отмечает следующие альтернативы:

If[#<1,0,#0[#-DivisorSum[#,1&]]+1]&
f@0=0;f@n_:=f[n-DivisorSum[n,1&]]+1

1

Хун , 93 76 байт

|=
r/@
?~
r
0
+($(r (sub r (lent (skim (gulf 1^r) |=(@ =(0 (mod r +<))))))))

Ungolfed:

|=  r/@
?~  r
  0
=+  (skim (gulf 1^r) |=(@ =(0 (mod r +<))))
+($(r (sub r (lent -))))

Возвращает функцию , которая принимает атом r. Создайте промежуточное значение, которое содержит все отклонения r(Составьте список [1..n], оставьте только те элементы, где (mod ri) ​​== 0). Еслиr ноль, вернуть ноль, иначе вернуть увеличенное значение рекурсии с r, равным r- (делители длины).

Код как есть занимает глупое количество времени для оценки при n = 100.000, полностью потому, что поиск девиаторов для больших чисел создает гигантский список и отображает его. Запоминание делителей дает правильный вывод для n = 10.000, но я не стал ждать 100.000


1

Haskell, 43 40 39 байт

g 0=0;g n=1+g(sum$min 1.mod n<$>[1..n])

Простой рекурсивный подход. Пример использования: g 16->5 .

Редактировать: @Lynn сохранил 3 4 байта. Благодарность!


Как насчет g(sum$signum.mod n<$>[1..n])?
Линн

О, и min 1на самом деле на один байт короче signum, даже
Линн

1

PowerShell v2 +, 74 67 байт

param($n)for($o=0;$n-gt0){$a=0;1..$n|%{$a+=!($n%$_)};$n-=$a;$o++}$o

Кажется довольно длинным по сравнению с некоторыми другими ответами ...

Принимает ввод $n, входит в forцикл с условием, $nкоторое больше, чем 0. Каждую итерацию цикла мы устанавливаем помощником $a, затем перебираем каждое число от 1до $n. Каждый внутренний цикл мы проверяем по каждому числу, чтобы увидеть, является ли он делителем, и если это так, мы увеличиваем наш помощник $a(используя логическое отрицание и неявное приведение к int). Затем мы вычитаем количество найденных делителей $n-=$aи увеличиваем наш счетчик $o++. Наконец, мы выводим$o .

Выполнение занимает много времени, так как это существенная конструкция цикла for. Например, запуск n = 10,000на моей машине (1-летний Core i5) занимает почти 3 минуты.


1

Ракетка - 126 байт До 98 байт 91 байт

Чрезвычайно наивное решение - вероятно, можно было бы много сократить с помощью приличного алгоритма и некоторых хитростей, которые я не знаю

(define(g x[c 0][d 0][i 2])(cond[(= x 0)c][(= i x)(g d(+ 1 c))][(=(modulo x i)0)(g x c d(+ 1 i))][else(g x c(+ 1 d)(+ 1 i))]))

Изменить: объяснение по запросу. Как я уже сказал, это чрезвычайно наивное рекурсивное решение и может быть намного короче.

(define (g x [c 0] [d 0] [i 2]) ;g is the name of the function - arguments are x (input), c (counter for steps), d (non-divisor counter), i (iterator)
  (cond
    [(= x 0) c] ;once x gets to 0 c is outputted
    [(= i x) (g d (+ 1 c))] ;if iterator reaches x then we recurse with d as input and add 1 to c
    [(= (modulo x i) 0) (g x c d (+ 1 i))] ;checks if iterator is non divisor, then adds it to d and increments iterator
    [else(g x c (+ 1 d) (+ 1 i))])) ;otherwise just increments iterator

Редактировать 2: 98-байтовую версию с менее глупым алгоритмом (хотя он все еще довольно тупой и может быть короче)

(define(g x)(if(< x 1)0(+ 1(g(length(filter(λ(y)(>(modulo x y)0))(cdr(build-list x values))))))))

Объяснение:

(define (g x) ;function name g, input x
  (if (< x 1)
      0 ;returns 0 if x < 1 (base case)
      (+ 1 ;simple recursion - adds 1 to output for each time we're looping
         (g (length ;the input we're passing is the length of... 
              (filter (λ (y) (> (modulo x y) 0)) ;the list where all numbers which are 0 modulo x are 0 are filtered out from...
                             (cdr (build-list x values)))))))) ;the list of all integers up to x, not including 0

Редактировать 3: Сохранено 7 байтов путем замены (cdr(build-list x values))на(build-list x add1)

(define(g x)(if(< x 1)0(+ 1(g(length(filter(λ(y)(>(modulo x y)0))(build-list x add1)))))))

Здравствуйте и добро пожаловать в PPCG! Отличный пост! Можете ли вы объяснить свое решение, пожалуйста? (PS Я люблю Лисп!)
NoOneIsHere

@NoOneIsHere Отредактировано в
kronicmage

0

> <> , 52 + 2 = 54 байта

Входной номер должен присутствовать в стеке при запуске программы, поэтому для -vфлага есть +2 байта . Попробуйте онлайн!

:0)?v~ln;>~$-]
03[}\::
@@:$<    v?=0:-1}+{~$?@@01%@:

4 раздражающих байта потрачены впустую на вопросы выравнивания. Ба.

Этот работает путем построения последовательности от nдо0 в стеке. Как только 0 будет достигнуто, вытолкните его и выведите длину оставшегося стека.

Кстати, он работает O(n^2)вовремя, поэтому я бы не стал пытаться n = 100000...


-vодин байт, а не два.
NoOneIsHere


0

Рубин, 42 байта

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

В самом большом тестовом примере есть ошибка переполнения стека 100000, так что вот итерационная версия в пределах 49 байтов . Хотя и требует времени, учитывая O(N^2)сложность.

->n{c=0;c+=1 while 0<n-=(1..n).count{|i|n%i<1};c}

0

Perl 5, 40 байт

sub f{@_?(1,f((1)x grep@_%$_,1..@_)):()}

Ввод и вывод в виде списков необходимого количества копий 1.



0

На самом деле, 17 байтов

";╗R`╜%`░l;"£╬klD

Попробуйте онлайн! (примечание: время последнего теста на TIO истекло)

Объяснение:

";╗R`╜%`░l;"£╬klD
"          "£╬     while top of stack is truthy, call the function:
 ;╗                  push a copy of n to reg0
   R                 range(1,n+1) ([1,n])
    `  `░l             push the number of values where the following is truthy:
     ╜%                  k mod n
                       (this computes the number of non-divisors of n)
          ;            make a copy
              klD  push entire stack as list, count number of items, subtract 1
                   (the result is the number of times the function was called)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.