Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Inspired by this question over at Mathematics.


The Problem

Let n be a natural number ≥ 2. Take the biggest divisor of n – which is different from n itself – and subtract it from n. Repeat until you get 1.

The Question

How many steps does it take to reach 1 for a given number n ≥ 2.

Detailed Example

Let n = 30.

The greatest divisor of:

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

It takes 6 steps to reach 1.

Input

  • Input is an integer n, where n ≥ 2.
  • Your program should support input up to the language's maximum integer value.

Output

  • Simply output the number of steps, like 6.
  • Leading/trailing whitespaces or newlines are fine.

Examples

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

Requirements

  • You can get input from STDIN, command line arguments, as function parameters or from the closest equivalent.
  • You can write a program or a function. If it is an anonymous function, please include an example of how to invoke it.
  • This is so shortest answer in bytes wins.
  • Standard loopholes are disallowed.

This series can be found on OEIS as well: A064097

A quasi-logarithm defined inductively by a(1) = 0 and a(p) = 1 + a(p-1) if p is prime and a(n*m) = a(n) + a(m) if m,n > 1.

share|improve this question

14 Answers 14

05AB1E, 13 11 bytes

Code:

[DÒ¦P-¼D#]¾

Explanation:

[        ]   # 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.

Uses CP-1252 encoding. Try it online!.

share|improve this answer
3  
Remove the first prime factor (the smallest one), in order to get the largest product How clever! :-) – Luis Mendo 4 hours ago
    
@LuisMendo Thank you! :) – Adnan 4 hours ago

Pyth, 11 bytes

fq1=-Q/QhPQ

Test suite

A straightforward repeat-until-true loop.

Explanation:

fq1=-Q/QhPQ
               Implicit: Q = eval(input())
f              Apply the following function until it is truthy:
         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.
share|improve this answer

Pyth - 15 14 13 bytes

Special casing 1 is really killing me.

tl.u-N/Nh+PN2

Try it online here.

share|improve this answer
    
One thing I always forget.... brute force is often the golfiest approach – Kenny Lau 4 hours ago
    
What do you mean with special casing 1? – Adnan 4 hours ago
    
@Adnan the prime factorization of 1 is [], which causes an error when I take the first element. I have to special case it to make it return 1 again so the .u fixed-point ends. I found a better way than .x try-except which is what saved me those 2 bytes. – Maltysen 4 hours ago

Mathematica, 36 bytes

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

An unnamed function takes the same bytes:

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

This is a very straightforward implementation of the definition as a recursive function.

share|improve this answer

PowerShell v2+, 81 bytes

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

Brutest of brute force.

Takes input $a, enters a for loop until $a is less than or equal to 1. Each loop we go through another for loop that counts down from $a until we find a divisor (!($a%$i). At worst, we'll find $i=1 as a divisor. When we do, increment our counter $j, subtract our divisor $a-=$i and set $i=0 to break out of the inner loop. Eventually, we'll reach a condition where the outer loop is false (i.e., $a has reached 1), so output $j and exit.

Caution: This will take a long time on larger numbers, especially primes. Input of 100,000,000 takes ~35 seconds on my Core i5 laptop. Edit -- just tested with [int]::MaxValue (2^32-1), and it took ~27 minutes. Not too bad, I suppose.

share|improve this answer

Python, 50 48 bytes

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

Return True for n=2, if that's okay. This isn't going to finish that last test case any time soon...

Alternatively, a 49-byte which returns 1 for n=2 (Python 2 only):

f=lambda n,k=1:2/n or n%(n-k)and f(n,k+1)or-~f(k)
share|improve this answer

Pyth, 17 16 bytes

L?tbhy-b*F+1tPb0

Try it online! (The y.v at the end is for function calling)


Original 17 bytes:

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

Try it online! (The y.v at the end is for function calling)

(I actually answered that question with this Pyth program.)

share|improve this answer
    
I didn't actually bother going through your program, but if you're using the recursive definition in the OP, u is probably shorter than actual recursion. – Maltysen 4 hours ago

Python 3, 75, 70, 67 bytes.

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]

This is a pretty straight forward recursive solution. It takes a VERY long time for the high number test cases.

share|improve this answer

><>, 32 bytes

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

Expects the input number, n, on the stack.

This program builds the complete sequence on the stack. As the only number that can lead to 1 is 2, building the sequence stops when 2 is reached. This also causes the size of the stack to equal the number of steps, rather than the number of steps +1.

share|improve this answer

Matlab(58)

  function p=l(a),p=0;if(a-1),p=1+l(a-a/min(factor(a)));end
share|improve this answer

C99, 62 bytes

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

Call as f(x,&y), where x is the input and y is the output.

share|improve this answer

Haskell, 65 bytes

Here's the code:

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&

And here's one reason why Haskell is awesome:

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
  ]

Yes, in Haskell you can define --> to be equivalent to ==.

share|improve this answer

Retina, 26

.+
$*
+`\b(1+)(\1+)$
,$2
,

Try it online - 1st line added to run all testcases in one go.

Sadly this uses unary for the calculations, so input of 2016155 is not practical.

  • The first stage simply converts the decimal input to unary as a string of 1s
  • The second stage calculates the largest factor of n using regex matching groups and effectively subtracts it from n. It also prepends a , to the pattern space. The + config causes this stage to repeat until there are no more changes. Thus the result is a number of , corresponding to the number of operations
  • The final stage simply counts and returns the number of ,.
share|improve this answer

Matlab(129)

  a=input('');c=[];b=factor(a);while(b~=1)f=sort(b);t=f(1:end-1);c=[c,t,2-(b(1)==a(1))];b=factor(max(b)-1);end,sum(fix(log2(c)))+1
  • Non-competing, this is not the iterative translation of my last submission, just another direct algerbraic method, it sums up all binary-logs of all (prime factors-1) of (maximums of factors -1) , kinda ambiguous to illustrate.
share|improve this answer
    
Does this give the correct result? For input 100 it gives 4. Also, I think you need to add disp to avoid ans=... being displayed – Luis Mendo 1 hour ago
    
@LuisMendo hmm i dont see why? my algorithm succeeds with the first testcases !! will see where is the bug – Agawa001 1 hour ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.