Go back to chapter 2

1 Exercise 1

The series, \(1^{1} + 2^{2} + 3^{3} + ... + 10^{10} = 10405071317\).

Find the last ten digits of the series, \(1^{1} + 2^{2} + 3^{3} + ... + 1000^{1000}\).

1.1 R

# R

1000**1000
## [1] Inf

# To manage very large numbers you have to use gmp
library(gmp)
## 
## Attaching package: 'gmp'
## The following objects are masked from 'package:base':
## 
##     %*%, apply, crossprod, matrix, tcrossprod

sum_n_power_last_digit <- function(n, last_digit){
  sum_series = sum(as.bigz(seq(1, n))**(seq(1, n)))
  sum_n = stringr::str_split(as.character(sum_series),'')[[1]]
  last_digits = sum_n[(length(sum_n)-last_digit+1):length(sum_n)]
  return(last_digits)
}

t = Sys.time()
sum_n_power_last_digit(1000,10)
##  [1] "9" "1" "1" "0" "8" "4" "6" "7" "0" "0"
Sys.time() - t
## Time difference of 0.008686066 secs

1.2 Python

# Python 
import numpy as np
import time

# default numpy dtype may not be appropriate to deal with very large number, python can do it, you can specify to numpy to use it as a python object

np.power(np.arange(1,15),np.arange(1,15))
## array([                1,                 4,                27,
##                      256,              3125,             46656,
##                   823543,          16777216,         387420489,
##              10000000000,      285311670611,     8916100448256,
##          302875106592253, 11112006825558016])
np.power(np.arange(1,15, dtype="object"),np.arange(1,15, dtype="object"))
## array([1, 4, 27, 256, 3125, 46656, 823543, 16777216, 387420489,
##        10000000000, 285311670611, 8916100448256, 302875106592253,
##        11112006825558016], dtype=object)


# In a function with python object
def sum_n_power_last_digit(n,last_digit):
  sum_series = np.sum(np.power(np.arange(1,n+1, dtype="object"),np.arange(1,n+1, dtype="object")))
  last_digits = str(sum_series)[-last_digit:]
  return last_digits

t = time.time()
sum_n_power_last_digit(1000,10)
## '9110846700'
time.time() - t
## 0.0056819915771484375

2 Exercise 2

2.1 Exercise 1

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 10000.

2.1.1 R

get_sum_multiples_below1 <- function(below,multiple_1,multiple_2){
  sum <- 0
  for(i in 1:(below-1)){
    if((i %% multiple_1 == 0)|(i %% multiple_2 == 0)){
      sum <-  sum + i 
    }
  }
  return(sum)
}

t <- Sys.time()
get_sum_multiples_below1(1000000,3,5)
## [1] 233333166668
Sys.time() - t
## Time difference of 0.4065418 secs



get_sum_multiples_below2 <- function(below,multiple_1,multiple_2){
  seq <- seq(1,(below-1))
  multiples <- sapply(seq,FUN = function(x){if((x %% multiple_1 == 0) | (x %% multiple_2 == 0)){x}else{0} })
  return(sum(multiples))
}

t <- Sys.time()
get_sum_multiples_below2(1000000,3,5)
## [1] 233333166668
Sys.time() - t
## Time difference of 1.117711 secs



get_sum_multiples_below3 <- function(below,multiple_1,multiple_2){
  seq <- seq(1,(below-1))
  multiples <- seq[which((seq %% multiple_1 == 0) | (seq %% multiple_2 == 0))]
  return(sum(multiples))
}

t <- Sys.time()
get_sum_multiples_below3(1000000,3,5)
## [1] 233333166668
Sys.time() - t
## Time difference of 0.008708954 secs

2.1.2 Python

import time
import numpy as np

def get_sum_multiples_below1(below,mutiple_1,multiple_2):
  sum = 0
  for i in range(below):
    if (i % mutiple_1 == 0) or (i % multiple_2 == 0):
      sum+= i 
      
  return sum

t = time.time()
get_sum_multiples_below1(1000000,3,5)
## 233333166668
time.time() - t
## 0.025700807571411133


def get_sum_multiples_below2(below,mutiple_1,multiple_2):
  multiples = [i if ((i % mutiple_1 == 0) or (i % multiple_2 == 0)) else 0 for i in range(below)]
  return sum(multiples)

t = time.time()
get_sum_multiples_below2(1000000,3,5)
## 233333166668
time.time() - t
## 0.028688907623291016


def get_sum_multiples_below3(below,mutiple_1,multiple_2):
  seq = list(range(below))
  multiples = map(lambda i: i if ((i % mutiple_1 == 0) or (i % multiple_2 == 0)) else 0, seq) 
  return sum(multiples)

t = time.time()
get_sum_multiples_below3(1000000,3,5)
## 233333166668
time.time() - t
## 0.04091191291809082



def get_sum_multiples_below4(below,mutiple_1,multiple_2):
  seq = np.arange(below)
  seq = seq[((seq % mutiple_1 == 0) | (seq % multiple_2 == 0))]
  return sum(seq)

t = time.time()
get_sum_multiples_below4(1000000,3,5)
## np.int64(233333166668)
time.time() - t
## 0.01642894744873047

2.2 Exercise 2

By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

What is the 10 001st prime number?

2.2.1 R



nth_prime <- function(nth){
  primes = c(2,3)
  i = 3
  while(length(primes)<nth){
    i <- i+1
    is_prime = TRUE
    for(j in 2:(round(sqrt(i))+1)){
      if(i%%j == 0){
        is_prime = FALSE
      }
      if(is_prime == FALSE){
        break
      }
    }
    if(is_prime == TRUE){
      primes = c(primes,i)
    }
  }
  
  return(primes[nth])
}

t <- Sys.time()
nth_prime(10001)
## [1] 104743
Sys.time() - t
## Time difference of 0.7728629 secs


nth_prime2 <- function(nth){
  primes = c(2,3)
  i = 3
  while(length(primes)<nth){
    i <- i+1
    ratio = i%%seq(2,round(sqrt(i))+1) == 0
    if(!any(ratio)){
      primes = c(primes,i)
    }
  }
  return(primes[nth])
}


t <- Sys.time()
nth_prime2(10001)
## [1] 104743
Sys.time() - t
## Time difference of 0.582736 secs

2.2.2 Python

# Python 
import numpy as np


def nth_prime(nth):
  primes = [2,3]
  i = 3
  while len(primes) < nth:
    i+=1 
    is_prime = True
    for j in range(2,(int(np.sqrt(i))+1)):
      if i%j == 0:
        is_prime = False
        break
        
    if is_prime == True:
      primes.append(i)
      
  print(primes[-1])


t = time.time()
nth_prime(10001)
## 104743
time.time() - t
## 0.07397699356079102


def nth_prime2(nth):
  primes = [2,3]
  i = 3
  while len(primes)<nth: 
    i+=1
    ratio = np.mod(i,np.arange(2,int(np.sqrt(i)+1))) == 0
    if not any(ratio):
      primes.append(i)
    
  
  print(primes[nth-1])


t = time.time()
nth_prime2(10001)
## 104743
time.time() - t
## 0.16478991508483887

3 Exercise 3

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.

Find the largest palindrome made from the product of two 3-digit numbers.

3.1 Python

# Python
#
t = time.time()
three_digits = np.arange(100,1000)
products = np.repeat(three_digits, len(three_digits))*np.tile(three_digits,len(three_digits))
palindromes = [x for x in products if str(x)==str(x)[::-1]]
print(max(palindromes))
## 906609
time.time() - t
## 0.08670210838317871

Go back to chapter 2