Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Euler Project #1 in R

Problem

Find the sum of all numbers below 1000 that can be divisible by 3 or 5

One solution I created:

x <- c(1:999)
values <- x[x %% 3 == 0 | x %% 5 == 0]
sum(values

Second solution I can't get to work and need help with. I've pasted it below. I'm trying to use a loop (here, I use while() and after this I'll try for()). I am still struggling with keeping references to indexes (locations in a vector) separate from values/observations within vectors. Loops seem to make it more challenging for me to distinguish the two.

Why does this not produce the answer to Euler #1?

x <- 0
i <- 1
while (i < 100) {
  if (i %% 3 == 0 | i %% 5 == 0) {
    x[i] <- c(x, i)
  }  
  i <- i + 1
}
sum(x)

And in words, line by line this is what I understand is happening:

  1. x gets value 0
  2. i gets value 1
  3. while object i's value (not the index #) is < 1000
  4. if is divisible by 3 or 5
  5. add that number i to the vector x
  6. add 1 to i in order (in order to keep the loop going to defined limit of 1e3
  7. sum all items in vector x

I am guessing x[i] <- c(x, i) is not the right way to add an element to vector x. How do I fix this and what else is not accurate?

like image 754
jmo Avatar asked Feb 10 '14 20:02

jmo


People also ask

Is Project Euler easy?

Thousands of people have completed the first 100 Project Euler problems over the years. It's just brutally hard.

Does Project Euler show solutions?

Projecteuler-solutions provides merely a list of answers -- that is, it does not provide solutions or code for individual problems. The link to the list of answers can be found at the top of this page.

What language does Project Euler use?

For example, most Project Euler problems are solved in Java most efficiently by using the features of Java that map 1:1 to features in C. You could do pretty much the entire suite of problems without even understanding the motivation of a language like Java.


3 Answers

A very efficient approach is the following:

div_sum <- function(x, n) {
  # calculates the double of the sum of all integers from 1 to n 
  # that are divisible by x
  max_num <- n %/% x
  (x * (max_num + 1) * max_num)      
}

n <- 999
a <- 3
b <- 5

(div_sum(a, n) + div_sum(b, n) - div_sum(a * b, n)) / 2

In contrast, a very short code is the following:

x=1:999
sum(x[!x%%3|!x%%5])
like image 156
Sven Hohenstein Avatar answered Oct 17 '22 11:10

Sven Hohenstein


Here is a shortcut that performs this sum, which is probably more in the spirit of the problem:

3*(333*334/2) + 5*(199*200/2) - 15*(66*67/2)
## [1] 233168

Here's why this works:

In the set of integers [1,999] there are:

333 values that are divisible by 3. Their sum is 3*sum(1:333) or 3*(333*334/2).

199 values that are divisible by 5. Their sum is 5*sum(1:199) or 5*(199*200/2).

Adding these up gives a number that is too high by their intersection, which are the values that are divisible by 15. There are 66 such values, and their sum is 15*(1:66) or 15*(66*67/2)

As a function of N, this can be written:

f <- function(N) {
  threes <- floor(N/3)
  fives  <- floor(N/5)
  fifteens <- floor(N/15)

  3*(threes*(threes+1)/2) +  5*(fives*(fives+1)/2) - 15*(fifteens*(fifteens+1)/2)
}

Giving:

f(999)
## [1] 233168
f(99)
## [1] 2318
like image 37
Matthew Lundberg Avatar answered Oct 17 '22 11:10

Matthew Lundberg


And another way:

x <- 1:999
sum(which(x%%5==0 | x%%3==0))
# [1] 233168
like image 1
jlhoward Avatar answered Oct 17 '22 10:10

jlhoward