Proper Divisor mash-up

20

1

A proper divisor is a divisor of a number n, which is not n itself. For example, the proper divisors of 12 are 1, 2, 3, 4 and 6.

You will be given an integer x, x ≥ 2, x ≤ 1000. Your task is to sum all the highest proper divisors of the integers from 2 to x (inclusive) (OEIS A280050).

Example (with x = 6):

  • Find all the integers between 2 and 6 (inclusive): 2,3,4,5,6.

  • Get the proper divisors of all of them, and pick the highest ones from each number:

    • 2 -> 1
    • 3 -> 1
    • 4 -> 1, 2
    • 5 -> 1
    • 6 -> 1, 2, 3.
  • Sum the highest proper divisors: 1 + 1 + 2 + 1 + 3 = 8.

  • The final result is 8.

Test Cases

Input  |  Output
-------+---------
       |
 2     | 1
 4     | 4
 6     | 8
 8     | 13
 15    | 41
 37    | 229
 100   | 1690
 1000  | 165279

Rules

Mr. Xcoder

Posted 2017-06-24T11:17:05.153

Reputation: 39 774

Sandbox. – Mr. Xcoder – 2017-06-24T11:18:02.273

5If you're going to sandbox something, leave it in there for more than two hours. – Peter Taylor – 2017-06-24T12:57:37.463

@PeterTaylor I sandboxed the post only to receive feedback, because this is a very simple challenge which I would usually not post in the sandbox at all. BTW thanks for the edit. – Mr. Xcoder – 2017-06-24T13:05:56.807

Answers

13

Oasis, 4 bytes

Code:

nj+U

Try it online!

Explanation:

Extended version:

nj+00

    0   = a(0)
   0    = a(1)

a(n) =

n       # Push n
 j      # Get the largest divisor under n
  +     # Add to a(n - 1)

Adnan

Posted 2017-06-24T11:17:05.153

Reputation: 41 965

5

Python 2, 50 bytes

f=lambda n,k=2:n/k and(f(n,k+1),n/k+f(n-1))[n%k<1]

This is slow and can't even cope with input 15 on TIO.

Try it online!

However, memoization (thanks @musicman523) can be used to verify all test cases.

Try it online!

Alternate version, 52 bytes

At the cost of 2 bytes, we can choose whether to compute f(n,k+1) or n/k+f(n-1).

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

With some trickery, this works for all test cases, even on TIO.

Try it online!

Dennis

Posted 2017-06-24T11:17:05.153

Reputation: 196 637

Since f is a pure function, you can memoize it to run the larger cases on TIO

– musicman523 – 2017-06-25T02:55:02.170

Right, not being able to use a decorator threw me off. Thanks! – Dennis – 2017-06-25T03:06:58.033

5

Husk, 7 bytes

ṁȯΠtptḣ

Try it online!

Explanation

Husk has no built-in for computing the divisors directly (yet), so I'm using prime factorization instead. The largest proper divisor of a number is the product of its prime factors except the smallest one. I map this function over the range from 2 to the input, and sum the results.

ṁȯΠtptḣ  Define a function:
      ḣ  Range from 1 to input.
     t   Remove the first element (range from 2).
ṁ        Map over the list and take sum:
 ȯ        The composition of
    p     prime factorization,
   t      tail (remove smallest prime) and
  Π       product.

Zgarb

Posted 2017-06-24T11:17:05.153

Reputation: 39 083

4

Jelly, 6 bytes

ÆḌ€Ṫ€S

Try it online!

How it works

ÆḌ€Ṫ€S
ÆḌ€    map proper divisor (1 would become empty array)
           implicitly turns argument into 1-indexed range
   Ṫ€  map last element
     S sum

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

4

Brachylog, 10 bytes

⟦bb{fkt}ᵐ+

Try it online!

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

You have clearly won this in all languages so far :)) – Mr. Xcoder – 2017-06-24T11:35:26.473

