Sum the powers that be

35

3

A simple but hopefully not quite trivial challenge:

Write a program or function that adds up the kth powers dividing a number n. More specifically:

  • Input: two positive integers n and k (or an ordered pair of integers, etc.)
  • Output: the sum of all of the positive divisors of n that are kth powers of integers

For example, 11! = 39916800 has six divisors that are cubes, namely 1, 8, 27, 64, 216, and 1728. Therefore given inputs 39916800 and 3, the program should return their sum, 2044.

Other test cases:

{40320, 1} -> 159120
{40320, 2} -> 850
{40320, 3} -> 73
{40320, 4} -> 17
{40320, 5} -> 33
{40320, 6} -> 65
{40320, 7} -> 129
{40320, 8} -> 1
{46656, 1} -> 138811
{46656, 2} -> 69700
{46656, 3} -> 55261
{46656, 4} -> 1394
{46656, 5} -> 8052
{46656, 6} -> 47450
{46656, 7} -> 1
{1, [any positive integer]} -> 1

This is code golf, so the shorter your code, the better. I welcome golfed code in all kinds of different languages, even if some other language can get away with fewer bytes than yours.

Greg Martin

Posted 2017-02-10T09:00:40.570

Reputation: 13 940

12When I first saw your challenge, I had the weird feeling that it was a Metallica song title. – Arnauld – 2017-02-10T14:54:15.580

1What? There's no Mathematica built-in for this? – boboquack – 2017-02-10T22:47:13.943

Answers

13

05AB1E, 9 bytes

DLImDŠÖÏO

Try it online!

Explanation

Example input 46656, 3

D          # duplicate first input
           # STACK: 46656, 46656
 L         # range [1 ... first input]
           # STACK: 46656, [1 ... 46656]
  Im       # each to the power of second input
           # STACK: 46656, [1, 8, 27 ...]
    D      # duplicate
           # STACK: 46656, [1, 8, 27 ...], [1, 8, 27 ...]
     Š     # move down 2 spots on the stack
           # STACK: [1, 8, 27 ...], 46656, [1, 8, 27 ...]
      Ö    # a mod b == 0
           # STACK: [1, 8, 27 ...], [1,1,1,1,0 ...]
       Ï   # keep only items from first list which are true in second
           # STACK: [1, 8, 27, 64, 216, 729, 1728, 5832, 46656]
        O  # sum
           # OUTPUT: 55261

Emigna

Posted 2017-02-10T09:00:40.570

Reputation: 50 798

6

Mathematica, 28 bytes

