The Arithmetic Derivative

35

1

The derivative of a function is a cornerstone of mathematics, engineering, physics, biology, chemistry, and a large number of other sciences as well. Today we're going to be calculating something only tangentially related: the arithmetic derivative.

Definition

The arithmetic derivative a(n) or n' is defined here (A003415) by a number of properties that are similar to the derivative of a function.

  • a(0) = a(1) = 0,
  • a(p) = 1, where p is any prime, and
  • a(mn) = m*a(n) + n*a(m).

The third rule is based on the product rule for differentiation of functions: for functions f(x) and g(x), (fg)' = f'g + fg'. So with numbers, (ab)' = a'b + ab'.

Also of note, since the arithmetic derivative can be extended to the negative numbers via this simple relation, a(-n) = -a(n), the input may be negative.

Rules

  • Write a program or function that, given any integer n, returns the arithmetic derivative of n.
  • Inputs will be -230 < n < 230, to avoid problems with integer sizes and numbers too large to factor in a reasonable amount of time. Your algorithm should still be able to theoretically calculate the arithmetic derivative of numbers outside this range.
  • Built-ins for symbolic math, prime factorization and differentiation are allowed.

Examples

> a(1)
0
> a(7)
1
> a(14)   # a(7)*2 + a(2)*7 = 1*2 + 1*7 = 9
9
> a(-5)   # a(-5) = -a(5) = -1
-1
> a(8)    # a(8) = a(2**3) = 3*2**2 = 12
12
> a(225)  # a(225) = a(9)*25 + a(25)*9 = 6*25 + 10*9 = 150 + 90 = 240
240
> a(299792458)  # a(299792458) = a(2)*149896229 + a(7)*42827494 + a(73)*4106746 + a(293339)*1022 = 1*149896229 + 1*42827494 + 1*4106746 + 1*1022 = 149896229 + 42827494 + 4106746 + 1022 = 196831491
196831491

As always, if the problem is unclear, please let me know. Good luck and good golfing!

Sherlock9

Posted 2016-04-03T11:23:22.977

Reputation: 11 664

What, exactly, is prime in a(prime)? Is it just a prime number? – Stackstuck – 2019-04-17T20:03:24.337

Also, I don't get how you decomposed the last example. – Stackstuck – 2019-04-17T20:20:44.467

@Stackstuck Yes, it's any prime. I've edited for clarity. Also, I added to the last example to hopefully make it clearer. – Sherlock9 – 2019-04-18T06:31:56.950

Answers

11

MATL, 12 bytes

|1>?GtYf/s}0

Try it online!

Explanation

Consider an integer a with |a|>1, and let the (possibly repeated) prime factors of |a| be f1, ..., fn. Then the desired result is a·(1/f1 + ... + 1/fn).

|1>     % take input's absolute value. Is it greater than 1?
?       % if so:
  Gt    %   push input twice
  Yf    %   prime factors. For negative input uses its absolute value
  /     %   divide element-wise
  s     %   sum of the array
}       % else:
  0     %   push 0

Luis Mendo

Posted 2016-04-03T11:23:22.977

Reputation: 87 464

Isn't the sum of the prime factors of 1 equal to 0? Or doesn't that work in MATL? – wythagoras – 2016-04-03T14:18:36.963

@wythagoras Actually 1 gives 1 as its "prime" number decomposition. It's a strange result (an empty array would be more meaningful). But that's how Matlab works. And also CJam. So I guess there must be good reason to output 1 in that case? What do you think? I've been tempted to redefine the Yf function to output an empty array for 1, but I wasn't sure – Luis Mendo – 2016-04-03T15:23:18.537

1Pyth gives an empty array, fwiw. – isaacg – 2016-04-05T04:34:38.220

@isaacg Thanks! Maybe I'll change that – Luis Mendo – 2016-04-05T08:35:18.223

Same in Mathematica (was almost a problem once) – CalculatorFeline – 2016-04-08T04:28:46.537