4

Pyth, 13 9 8 bytes

1 byte thanks to jacoblaw.

tsm*FtPh

Test suite.

How it works

The largest proper divisor is the product of the prime factors except the smallest one.

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

8 bytes – jacoblaw – 2017-06-24T17:46:25.990

4

Haskell, 48 46 43 bytes

f 2=1
f n=until((<1).mod n)pred(n-1)+f(n-1)

Try it online!

Edit: @rogaos saved two bytes. Thanks!

Edit II: ... and @xnor another 3 bytes.

nimi

Posted 2017-06-24T11:17:05.153

Reputation: 34 639

-2 bytes: f 2=1 f n=last[d|d<-[1..n-1],mod n d<1]+f(n-1) – vroomfondel – 2017-06-24T21:28:53.230

@rogaos: Thanks! I've tried the explicit recursion myself, but didn't remove sum, so I thought it isn't shorter. – nimi – 2017-06-24T21:49:04.547

1until saves some more: until((<1).mod n)pred(n-1)+f(n-1) – xnor – 2017-06-25T04:30:06.433

4

JavaScript (ES6), 40 bytes

f=(n,i=2)=>n<2?0:n%i?f(n,i+1):n/i+f(n-1)
<input type=number oninput=o.textContent=f(this.value)><pre id=o>

A number equals the product of its highest proper divisor and its smallest prime factor.

Neil

Posted 2017-06-24T11:17:05.153

Reputation: 95 035

stack overflows for n>352(at least in this snippet, dont know if it is my browser/machine dependency) while you are supposed to support at least upto n=1000. – officialaimm – 2017-06-24T13:27:31.507

@officialaimm It works for n=1000 if you use e.g. node --stack_size=8000. – Neil – 2017-06-24T22:01:21.097

4

Japt, 8+2=10 8 6 bytes

òâ1 xo

Test it

  • 1 byte saved thanks to ETHproductions.

Explanation

    :Implicit input of integer U.
ò   :Generate an array of integers from 1 to U, inclusive
â   :Get the divisors of each number,
1   :  excluding itself.
x   :Sum the main array
o   :by popping the last element from each sub-array.
    :Implicit output of result

Shaggy

Posted 2017-06-24T11:17:05.153

Reputation: 24 623

Note that -x counts as two bytes according to this post. However, I think you can save a byte with ò2_â1 o (â excludes the original number when given an argument)

– ETHproductions – 2017-06-24T14:02:05.310

Thanks, @ETHproductions; I'd missed both those things. I wonder does that apply retroactively to all solutions where we counted flags as 1 byte? I was working up an alternative solution that didn't use a flag anyway; pointing out â's argument got me the saving I was looking for. – Shaggy – 2017-06-24T14:27:48.900

I would assume so, since we weren't really following a consensus before. BTW, I had been playing with õ Å before and found a couple 8- and 9-byters: õ Åx_/k g, õ Åx_k Å×, õ Åx_â¬o. And by combining õ and Å with your genius xo trick I found a 7-byte solution :-) – ETHproductions – 2017-06-24T15:58:56.077

4

Retina, 31 24 bytes

7 bytes thanks to Martin Ender.