Tr[Divisors@#⋂Range@#^#2]&

Unnamed function taking n and k as inputs in that order.

Martin Ender

Posted 2017-02-10T09:00:40.570

Reputation: 184 808

2DivisorSum is frustratingly close to being useful here. – ngenisis – 2017-02-10T19:24:47.140

5

Python 2, 54 52 bytes

lambda x,n:sum(i**n*(x%i**n<1)for i in range(1,-~x))

Thanks @Rod for cutting off 2 bytes.

hashcode55

Posted 2017-02-10T09:00:40.570

Reputation: 581

You can replace x%i**n==0 with x%i**n<1, and move to the other side as i**n*(x%i**n<1) – Rod – 2017-02-10T12:05:18.860

5

Haskell, 37 35 34 bytes

n!k=sum[x^k|x<-[1..n],n`mod`x^k<1]

Try it online! Usage:

Prelude> 40320 ! 1
159120

The code is quite inefficient because it always computes 1^k, 2^k, ..., n^k.

Edit: Saved one byte thanks to Zgarb.

Explanation:

n!k=             -- given n and k, the function ! returns
 sum[x^k|        -- the sum of the list of all x^k
   x<-[1..n],    -- where x is drawn from the range 1 to n
   n`mod`x^k<1]  -- and n modulus x^k is less than 1, that is x^k divides n

Laikoni

Posted 2017-02-10T09:00:40.570

Reputation: 23 676

1mod n(x^k) can be n\mod`x^k`. – Zgarb – 2017-02-10T14:08:13.307

4

Ruby, 45 bytes

->n,m{(1..n).reduce{|a,b|n%(c=b**m)<1?a+c:a}}

Would be shorter using "sum" in Ruby 2.4. Time to upgrade?

G B

Posted 2017-02-10T09:00:40.570

Reputation: 11 099

4Time to upgrade. – Yytsi – 2017-02-10T10:34:45.337

4

MATL, 10 bytes

t:i^\~5M*s

Try it online!

How it works

Example with 46656, 6.

t      % Implicitly input n. Duplicate
       % STACK: 46656, 46656
:      % Range
       % STACK: 46656, [1 2 ... 46656]
i      % Input k
       % STACK: 46656, [1 2 ... 46656], 6
^      % Power, element-wise
       % STACK: 46656, [1 64 ... 46656^6]
\      % Modulo
       % STACK: [0 0 0 1600 ...]
~      % Logically negate
       % STACK: [true true true false ...]
5M     % Push second input to function \ again
       % STACK: [true true true false ...], [1^6 2^6 ... 46656^6]
*      % Multiply, element-wise
       % STACK: [1 64 729 0 ...]
s      % Sum of array: 47450
       % Implicitly display

Luis Mendo

Posted 2017-02-10T09:00:40.570

Reputation: 87 464

4

Jelly, 7 6 bytes

-1 byte thanks to Dennis (traverse an implicit range)
A clever efficiency save also by Dennis at 0-byte cost
(Previously ÆDf*€S would filter keep those divisors that are a power of k of any natural number up to n. But note that n can only ever have a divisor of ik if it has a divisor of i anyway!)

ÆDf*¥S

Try it online!

How?

ÆDf*¥S - Main link: n, k
ÆD     - divisors of n  -> divisors = [1, d1, d2, ..., n]
    ¥  - last two links as a dyadic chain
  f    -     filter divisors keeping those that appear in:
   *   -     exponentiate k with base divisors (vectorises)
       - i.e. [v for v in [1, d1, d2, ..., n] if v in [1^k, d1^k, ..., n^k]]
     S - sum

Jonathan Allan

Posted 2017-02-10T09:00:40.570

Reputation: 67 804

3

JavaScript (ES7), 56 53 bytes

Takes n and k in currying syntax (n)(k).

n=>k=>[...Array(n)].reduce(p=>n%(a=++i**k)?p:p+a,i=0)

Test cases

let f =

n=>k=>[...Array(n)].reduce(p=>n%(a=++i**k)?p:p+a,i=0)

console.log(f(40320)(1)) // -> 159120
console.log(f(40320)(2)) // -> 850
console.log(f(40320)(3)) // -> 73
console.log(f(40320)(4)) // -> 17
console.log(f(40320)(5)) // -> 33
console.log(f(40320)(6)) // -> 65
console.log(f(40320)(7)) // -> 129
console.log(f(40320)(8)) // -> 1
console.log(f(46656)(1)) // -> 138811
console.log(f(46656)(2)) // -> 69700
console.log(f(46656)(3)) // -> 55261
console.log(f(46656)(4)) // -> 1394
console.log(f(46656)(5)) // -> 8052
console.log(f(46656)(6)) // -> 47450
console.log(f(46656)(7)) // -> 1

Arnauld

Posted 2017-02-10T09:00:40.570

Reputation: 111 334

3

Perl 6, 39 bytes

->\n,\k{sum grep n%%*,({++$**k}...*>n)}

How it works

->\n,\k{                              }  # A lambda taking two arguments.
                        ++$              # Increment an anonymous counter
                           **k           # and raise it to the power k,
                       {      }...       # generate a list by repeatedly doing that,
                                  *>n    # until we reach a value greater than n.
            grep n%%*,(              )   # Filter factors of n from the list.
        sum                              # Return their sum.

Try it

smls

Posted 2017-02-10T09:00:40.570

Reputation: 4 352

2

Japt, 10 bytes

Saved lots of bytes thanks to @ETHproductions

òpV f!vU x

Explanation

òpV f!vU x
ò           // Creates a range from 0 to U
 pV         // Raises each item to the power of V (Second input)
    f       // Selects all items Z where
     !vU    //   U is divisible by Z
            //   (fvU would mean Z is divisible by U; ! swaps the arguments)
         x  // Returns the sum of all remaining items

Test it online!

Oliver

Posted 2017-02-10T09:00:40.570

Reputation: 7 160

Does vU detect numbers divisible by U, or numbers that divide U? – Greg Martin – 2017-02-10T18:43:45.117

@GregMartin fvU filters to items that are divisible by U; f!vU filters to items that U is divisible by. ! swaps the arguments. – Oliver – 2017-02-10T18:47:45.790

Cool, so the code looks right, but the explanation might need to be tweaked. – Greg Martin – 2017-02-10T18:53:06.043

@GregMartin Should be clearer now. – ETHproductions – 2017-02-10T18:55:55.973

2

Scala 63 bytes

(n:Int,k:Int)=>1 to n map{Math.pow(_,k).toInt}filter{n%_==0}sum

jaxad0127

Posted 2017-02-10T09:00:40.570

Reputation: 281

2

Python 2, 50 bytes

f=lambda n,k,i=1:n/i and(n%i**k<1)*i**k+f(n,k,i+1)

Try it online! Large inputs may exceed the recursion depth depending on your system and implementation.

xnor

Posted 2017-02-10T09:00:40.570

Reputation: 115 687

2

JavaScript (ES7), 49 46 bytes

n=>g=(k,t=i=0,p=++i**k)=>p>n?t:g(k,t+p*!(n%p))

Neil

Posted 2017-02-10T09:00:40.570

Reputation: 95 035

Since you aren't recursing, why not n=>k=>? +1. – Yytsi – 2017-02-12T09:51:34.693

@TuukkaX I came up with something better. (I actually had this earlier with i as a local, which costs 4 extra bytes, and forgot that I could abuse i in the same way that I did with my other formulation.) – Neil – 2017-02-12T10:17:05.957

1

PHP, 86 bytes

$n=$argv[1];$k=$argv[2];for($i=1;$i<=$n**(1/$k);$i++)if($n%$i**$k<1)$s+=$i**$k;echo$s;

Try it here !

Breakdown :

$n=$argv[1];$k=$argv[2];       # Assign variables from input
for($i=1;$i<=$n**(1/$k);$i++)  # While i is between 1 AND kth root of n
    if($n%$i**$k<1)            #     if i^k is a divisor of n
        $s+=$i**$k;            #         then add to s
echo$s;                        # echo s (duh!)

roberto06

Posted 2017-02-10T09:00:40.570

Reputation: 351

golfed, but not tested: for(;$x<$n=$argv[1];)$n%($x=++$i**$argv[2])?:$s+=$x;echo$s; 59 bytes; requires PHP 5.6 or later. – Titus – 2017-02-12T15:05:37.570

1

CJam, 20 bytes

Probably not optimally golfed, but I don't see any obvious changes to make...

ri:N,:)rif#{N\%!},:+