8

Python, 59 bytes

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

A recursive function. On large inputs, it runs out of stack depth on typical systems unless you run it with something like Stackless Python.

The recursive definition is implemented directly, counting up to search for candidate prime factors. Since f(prime)=1, if n has a prime p as a factor, we have f(n) == p*f(n/p)+n/p.

xnor

Posted 2016-04-03T11:23:22.977

Reputation: 115 687

Don't you need input and print? At least when I run this (Python 2), I get no result. – wythagoras – 2016-04-03T18:05:20.893

@wythagoras By default, functions are allowed as an alternative to programs. Also, this challenge says "program or function".

– xnor – 2016-04-03T18:14:01.827

7

Jelly, 8 7 bytes

-1 byte by @Dennis

ÆfḟṠ³:S

Uses the same formula everyone else does. However, there's a little trick to deal with 0.

o¬AÆfİS×     Main link. Inputs: n
o¬             Logical OR of n with its logical NOT
               That is, 0 goes to 1 and everything else goes to itself.
  A            Then take the absolute value
   Æf          get its list of prime factors
     İ         divide 1 by those
      S        sum
       ×       and multiply by the input.

Try it here.

lirtosiast

Posted 2016-04-03T11:23:22.977

Reputation: 20 331

Can you please add an explanation? I like answers to have explanations before I upvote them. – Sherlock9 – 2016-04-03T19:10:03.480

@Sherlock9 Done. – lirtosiast – 2016-04-03T21:51:30.990

I see that your answer has been golfed and the explanation is now out-of-date. Would you please fix that? Thanks :D – Sherlock9 – 2016-04-12T06:01:21.897

5

Python 2, 87 78 76 74 bytes

a=b=input()
d=2
s=0
while d<=abs(b):
    if a%d==0:
        a=a/d
        s+=b/d
    else:
        d+=1
print s

Improvements thanks to @Maltysen:

a=b=input()
d=2
s=0
while d<=abs(b):
    if a%d==0:a/=d;s+=b/d
    else:d+=1
print s

Further improvement by two bytes:

a=b=input()
d=2
s=0
while abs(a)>1:
    if a%d<1:a/=d;s+=b/d
    else:d+=1
print s

Further improvement thanks to @xnor:

a=b=input()
d=2
s=0
while a*a>1:
    if a%d<1:a/=d;s+=b/d
    else:d+=1
print s

Explanation

The arithmetic derivative of a is equal to a times the sum of the reciprocals of the prime factors of a. No exception for 1 is needed since the sum of the reciprocals of the prime factors of 1 is zero.

wythagoras

Posted 2016-04-03T11:23:22.977

Reputation: 175

abs(a)>1 can be a*a>1. – xnor – 2016-04-03T17:22:48.217

@xnor Yes, thank you. – wythagoras – 2016-04-03T17:27:37.407

Replace line 2 with d,s = 2,0 – Agnishom Chattopadhyay – 2016-04-04T12:42:48.277

@AgnishomChattopadhyay Both are 8 bytes in total. – wythagoras – 2016-04-04T15:44:26.173

4

J, 30 27 19 chars

Thanks to @Dennis for chopping off 3 characters.

Thanks to @Zgarb for chopping off 8 characters.