.+
$*
M!&`(1+)(?=\1+$)
1

Try it online!

How it works

The regex /^(1+)\1+$/ captures the largest proper divisor of a certain number represented in unary. In the code, the \1+ is turned to a lookahead syntax.

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

4

05AB1E, 9 8 bytes

-1 Byte thanks to Leaky Nun's prime factor trick in his Pyth answer

L¦vyÒ¦PO

Try it online!

Explanation

L¦vyÒ¦PO
L¦       # Range [2 .. input]
  vy     # For each...
    Ò¦    # All prime factors except the first one
      P   # Product
       O  # Sum with previous results
         # Implicit print

Alternative 8 Byte solution (That doesnt work on TIO)

L¦vyѨθO    

and ofc alternative 9 Byte solution (That works on TIO)

L¦vyѨ®èO    

Datboi

Posted 2017-06-24T11:17:05.153

Reputation: 1 213

4

Python 2 (PyPy), 73 71 70 bytes

n=input();r=[0]*n;d=1
while n:n-=1;r[d+d::d]=n/d*[d];d+=1
print sum(r)

Not the shortest Python answer, but this just breezes through the test cases. TIO handles inputs up to 30,000,000 without breaking a sweat; my desktop computer handles 300,000,000 in a minute.

At the cost of 2 bytes, the condition n>d could be used for a ~10% speed-up.

Thanks to @xnor for the r=[0]*n idea, which saved 3 bytes!

Try it online!

Dennis

Posted 2017-06-24T11:17:05.153

Reputation: 196 637

Funny, I just wrote basically the same code.

– xnor – 2017-06-24T16:12:17.703

l=[0]*n should allow you to get rid of -2. exec kinda kills the speed, but even a while loop would be shorter than my approach. – Dennis – 2017-06-24T16:22:53.323

This seems to be marginally faster than my approach. Mind if I edit that into my answer? – Dennis – 2017-06-24T16:42:09.440

Please, go for it. – xnor – 2017-06-24T16:43:22.543

@Dennis This would have totally won a [tag:fastest-code] challege – Mr. Xcoder – 2017-06-24T17:05:07.057

1@Mr.Xcoder Not in PyPy, but yes, sieves do fine for this kind of problem. – Dennis – 2017-06-24T17:20:17.450

@Mr.Xcoder Challenge accepted!

– Anders Kaseorg – 2017-06-25T01:50:42.130

4

Mathematica, 30 bytes

Divisors[i][[-2]]~Sum~{i,2,#}&

J42161217

Posted 2017-06-24T11:17:05.153

Reputation: 15 931

3

PHP, 56 bytes

for($i=1;$v||$argn>=$v=++$i;)$i%--$v?:$v=!$s+=$v;echo$s;

Try it online!

Jörg Hülsermann

Posted 2017-06-24T11:17:05.153

Reputation: 13 026

3

MATL, 12 bytes

q:Q"@Z\l_)vs

Try it at MATL Online

Explanation

        % Implicitly grab input (N)
q       % Subtract one
:       % Create an array [1...(N-1)]
Q       % Add one to create [2...N]
"       % For each element
  @Z\   % Compute the divisors of this element (including itself)
  l_)   % Grab the next to last element (the largest that isn't itself)
  v     % Vertically concatenate the entire stack so far
  s     % Sum the result

Suever

Posted 2017-06-24T11:17:05.153

Reputation: 10 257

3

Prolog (SWI), 72 bytes

f(A,B):-A=2,B=1;C is A-1,f(C,D),between(2,A,E),divmod(A,E,S,0),B is D+S.

Try it online!

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

3

C# (.NET Core), 74 72 bytes

n=>{int r=0,j;for(;n>1;n--)for(j=n;--j>0;)if(n%j<1){r+=j;j=0;}return r;}

Try it online!

  • 2 bytes shaved thanks to Kevin Cruijssen.

Charlie

Posted 2017-06-24T11:17:05.153

Reputation: 11 448

1I know it's been about a year, but you can golf break to j=0. – Kevin Cruijssen – 2018-06-20T09:18:13.733

@KevinCruijssen a very simple but effective trick. Nice idea! – Charlie – 2018-06-20T09:22:35.337

3

Cubix, 27 39 bytes

?%\(W!:.U0IU(;u;p+qu.@Op\;;

Try it online!

Cubified

      ? % \
      ( W !
      : . U
0 I U ( ; u ; p + q u .
@ O p \ ; ; . . . . . .
. . . . . . . . . . . .
      . . .
      . . .
      . . .

Watch It Run

  • 0IU Set up the stack with an accumulator, and the starting integer. U-turn into the outer loop
  • :(? duplicate the current top of stack, decrement and test
  • \pO@ if zero loop around the cube to a mirror, grab the bottom of stack, output and halt
  • %\! if positive, mod, relect and test.
    • u;.W if truthy, u-turn, remove mod result and lane change back into inner loop
    • U;p+qu;;\( if falsey, u-turn, remove mod result, bring accumulator to top, add current integer (top) divisor push to bottom and u-turn. Clean up the stack to have just accumulator and current integer, decrement the integer and enter the outer loop again.

MickyT

Posted 2017-06-24T11:17:05.153

Reputation: 11 735

2

Python 3, 69 63 59 bytes

4 bytes thanks to Dennis.

f=lambda n:n-1and max(j for j in range(1,n)if n%j<1)+f(n-1)

Try it online!

I set the recursion limit to 2000 for this to work for 1000.

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

+1 You have my brownie points! That's the solution I was talking about when saying "shorter than 70 bytes"... – Mr. Xcoder – 2017-06-24T11:30:53.903

Also, this works in Python 2 as well – Mr. Xcoder – 2017-06-24T11:45:02.153

2

Actually, 12 bytes

u2x⌠÷R1@E⌡MΣ

Try it online!

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

2

Python 3, 78 75 73 71 bytes

Not even close to Leaky nun's python answer in byte count.

f=lambda z:sum(max(i for i in range(1,y)if 1>y%i)for y in range(2,z+1))

Try it online!

officialaimm

Posted 2017-06-24T11:17:05.153

Reputation: 2 739

1You're getting close to the first revision of my answer... you can check my editing history. – Leaky Nun – 2017-06-24T14:24:45.830

Oh, haha... I swear I did not steal it... :) – officialaimm – 2017-06-24T14:29:45.017

2

Pari/GP, 36 30 bytes

n->sum(i=2,n,i/divisors(i)[2])

Try it online!

alephalpha

Posted 2017-06-24T11:17:05.153

Reputation: 23 988

2

Charcoal, 37 bytes

A⁰βF…·²N«A⟦⟧δF⮌…¹ι«¿¬﹪ικ⊞δκ»A⁺β⌈δβ»Iβ

Try it online!

Link is to the verbose version. It took me almost all day to figure out how could I solve a non-ASCII-art-related question in Charcoal, but finally I got it and I am very proud of me. :-D

Yes, I am sure this can be golfed a lot. I just translated my C# answer and I am sure things can be done differently in Charcoal. At least it solves the 1000 case in a couple of seconds...

Charlie

Posted 2017-06-24T11:17:05.153

Reputation: 11 448

2

Python 2 (PyPy), 145 bytes

Because turning code-golf competitions into fastest-code competitions is fun, here is an O(n) algorithm that, on TIO, solves n = 5,000,000,000 in 30 seconds. (Dennis’s sieve is O(n log n).)

import sympy
n=input()
def g(i,p,k,s):
 while p*max(p,k)<=n:l=k*p;i+=1;p=sympy.sieve[i];s-=g(i,p,l,n/l*(n/l*k+k-2)/2)
 return s
print~g(1,2,1,-n)

Try it online!

How it works

We count the size of the set

S = {(a, b) | 2 ≤ an, 2 ≤ b ≤ largest-proper-divisor(a)},

by rewriting it as the union, over all primes p ≤ √n, of

Sp = {(pd, b) | 2 ≤ dn/p, 2 ≤ bd},

and using the inclusion–exclusion principle:

|S| = ∑ (−1)m − 1 |Sp1 ∩ ⋯ ∩ Spm| over m ≥ 1 and primes p1 < ⋯ < pm ≤ √n,

where

Sp1 ∩ ⋯ ∩ Spm = {(p1pme, b) | 1 ≤ en/(p1pm), 2 ≤ bp1pm − 1e},
|Sp1 ∩ ⋯ ∩ Spm| = ⌊n/(p1pm)⌋⋅(p1pm − 1⋅(⌊n/(p1pm)⌋ + 1) − 2)/2.

The sum has Cn nonzero terms, where C converges to some constant that’s probably 6⋅(1 − ln 2)/π2 ≈ 0.186544. The final result is then |S| + n − 1.

Anders Kaseorg

Posted 2017-06-24T11:17:05.153

Reputation: 29 242

Oooh, that's fast... – Mr. Xcoder – 2017-06-25T07:37:57.090

2

NewStack, 5 bytes

Luckily, there's actually a built in.

Nᵢ;qΣ

The breakdown:

Nᵢ       Add the first (user's input) natural numbers to the stack.
  ;      Perform the highest factor operator on whole stack.
   q     Pop bottom of stack.
    Σ    Sum stack.

In actual English:

Let's run an example for an input of 8.

Nᵢ: Make list of natural numbers from 1 though 8: 1, 2, 3, 4, 5, 6, 7, 8

;: Compute the greatest factors: 1, 1, 1, 2, 1, 3, 1, 4

q. Remove the first element: 1, 1, 2, 1, 3, 1, 4

Σ And take the sum: 1+1+2+1+3+1+4 = 13

Graviton

Posted 2017-06-24T11:17:05.153

Reputation: 2 295

1+1+2+1+3+1+4 = 13 not 8. Apart from that: great answer so +1. – Kevin Cruijssen – 2017-06-26T08:53:28.660

@KevinCruijssen Whoops, thanks for catching that! – Graviton – 2017-06-26T08:56:05.743

2

Java 8, 78 74 72 bytes

n->{int r=0,j;for(;n>1;n--)for(j=n;j-->1;)if(n%j<1){r+=j;j=0;}return r;}

Port of @CarlosAlejo's C# answer.

Try it here.

Old answer (78 bytes):

n->{int r=0,i=1,j,k;for(;++i<=n;r+=k)for(j=1,k=1;++j<i;k=i%j<1?j:k);return r;}

Try it here.

Explanation (of old answer):

n->{                    // Method with integer parameter and integer return-type
  int r=0,              //  Result-integers
      i=1,j,k;          //  Some temp integers
  for(;++i<=n;          //  Loop (1) from 2 to `n` (inclusive)
      r+=k)             //    And add `k` to the result after every iteration
    for(j=1,k=1;++j<i;  //   Inner loop (2) from `2` to `i` (exclusive)
      k=i%j<1?j:k       //    If `i` is dividable by `j`, replace `k` with `j`
    );                  //   End of inner loop (2)
                        //  End of loop (2) (implicit / single-line body)
  return r;             //  Return result-integer
}                       // End of method

Kevin Cruijssen

Posted 2017-06-24T11:17:05.153

Reputation: 67 575

1

Lua, 74 bytes

c=0 for i=2,...do for j=1,i-1 do t=i%j<1 and j or t end c=c+t end print(c)

Try it online!

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

1

J, 18 bytes

[:+/1}.&.q:@+}.@i.

Try it online!

Leaky Nun

Posted 2017-06-24T11:17:05.153

Reputation: 45 011

1

Stacked, 31 bytes

[2\|>[divisors:pop\MAX]map sum]

Try it online! (All testcases except for 1000, which exceeds the 60 second online time limit.)

Explanation

[2\|>[divisors:pop\MAX]map sum]
 2\|>                               range from 2 to the input inclusive
     [                ]map          map this function over the range
      divisors                      get the divisors of the number (including the number)
              :pop\                 pop a number off the array and swap it with the array
                   MAX              gets the maximum value from the array
                           sum      sum's all the max's

Conor O'Brien

Posted 2017-06-24T11:17:05.153

Reputation: 36 228

1

C (gcc), 53 bytes

x;s;f(n){for(s=0;n>1;--n){for(x=n;n%--x;);s+=x;}n=s;}

Try it online!

Comfortably an quickly passes all test cases.

Conor O'Brien

Posted 2017-06-24T11:17:05.153

Reputation: 36 228

51 bytes – ceilingcat – 2019-07-29T11:40:47.840

1

Perl 6, 36 bytes

{sum map {max grep $_%%*,^$_},2..$_}

Test it

Expanded:

{
  sum
    map
    {
      max
        grep
        $_ %% *, # is the input to this block divisible by
        ^$_      # Range of possible divisors
    },
    2 .. $_
}

Brad Gilbert b2gills

Posted 2017-06-24T11:17:05.153

Reputation: 12 713

1

Alice, 17 bytes

/o
\i@/&w!qB;?+]k

Try it online!

Explanation

This is a standard format for a program which takes input as an integer, outputs an integer, and does everything else in cardinal mode.

The program tries to add up the highest proper divisor of every number from 0 to n. In the case of 0 and 1, the number added comes from the implicit zeros on the stack, so we don't have to bother skipping these cases.

i    Take input string (in ordinal mode)
&w   Implicitly convert into an integer, and push a return address n times.
     This starts the main loop, which will run a total of n+1 times.
!    Store the accumulator on the current tape cell.
q    Get the tape position. (initially zero)
B    Compute all divisors.
;    Remove the top of the stack (the number itself).
?    Copy accumulator back from tape.
+    Add to greatest proper divisor.
]    Move tape right.
k    Return to pushed return address.  The (n+1)st time through this loop, 
     there is nowhere to return to, and the program continues.
o    Output the integer (as a string in ordinal mode).
@    Terminate.

Nitrodon

Posted 2017-06-24T11:17:05.153

Reputation: 9 181

1

Neim, 7 bytes

Γ)

Explanation:

Example input: 6
        Inclusive range [1 .. input]
         stack: [1 2 3 4 5 6]
 Γ       For each...
          Get factors
           stack: [[1] [1 2] [1 3] [1 2 4] [1 5] [1 2 3 6]]
          Remove last element
           stack: [[] [1] [1] [1 2] [1] [1 2 3]]
          Get greatest element
           stack: [0 1 1 2 1 3]
      )  End for each
        Sum.
         stack: [8]
Implicit output: 8

Try it!

Okx

Posted 2017-06-24T11:17:05.153

Reputation: 15 025

0

Charcoal, 22 bytes

IL⪫E…·²N×⌈E…¹ι⎇﹪ιλ⁰λ1ω

Try it online! Link is to verbose version of code. Explanation:

      ²                 Literal 2
       N                Input number
    …·                  Inclusive range
   E                    Map with variable `i`
            ¹           Literal 1
             ι          Variable `i`
           …            Exclusive range
          E             Map with variable `l`
                ι       Variable `i`
                 λ      Variable `l`
               ﹪        Modulo
              ⎇         Ternary
                  ⁰     If nonzero then zero
                   λ    If zero then variable `l`
         ⌈              Take the maximum
                    1   Arbitrary character
        ×               Repeat it
  ⪫                  ω  Join the strings together
 L                      Take the length
I                       Cast to string
                        Implicitly print

The Sum function has been added since the question was asked, reducing the code to 18 bytes:

IΣE…·²N⌈E…¹ι⎇﹪ιλ⁰λ

Neil

Posted 2017-06-24T11:17:05.153

Reputation: 95 035

0

R, 53 bytes

function(n){for(i in 2:n)F=F+(y=(i-1):1)[!i%%y][1]
F}

Try it online!

For each integer i in 2...n, computes the divisors of i in decreasing order with (y=(i-1):1)[!i%%y] and then selects the first, as that will be the largest, adding it to F, which is by default initialized to FALSE or 0.

Giuseppe

Posted 2017-06-24T11:17:05.153

Reputation: 21 077