Finding the GCD without looping - R - r

So I'm trying to learn R and using a number of resources including a book called "Discovering Statistics using R" and a bunch of other cool eBooks.
I understand a great method in programming is the Euclid's Algorithm.
Implementing it in a loop can be achieved like this:
gcd(x,y) //assuming x is the largest value
//do
r = x%y;
x = y;
y = r;
//while r != 0;
return x;
After several searches on Google, SO and Youtube refreshing my memory of gcd algorithms, I wasn't able to find one that doesn't use a loop. Even recursive methods seem to use loops.
How can this be achieved in R without the use of loops or if statements?
Thanks in advance.

Using the statement "without loops or the if statement" literally, here is a recursive version that uses ifelse:
gcd <- function(x,y) {
r <- x%%y;
return(ifelse(r, gcd(y, r), y))
}
One might not expect it, but this is actually vectorized:
gcd(c(1000, 10), c(15, 10))
[1] 5 10
A solution using if would not handle vectors of length greater than 1.

Reducing GCD for two integers enables you to compute GCD for any sequence of integers (sorted or not):
gcd2 <- function(a, b) {
if (b == 0) a else Recall(b, a %% b)
}
gcd <- function(...) Reduce(gcd2, c(...))

You can solve it recursively.
euclids <- function(x,y){
theMax = max(x,y)
theMin = min(x,y)
if (theMax == theMin) return (theMax)
else return (euclids(theMin, theMax-theMin))
}

It's easy to do with a couple modulo operations. Sadly, I left my personal gcd code on a different machine (in a galaxy far away) - but you can find the source in either the numbers or pracma packages.
BTW, here's a good way to find existing code: library(sos); ???gcd

Related

How can I create a vector by only using for loop? (vector is specified in the body)

(1,2,2,3,3,3,4,4,4,4,...,n,...,n)
I want to make the above vector by for loop, but not using rep function or the other functions. This may not be good question to ask in stackoverflow, but since I am a newbie for R, I dare ask here to be helped.
(You can suppose the length of the vector is 10)
With a for loop, it can be done with
n <- 10
out <- c()
for(i in seq_len(n)){
for(j in seq_len(i)) {
out <- c(out, i)
}
}
In R, otherwise, this can be done as
rep(seq_len(n), seq_len(n))
I have been beaten by #akrun by seconds, even so I'd like to give you a few hints if using rep would have been possible which may help you with R in general. (Without rep usage, just look at #akrun)
Short answer using rep
rep(1:n, 1:n)
Long Answer using rep
Before posting a question you should try to develop your own solutions and share them.
Trying googling a bit and sharing what you already found is usually good as well. Please, have a look at "help/how-to-ask"
Let's try to do it together.
First of all, we should try to have a look at official sources:
R-project "getting help", here you can see the standard way to get a function's documentation is just typing ?func_name in your R console
R-project "official manuals" offer a good introduction to R. Try looking at the first topic, "An Introduction to R"
From the previous two (and other sources as well) you will find two interesting functions:
: operator: it can be used to generate a sequence of integers from a to b like a:b. Typing 1:3, for instance, gives you the 1, 2, 3 vector
rep(x, t) is a function which can be used to replicate the item(s) x t times.
You also need to know R is "vector-oriented", that is it applies functions over vectors without you typing explicits loops.
For instance, if you call repl(1:3, 2), it's (almost) equivalent to running:
for(i in 1:3)
rep(i, 2)
By combining the previous two functions and the notion R is "vector-oriented", you get the rep(1:n, 1:n) solution.
I am not sure why you don't want to use rep, but here is a method of not using it or any functions similar to rep within the loop.
`for (i in 1:10){
a<-NA
a[1:i] <- i
if (i==1){b<-a}
else if (i >1){b <- c(b,a)}
assign("OutputVector",b,envir = .GlobalEnv)
}`
`OutputVector`
Going for an n of ten seemed subjective so I just did the loop for numbers 1 through 10 and you can take the first 10 numbers in the vector if you want. OutputVector[1:10]
You can do this with a single loop, though it's a while rather than a for
n <- 10
x <- 1;
i <- 2;
while(i <= n)
{
x <- c(x, 1/i);
if(sum(x) %% 1 == 0) i = i + 1;
}
1/x

Which loop to use, R language?