Try it online!

Business Cat

Posted 2017-02-10T09:00:40.570

Reputation: 8 927

1

Jelly, 8 bytes

R*³%$ÐḟS

Try it online!

(Credit not mine.)

Erik the Outgolfer

Posted 2017-02-10T09:00:40.570

Reputation: 38 134

1

Bash + Unix utilities, 44 bytes

bc<<<`seq "-fx=%.f^$2;s+=($1%%x==0)*x;" $1`s

Try it online!

Test runs:

for x in '40320 1' '40320 2' '40320 3' '40320 4' '40320 5' '40320 6' '40320 7' '40320 8' '46656 1' '46656 2' '46656 3' '46656 4' '46656 5' '46656 6' '46656 7' '1 1' '1 2' '1 3' '1 12' ; do echo -n "$x "; ./sumpowerdivisors $x; done

40320 1 159120
40320 2 850
40320 3 73
40320 4 17
40320 5 33
40320 6 65
40320 7 129
40320 8 1
46656 1 138811
46656 2 69700
46656 3 55261
46656 4 1394
46656 5 8052
46656 6 47450
46656 7 1
1 1 1
1 2 1
1 3 1
1 12 1

Mitchell Spector

Posted 2017-02-10T09:00:40.570

Reputation: 3 392

1

Python, 56 bytes

lambda n,k:sum(j*(j**k**-1%1==n%j)for j in range(1,n+1))

Try it online!

Fairly straightforward. The only noteworthy thing is that j**k**-1%1 always returns a float in [0,1) while n%j always returns a non-negative integer, so they can only be equal if both are 0.

Dennis

Posted 2017-02-10T09:00:40.570

Reputation: 196 637

1

Batch, 138 bytes

@set s=n
@for /l %%i in (2,1,%2)do @call set s=%%s%%*n
@set/at=n=0
:l
@set/an+=1,p=%s%,t+=p*!(%1%%p)
@if %p% lss %1 goto l
@echo %t%

Since Batch doesn't have a power operator, I'm abusing set/a as a form of eval. Very slow when k=1. 32-bit integer arithmetic limits the supported values of n and k:

           n   k
  (too slow)   1
 <1366041600   2
 <1833767424   3
 <2019963136   4
 <2073071593   5
 <1838265625   6
 <1801088541   7
 <1475789056   8
 <1000000000   9
 <1073741824  10
 <1977326743  11
  <244140625  12
 <1220703125  13
  <268435456  14
 <1073741824  15
   <43046721  16
  <129140163  17
  <387420489  18
 <1162261467  19
    <1048576  20
           ...
 <1073741824  30

Neil

Posted 2017-02-10T09:00:40.570

Reputation: 95 035

0

R, 28 bytes direct, 43 bytes for function

if n,k in memory:

sum((n%%(1:n)^k==0)*(1:n)^k)

for a function:

r=function(n,k)sum((n%%(1:n)^k==0)*(1:n)^k)

Zahiro Mor

Posted 2017-02-10T09:00:40.570

Reputation: 371