除数减少


21

数字n的除数是将n平均除的任何数字,包括1和n本身。除数d(n)是一个数有多少个除数。这是前两个n 的d(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,2016年

Answers:


1

果冻,10 9个字节

1字节感谢Dennis♦

我在Pyth答案

ÆDLạµÐĿL’

在线尝试!

测试套件。

说明

_ÆDL$$ÐĿL’
      ÐĿ    Repeat the following until result no longer unique:
 ÆD             Yield the array of the divisors
   L            Yield the length of the array
_               Subtract that from the number
        L   Number of iterations
         ’  Minus one.

6

Python,49个字节

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

orlp帮助节省了一个字节!Sp3000又节省了两个。谢谢!


1
应该可以通过将-~移到n%-~k并删除范围的下限来缩短内容。
orlp

5

C,52个字节

g,o;l(f){for(g=o=f;o;f%o--||--g);return f?1+l(g):0;}

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

不要问我为什么我不必要地使用尾递归。


2

爪哇,147 93

a->{int k,i,n=new Integer(a),l=0;for(;n!=0;n-=k)for(l+=k=i=1;i<n;)if(n%i++==0)++k;return l;}

3
为什么要n=new Integer(100000)代替n=100000
user8397947's

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个字节,并通过@Adnan修复了输入0的错误


非常好!我尝试打一下高尔夫球,并将其减小到10个字节:[Ð>#Ñg-¼]¾。不过,必须有一种方法来缩短它的长度
Adnan

@LuisMendo是的,因为该D0Q#部分在计数器增加之后。该[Ð>#Ñg-¼]¾代码应该可以工作0:)。
阿德南

@Adnan:我尝试了基于生成所有计数最多n并从索引到索引处的值并向上计数的版本,但是没有设法使它更短。
Emigna '16


1

Mathcad,[tbd]字节

enter image description here


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

Hoon93 76字节

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

取消高尔夫:

|=  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还要短一个字节,甚至
林恩(Lynn)2016年

1

PowerShell v2 +,74 67字节

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

与其他一些答案相比,似乎很冗长。

接受输入$nfor$n大于的条件进入循环0。每次循环迭代我们设置助手$a,然后通过从每一个数字环路1最多$n。每个内部循环我们都会检查每个数字是否是除数,如果是,我们将增加辅助函数$a(使用布尔求和和隐式强制转换为整数)。然后,我们减去找到的除数$n-=$a并增加counter $o++。最后,我们输出$o

需要很长的时间来执行,因为它是一个显著for循环结构。例如,n = 10,000在我的计算机(旧的Core i5版本)上运行大约需要3分钟。


1

球拍-126字节降至98字节 91字节

一个非常幼稚的解决方案-也许可以通过一个不错的算法和一些我不知道的Lisp技巧将其削减很多

(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:通过替换(cdr(build-list x values))为保存7个字节(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我爱Lisp!)
NoOneIsHere16年

@NoOneIsHere编辑于
kronicmage '16

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

> <>,36 + 3 = 39字节

:?v~ln; >~&
:}\0&
+&>1-:?!^:{:}$%0)&

该实现相对简单,每次迭代为sum(n%k>0 for k in range(1,n-1))-v每个meta +3字节的标志

在线尝试!


0

Ruby,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

C#,63个字节

int F(int n)=>n<1?0:F(Enumerable.Range(1,n).Count(i=>n%i>0))+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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.