How is the following for loop working? - r

I am doing this in R. Though there is a shortcut way to do the following in R, I want to check it out:
x <- c(7,6,8,7)
y <- 1
n <- length(x)
p=1
s = 0
for(i in 1:n){
s = s + (x^p * y^p)
}
s
Since I have not specified the index number of x in the for loop, I guessed that only the first element of x will be used. So I made a table:
i s= s + (x^p * y^p)
1 s= 0 + (7^1 * 1^1)=7
2 s= 7 + (7^1 * 1^1)=14
3 s= 14 + (7^1 * 1^1)=21
4 s= 21 + (7^1 * 1^1)=28
But the result was:
s
[1] 28 24 32 28
I couldn't match this result in any way. How does it work?

x is not a single integer, but a vector of integers. You need to subset your x the way god intended. When you specify x, R doesn't use just the first element, but all of them. This is the assumption that is clouding your solution.
x <- c(7,6,8,7)
y <- 1
n <- length(x)
p <- 1
s <- 0
for(i in 1:n){
s <- s + (x[1]^p * y^p)
message(s)
}
7
14
21
28

Related

Using for-loop to fill vector in R

I'm simplifying this question, for clarity.
Say I want to create a vector with a number of elements with the value zero. I then want to use a for-loop to replace every element with its own index number inside the vector.
Can this be done?
K <- 11
p <- rep(0, K + 1)
for (k in 0:K) {
p[k+1] <- .... ?
}
Here's one solution if I understand your expected output:
K <- 11
p <- rep(0, K + 1)
for (k in 0:K) {
p[k + 1] <- k
}
Which returns:
[1] 0 1 2 3 4 5 6 7 8 9 10 11

Create Looping with Customize numbers in R

i want to create an optimal script about 3 parameters in R. These parameters are: n = long of looping, x = any first number, y = any second number. Here the examples:
We can use rep to repeat x and y, n times.
x <- 13
y <- 10
n <- 2
rep(c(x, y), n)
#[1] 13 10 13 10
Using for loop :
vector <- integer(2 * n)
for (i in seq_len(n)) {
vector[c(2 * i -1, 2 * i)] <- c(x, y)
}
vector
#[1] 13 10 13 10

How to generate random integers in R so that no two consecutive numbers are the same

Is there a method to generate random integers in R such that any two consecutive numbers are different? It is probably along the lines of x[k+1] != x[k] but I can't work out how to put it all together.
Not sure if there is a function available for that. Maybe this function can do what you want:
# n = number of elements
# sample_from = draw random numbers from this range
random_non_consecutive <- function(n=10,sample_from = seq(1,5))
{
y=c()
while(length(y)!=n)
{
y= c(y,sample(sample_from,n-length(y),replace=T))
y=y[!c(FALSE, diff(y) == 0)]
}
return(y)
}
Example:
random_non_consecutive(20,c(2,4,6,8))
[1] 6 4 6 2 6 4 2 8 4 2 6 2 8 2 8 2 8 4 8 6
Hope this helps.
The function above has a long worst-case runtime. We can keep that worst-case more constant with for example the following implementation:
# n = number of elements
# sample_from = draw random numbers from this range
random_non_consecutive <- function(n=10,sample_from = seq(1,5))
{
y= rep(NA, n)
prev=-1 # change this if -1 is in your range, to e.g. max(sample_from)+1
for(i in seq(n)){
y[i]=sample(setdiff(sample_from,prev),1)
prev = y[i]
}
return(y)
}
Another approach is to over-sample and remove the disqualifying ones as follows:
# assumptions
n <- 5 # population size
sample_size <- 1000
# answer
mu <- sample_size * 1/n
vr <- sample_size * 1/n * (1 - 1/n)
addl_draws <- round(mu + vr, 0)
index <- seq(1:n)
sample_index <- sample(index, sample_size + addl_draws, replace = TRUE)
qualified_sample_index <- sample_index[which(diff(sample_index) != 0)]
qualified_sample_index <- qualified_sample_index[1:sample_size]
# In the very unlikely event the number of qualified samples < sample size,
# NA's will fill the vector. This will print those N/A's
print(which(is.na(qualified_sample_index) == TRUE))

Number of comparisons in mergesort in R

i am writing a merge sort in R. I have 2 functions. The first is mergelist()
mergelist <- function(a, b)
{
al <- length(a$data)
bl <- length(b$data)
r <- numeric(al + bl)
numberOfComparisions <-0
ai <- 1
bi <- 1
j <- 1
while((ai <= al) && (bi <= bl))
{
if(a$data[ai]<b$data[bi])
{
r[j] <- a$data[ai]
ai <- ai + 1
numberOfComparisions = numberOfComparisions + 1
}
else
{
r[j] <- b$data[bi]
bi <- bi + 1
numberOfComparisions = numberOfComparisions + 1
}
j <- j + 1
}
if(ai<=al)
r[j:(al+bl)] <- a$data[ai:al]
else if(bi <= bl)
r[j:(al+bl)] <- b$data[bi:bl]
returnList <- list(number=numberOfComparisions + a$number + b$number , data = r)
return(returnList)
}
This methods takes in 2 sorted lists as parameter a and b and returns a sorted list with the number attribute of the list telling me how many comparisions there have been made.
I also have this method mergesort()
mergesort <- function(x)
{
l <- length(x)
if(l > 1) {
p <- ceiling(1/2)
a <- mergesort(x[1:p])
b <- mergesort(x[(p+1):l])
return(mergelist(a,b))
}
lister <- list(number=0, data = x)
return(lister)
}
Which takes in a vector x and sorts it. It is returning a list just like mergelist() with the number attribute being the same as in mergelist.
Now my problem is that i have following example: mergesort(c(11,10,9,15,6,12,17,8,19,7)) ,
Which should return
$number [1] 22
$data [1] 6 7 8 9 10 11 12 15 17 19
But it returns
$number
[1] 30
$data
[1] 6 7 8 9 10 11 12 15 17 19
So this means it counts a comparision where it shouldn´t. I don´t know where. Can somebody tell me what i am doing wrong?
Shouldn't your code
p <- ceiling(**1**/2)
be like this
p <- ceiling(**l**/2)

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:
x gets value 0
i gets value 1
while object i's value (not the index #) is < 1000
if is divisible by 3 or 5
add that number i to the vector x
add 1 to i in order (in order to keep the loop going to defined limit of 1e3
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?
First, your loop runs until i < 100, not i < 1000.
Second, replace x[i] <- c(x, i) with x <- c(x, i) to add an element to the vector.
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
And another way:
x <- 1:999
sum(which(x%%5==0 | x%%3==0))
# [1] 233168
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])
Here is an alternative that I think gives the same answer (using 99 instead of 999 as the upper bound):
iters <- 100
x <- rep(0, iters-1)
i <- 1
while (i < iters) {
if (i %% 3 == 0 | i %% 5 == 0) {
x[i] <- i
}
i <- i + 1
}
sum(x)
# [1] 2318
Here is the for-loop mentioned in the original post:
iters <- 99
x <- rep(0, iters)
i <- 1
for (i in 1:iters) {
if (i %% 3 == 0 | i %% 5 == 0) {
x[i] <- i
}
i <- i + 1
}
sum(x)
# [1] 2318

Resources