通过减去最大除数从n到1需要多少步?


50

这个问题的灵感来自数学


问题

我们n是一个自然数≥ 2。取最大除数(nn自己不同)除以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) = 0a(p) = 1 + a(p-1)if 归纳定义的准对数,p以及a(n*m) = a(n) + a(m)if m,n > 1


用本地任意精度整数阐明语言的输入要求?
斯帕

@Sparr我想说的是,您至少应该支持2^32 - 1。其余的取决于您和您的系统。希望这就是您对问题的意思。
此处插入用户名,2016年

3
我喜欢标题的全部内容
路易斯·门多

Answers:


20

果冻,9 字节

ÆṪÐĿÆFL€S

在线尝试!验证所有测试用例

背景

序列A064097的定义意味着

definition

欧拉的产品公式

Euler's product formula

其中φ表示欧拉的张力函数,而p仅在素数上变化。

结合两者,我们推导出该属性

first property

其中ω表示n的不同素数的数量。

应用所得公式k + 1次,其中k足够大,使得φk + 1(n)= 1,我们得到

second property

从该属性,我们获得公式

formula

因为ω(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.

现在这是一个超级聪明的方法!
2016年

15

05AB1E13 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,2016年

@SargeBorsch是的,这是正确的:)
Adnan

[¼Ñü-¤Ä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.

这是filter 的一个非常好的技巧。
Maltysen '16

3
我不明白为什么这会输出函数运行的次数。这是的未记录功能f吗?
corsiKa's

f不带第二个参数的@corsiKa 迭代所有从开始的正整数,1并返回在内部语句上为true的第一个值。该值恰好在该程序中未使用,因此它返回其运行的次数。并非没有证件,只是非正统的:)如果有帮助,您可以将其视为一个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>),fFirst输入,其中A(_)true是over[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而不是1for 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

  • @MartinBüttner节省了14个字节
(1 +)(?= \ 1 + $)

假定输入为一进制,输出为十进制。如果这是不可接受的,那么我们可以多做6个字节:

视网膜 18

  • @MartinBüttner节省了8个字节
。+
$ *
(1 +)(?= \ 1 + $)

在线尝试-添加了第一行以一次性运行所有测试用例。

可悲的是,这使用一元进行计算,因此2016 155的输入不切实际。

  • 第一级(2行)将十进制输入简单地转换为一串1s的一元
  • 第二阶段(1行)使用正则表达式匹配组计算n的最大因数,然后查找并有效地从n中减去它。此正则表达式将匹配尽可能多的次数,以尽可能减少数量。正则表达式匹配数将是步数,并在此阶段输出。

我认为您不需要\b
马丁·恩德


@MartinBüttner太棒了!非常优雅-谢谢!
Digital Trauma

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定点结束。我找到了比.xtry-except 更好的方法,除了这为我节省了这2个字节。
Maltysen,2013年

它只需要接受数字> = 2(> 1)。
所罗门·乌科

@SolomonUcko您误会了,.u定点将最终到达1所有输入,此时必须进行特殊情况处理。
Maltysen

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所需的两个字节
Neil

@尼尔再想:没有。“让n是一个自然数≥2 ...”
edc65 '16

我需要新眼镜。
尼尔

为什么不f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0呢?
l4m2

@ l4m2对,为什么不呢?谢谢
edc65 '18

4

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

感谢Stewie Griffin更新,节省了1个字节

进一步更新,通过在while-check中使用分解的结果来节省三个字节。

样品运行:

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八度中的最后一个是吗?
2016年

它是。我从您的答案中注意到它不在matlab中,但是Octave期望它(正如我从在Octave中尝试您的经验中学到的)。
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 '18

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

在线尝试!(包括所有测试用例)

感谢MartinBüttner,节省了6个字节;感谢Dennis,节省了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并退出。

注意:较大的数字,尤其是素数,将花费很长时间。在我的Core i5笔记本电脑上输入1亿,大约需要35秒。编辑 -刚刚用[int]::MaxValue(2 ^ 32-1)进行了测试,大约花费了27分钟。不是糟糕,我想。


3

Matlab,58个字节

function p=l(a),p=0;if(a-1),p=1+l(a-a/min(factor(a)));end

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在堆栈上输入数字。

该程序在堆栈上构建完整的序列。由于唯一可导致的数字12,构建序列会在2到达时停止。这也会导致堆栈的大小等于步数,而不是步数+1。


2

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

Matlab,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个字节

@Alchymist打了1个字节。

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是输出。


如果您测试a%-b,那么最后可以避免b--。节省一整个字节。
Alchymist


2

Clojure,116104字节

(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))))))

过滤一个范围以找到倍数,然后使用last一个获得最大的一个,从而得到-12个字节

天真的解决方案,基本上可以解决OP所描述的问题。不幸的是,仅找到最大的除数就占用了一半的字节。至少我应该从这里有很多打高尔夫球的空间。

预先测试并测试:

(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程序回答了这个问题。)


我实际上并不在乎您的程序,但是如果您在OP中使用递归定义,u则它可能比实际的递归要短。
马蒂森(Maltysen)

1

Pyke,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无需使用while循环即可实现所有功能-快去吧!

在这里尝试!


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查找最大的除数,直到发现没有大于1的值为止一直循环。

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.