0:`(*[:+/%@q:@|)@.*

Try it online!

Sample input:

0:`(*[:+/%@q:@|)@.* _8
_12

0:`(*[:+/%@q:@|)@.* 0
0

0:`(*[:+/%@q:@|)@.* 8
12

How it works:

0:`(*[:+/%@q:@|)@.* N
XX`YYYYYYYYYYYYY@.Z   if Z then Y else X end
0:                        X:  return 0
                  Z       Z:  signum(N)
   (*[:+/%@q:@|)          Y:  N*add_all(reciprocal_all(all_prime_factors(abs(N))))
                              N
    *                          *
      [:+/                      add_all(                                         )
          %@                            reciprocal_all(                         )
            q:@                                       all_prime_factors(      )
               |                                                        abs( )
                                                                            N

Leaky Nun

Posted 2016-04-03T11:23:22.977

Reputation: 45 011

4

Haskell, 203 90 bytes

Thanks @nimi!

I still have no idea when what indentations cause what interpretation, this is the shortest I managed so far, and as always, I'm sure it can be golfed a lot more. I'm going to try again in the evening.

n#(x:_)|y<-div n x=x*a y+y*a x;_#_=1
a n|n<0= -a(-n)|n<2=0|1<2=n#[i|i<-[2..n-1],mod n i<1]

flawr

Posted 2016-04-03T11:23:22.977

Reputation: 40 560

1Thank you very much, teacher=) I can always learn so much whenever you help me out here! Feel free to add your version as your own answer! – flawr – 2016-04-03T15:35:37.733

3

APL (Dyalog Extended), 13 9 bytes

A simple solution. The Dyalog Unicode version was simply a longer version of this so it has been omitted.

Edit: Saved 4 bytes by adopting the method in lirtosiast's Jelly solution.

{+/⍵÷⍭|⍵}

Try it online!

Ungolfing

{+/⍵÷⍭|⍵}

{        }  A dfn, a function in {} brackets.
     ⍭|⍵   The prime factors of the absolute value of our input.
   ⍵÷      Then divide our input by the above array,
            giving us a list of products for the product rule.
 +/         We sum the above numbers, giving us our arithmetic derivative.

Sherlock9

Posted 2016-04-03T11:23:22.977

Reputation: 11 664

3

Japt -x, 16 13 10 bytes

ÒU©a k £/X

- 6 bytes thanks to @Shaggy

Try it online!

Quintec

Posted 2016-04-03T11:23:22.977

Reputation: 2 801

Both fail for negative numbers because, for some reason, N.k() doesn't work on them. – Shaggy – 2019-02-28T16:54:41.390

Here's a fix, with some golfing. – Shaggy – 2019-02-28T16:58:40.567

Or -2 more byes with the -x flag.

– Shaggy – 2019-02-28T16:59:49.843

Knocked another byte off – Shaggy – 2019-02-28T18:10:45.567

@Shaggy Thanks, nice – Quintec – 2019-02-28T19:26:39.803

11 bytes – Shaggy – 2019-02-28T20:57:07.427

(Or 10, with -x)

– Shaggy – 2019-02-28T22:44:13.993

@Shaggy Ah, nice, still learning! :) Forgot about flags and the fact that summing can take a function, as with many other functions in japt – Quintec – 2019-02-28T23:15:27.713

3

Pyth - 10 8 bytes

Lovin' the implicit input! Should bring it on par with Jelly for most things (Except Dennis' golfing skills).

*scL1P.a

Test Suite.

*             Times the input, implicitly (This also adds the sign back in)
 s            Sum
  cL1         Reciprocal mapped over lit
   P          Prime factorization
    .a        Absolute value of input, implicitly

Maltysen

Posted 2016-04-03T11:23:22.977

Reputation: 25 023

3

Haskell, 59 bytes

n%p|n*n<2=0|mod n p>0=n%(p+1)|r<-div n p=r+p*r%2
(%2)

Implements the recursive definition directly, with an auxiliary variable p that counts up to search for potential prime factors, starting from 2. The last line is the main function, which plugs p=2 to the binary function defined in the first line.

The function checks each case in turn:

  • If n*n<2, then n is one of -1,0,1, and the result is 0.
  • If n is not a multiple of p, then increment p and continue.
  • Otherwise, express n=p*r, and by the "derivative" property, the result is r*a(p)+p*a(r), which simplifies to r+p*a(r) because p is prime.

The last case saves bytes by binding r in a guard, which also avoids the 1>0 for the boilerplate otherwise. If r could be bound earlier, the second condition mod n p>0 could be checked as r*p==n, which is 3 bytes shorter, but I don't see how to do that.

xnor

Posted 2016-04-03T11:23:22.977

Reputation: 115 687

3

Seriously, 17 14 11 12 bytes

My first ever Seriously answer. This answer is based on Luis Mendo's MATL answer and the idea that the arithmetic derivative of a number m is equal to m·(1/p1 + 1/p2 + ... + 1/pn) where p1...pn is every prime factor of n to multiplicity. My addition is to note that, if m = p1e1·p2e2·...·pnen, then a(m) = m·(e1/p1 + e2/p2 + ... + en/pn). Thanks to Mego for golfing and bug fixing help. Try it online!

,;w`i@/`MΣ*l

Ungolfing:

,             get a single input
 ;w           duplicate input and get prime factorization, p_f
               for input [-1..1], this returns [] and is dealt with at the end
   `   `M     map the function inside `` to p_f
    i         pop all elements of p_f[i], the prime and the exponent, to the stack
     @        rotate so that the exponent is at the top of the stack
      /       divide the exponent by the prime
         Σ    sum it all together
          *   multiply this sum with the input
           l  map and multiply do not affect an empty list, so we just take the length, 0
               l is a no-op for a number, so the result is unchanged for all other inputs

Sherlock9

Posted 2016-04-03T11:23:22.977

Reputation: 11 664

2

Ruby, 87 66 80 75 70 68 bytes

This answer is based on Luis Mendo's MATL answer, wythagoras's Python answer, and the idea that the arithmetic derivative of a number m is equal to m·(1/p1 + 1/p2 + ... + 1/pn) where p1...pn is every prime factor of n to multiplicity.

->n{s=0;(2...m=n.abs).map{|d|(m/=d;s+=n/d)while m%d<1};m<2?0:s+0**s}

This function is called in the following way:

> a=->n{s=0;(2...m=n.abs).map{|d|(m/=d;s+=n/d)while m%d<1};m<2?0:s+0**s}
> a[299792458]
196831491

Ungolfing:

def a(n)
  s = 0
  m = n.abs
  (2...m).each do |z|
    while m%d == 0
      m /= d
      s += n / d
    end
  end
  if s == 0
    if n > 1
      s += 1 # if s is 0, either n is prime and the while loop added nothing, so add 1
             # or n.abs < 2, so return 0 anyway
             # 0**s is used in the code because it returns 1 if s == 0 and 0 for all other s
    end
  end
  return s
end

Sherlock9

Posted 2016-04-03T11:23:22.977

Reputation: 11 664

2

Julia, 72 43 bytes

n->n^2>1?sum(p->n÷/(p...),factor(n^2))/2:0

This is an anonymous function that accepts an integer and returns a float. To call it, assign it to a variable.

For an input integer n, if n2 ≤ 1 return 0. Otherwise obtain the prime factorization of n2 as a Dict, then for each prime/exponent pair, divide the prime by its exponent, then divide n by the result. This is just computing n x / p, where p is the prime factor and x is its exponent, which is the same as summing n / p, x times. We sum the resulting array and divide that by 2, since we've summed twice as much as we need. That's due to the fact that we're factoring n2 rather than n. (Doing that is a byte shorter than factoring |n|.)

Saved 29 bytes thanks to Dennis!

Alex A.

Posted 2016-04-03T11:23:22.977

Reputation: 23 761

1

APL(NARS), 35 char, 70 bytes

{1≥a←∣⍵:0⋄1=≢k←πa:×⍵⋄c+m×∇c←⍵÷m←↑k}

test and how to use:

  f←{1≥a←∣⍵:0⋄1=≢k←πa:×⍵⋄c+m×∇c←⍵÷m←↑k}
  f 14
9
  f 8
12
  f 225
240
  f ¯5
¯1
  f 299792458
196831491

I thought that it would not be ok because I don't know if c variable is composed (and not a prime)... But seems ok for the test...

RosLuP

Posted 2016-04-03T11:23:22.977

Reputation: 3 036

1

05AB1E, 7 4 bytes

ÄÒ÷O

Port of @lirtosiast's Jelly answer.

Try it online or verify all test cases.

Explanation:

Ä     # Take the absolute value of the (implicit) input
 Ò    # Get all its prime factors (with duplicates)
  ÷   # Integer divide the (implicit) input by each of these prime factors
   O  # And take the sum (which is output implicitly)

Kevin Cruijssen

Posted 2016-04-03T11:23:22.977

Reputation: 67 575

1

Mathematica 10.0, 39 bytes

Tr[If[#>1,#2/#,0]&@@@FactorInteger@#]#&

feersum

Posted 2016-04-03T11:23:22.977

Reputation: 29 566

1Can you please add an explanation? I like answers to have explanations before I upvote them. – Sherlock9 – 2016-04-04T09:31:49.957

1@Sherlock9 This is a quite uninteresting answer so I don't plan to add one. It's OK if no one upvotes it. – feersum – 2016-04-04T10:24:10.777

Alright, then. Have a good day :) – Sherlock9 – 2016-04-04T10:25:40.417

In the current Mathematica version, FactorInteger@1 yields {1,1}, so the If function is no longer necessary, saving 10 bytes. – Greg Martin – 2016-08-26T05:52:26.470

@GregMartin Seriously? That's even more inconsistent than the value, {{1,1}}, returned by my version ({} is the expected result to me). – feersum – 2016-08-26T06:31:22.443

Sorry, I meant {{1,1}}. Mathematically {} makes more sense, of course ... but I admit that {{1,1}} makes coding a little easier. And FactorInteger[-1] returns {{-1,1}} (maybe that's not a change). – Greg Martin – 2016-08-26T17:15:52.340

@GregMartin I don't understand how an inconsistent behavior would make coding easier... anyway, {{1,1}} is not a different result than when I wrote this answer, so the If must be there for a good reason. – feersum – 2016-08-26T18:39:04.513

1

Jolf, 13 bytes

*jmauΜm)jd/1H

Kudos to the MATL answer for the algorithm! Try it here, or test them all at once. (Outputs [key,out] in an array.)

Explanation

*jmauΜm)jd/1H
*j             input times
      m)j         p.f. of input
     Μ   d/1H      mapped to inverse
    u            sum of
  ma            abs of