We have to create function(K) that returns vector which has all items smaller than or equal to K from fibonacci sequence. We can assume K is fibonacci item. For example if K is 3 the function would return vector (1,1,2,3).
In general, a for loop is used when you know how many iterations you need to do, and a while loop is used when you want to keep going until a condition is met.
For this case, it sounds like you get an input K and you want to keep going until you find a Fibonacci term > K, so use a while loop.
ans <- function(n) {
x <- c(1,1)
while (length(x) <= n) {
position <- length(x)
new <- x[position] + x[position-1]
x <- c(x,new)
}
return(x[x<=n])
}
`
Tried many different loops, and this is closest I get. It works with every other number but ans(3) gives 1,1,2 even though it should give 1,1,2,3. Couldn't see what is wrong with this.

Codewars R Challenge: for i from 1 to n, do i % m and return the sum | Looking to optimize the code

This is a rather simple question but somehow my code either takes long time or consumes more resource. It is a question asked in www.codewars.com which I use for R Programming practice.
Below are the two versions of the problem I coded:
Version 1 :
f <- function(n, m){
# Your code here
if(n<=0) return(0) else return((n%%m)+f((n-1),m))
}
Version 2:
#Function created to calculate the sum of the first half of the vector
created
calculate_sum <- function(x,y){
sum = 0
for(i in x){
sum = sum + i%%y
}
return(sum)
}
#Main function to be called with a test call
f <- function(n, m){
# Your code here
#Trying to create two vectors from the number to calculate the sum
#separately for each half
if(n%%2==0){
first_half = 1:(n/2)
second_half = ((n/2)+1):n
} else {
first_half = 1:floor(n/2)
second_half = (ceiling(n/2)):n
}
sum_first_half = calculate_sum(first_half,m)
sum_second_half = 0
for(j in second_half){
sum_second_half = sum_second_half+(j%%m)
}
return(sum_first_half+sum_second_half)
}
I am trying to figure out a way to optimize the code. For the first version it gives the following error message:
Error: C stack usage 7971184 is too close to the limit
Execution halted
For the second version it says my code took more than 7000 ms and hence was killed.
Can someone give me a few pointers on how to optimize the code in R??
The optimisation is mathematical, not programmatical (though as others have mentioned, loops are slow in R.)
Firstly, note that sum(0:(m-1)) = m*(m-1)/2.
You are being asked to calculate this n%/%m times, and add a remainder of (n - n%/%m)(n - n%/%m + 1)/2. So you might try
f <- function(n,m){
k <- n%/%m
r <- n - k*m
return(k*m*(m-1)/2 + r*(r+1)/2)
}
which is a much less complex calculation, and will not take very long regardless of how large n or m is.
There is a risk that, if n is greater than 2^53 and m does not have enough powers of 2 in its factorisation, there will not be enough precision to calculate k and r accurately enough.
EDIT: Just Realized it is actually a trick question
I would do
n%/%m *sum(1:(m-1)) + sum( 0:(n%%m))
Loop are real slow in R. Also, from my experience recursive function in R doesnt help much with the speed and it takes lots of memory

Repeat codeline in R

How can I repeat a code-line in R?
I have created a function called 'func1' and I want ‘data’ to run though ‘func1’ 10 times after another
This is what I have now:
data<-func1(data);data<-func1(data);data<-func1(data);data<-func1(data);data<-func1(data);data<-func1(data)
data<-func1(data);data<-func1(data);data<-func1(data);data<-func1(data)
This is what I would like to have:
solution
data<-func1(data,times=10)
Thanks in advance
Jannik
A simple loop would do this,
for(i in 1:10) {
data <- func1(data)
}
You can write a higher-order function which, given a function, f, a seed value, s, and an integer n, computes
f(f(f( ....(s))...)
(with n function evalutions):
iterate <- function(f,s,n){
if(n == 0){
s
}
else{
f(iterate(f,s,n-1))
}
}
Then you seem to want data <- iterate(func1,data,10)
You can also write iterate using a loop (in a way which is similar to the excellent answer of #JamesElderfield ) but the recursive approach given above is fairly common in the functional programming paradigm (which is one of R's native paradigms).

intToBin with large numbers

I'm using the intToBin() function from "R.utils" package and am having trouble using it to convert large decimal numbers to binary.
I get this error : NAs introduced by coercion.
Is there another function out there that can handle big numbers/ is there an algorithm/ code to implement such a function?
Thanks
If you read the help page for intToBin, it quite explicitly says it takes "integer" inputs. These are not mathematical "integers" but rather the computer-language-defined ints, which are limited to 16 bits (or something like that).
You'll need to find (or write :-() a function which converts floating-point numbers to binary floats, or if you're lucky, perhaps Rmpfr or gmp packages, which do arbitrary precision "big number" math, may have a float-to-binary tool.
By the time this gets posted, someone will have exposed my ignorance by posting an existing function, w/ my luck.
Edit -- like maybe the package pack
I needed a converter between doubles and hex numbers. So I wrote those, might be helpful to others
doubleToHex <- function(x) {
if(x < 16)
return(sprintf("%X", x))
remainders <- c()
while(x > 15) {
remainders <- append(remainders, x%%16)
x <- floor(x/16)
}
remainders <- paste(sprintf("%X", rev(remainders)), collapse="")
return(paste(x, remainders, sep=""))
}
hexToDouble <- function(x) {
x <- strsplit(x,"")[[1]]
output <- as.double(0)
for(i in rev(seq_along(x))) {
output <- output + (as.numeric(as.hexmode(x[i]) * (16**(length(x)-i))))
}
return(output)
}
doubleToHex(x = 8356723)
hexToDouble(x = "7F8373")
Hasn't been extensively tested yet, let me know if you detect a problem with it.

Resources