Conor O'Brien

Posted 2016-04-03T11:23:22.977

Reputation: 36 228

0

Ink, 183 bytes

==function a(n)
{n<0:
~return-a(-n)
}
{n<2:
~return 0
}
~temp f=t(n,2)
{f:
~return a(n/f)*f+n/f
}
~return 1
==function t(n,i)
{n>1&&n-i:
{n%i:
~return t(n,i+1)
}
~return i
}
~return 0

Try it online!

I refuse to believe this is a good solution, but I can't see a way to improve it either.

Sara J

Posted 2016-04-03T11:23:22.977

Reputation: 2 576

0

Pari/GP, 45 bytes

n->n*vecsum([i[2]/i[1]|i<-factor(n)~,i[1]>0])

Try it online!

alephalpha

Posted 2016-04-03T11:23:22.977

Reputation: 23 988

0

Perl 5, 62 bytes

perl -MMath::Prime::Util=:all -E"map$i+=1/$_,factor abs($j=<>);say$i*$j"

Uses the formula (from OEIS): If n = Product p_i^e_i, a(n) = n * Sum (e_i/p_i).

msh210

Posted 2016-04-03T11:23:22.977

Reputation: 3 094

0

Perl 6, 90

sub A(\n) {0>n??-A(-n)!!(n>1)*{$_??n/$_*A($_)+$_*A n/$_!!1}(first n%%*,2..^n)};say A slurp

This might be a bit slow for large numbers. Replace 2..^n with 2..n.sqrt for longer code but faster computation.

bb94

Posted 2016-04-03T11:23:22.977

Reputation: 1 831