Input in R to calculate factorial of a number - r

I am trying to write a program that will ask the user for an integer and calculate the integer's factorial and the program will end if the user gives a negative number. I get an
Error in while (x >= 0) { : missing value where TRUE/FALSE
needed and sometimes this
Error in x + 1 : non-numeric argument to binary operator
My code:
x <-readline(prompt="Enter an integer: ")
x <- as.integer(x)
while(x >= 0)
{
y <- factorial(x)
y
x <-readline(prompt="Enter an integer: ")
x <- as.integer(x)
}

Your code will work if you put everything inside a function. I improved your code and created a function myfun.
myfun <- function()
{
z <- TRUE
while( z )
{
x <- readline( prompt="Enter an integer: " )
if ( x < 1 ) {
z <- FALSE
} else {
y <- factorial( as.numeric( x ) )
print( y )
}
}
}
myfun()
# Enter an integer: 1
# [1] 1
# Enter an integer: 5
# [1] 120
# Enter an integer: -1
# >

Related

R function using a 'for' loop that returns a list with number of uppercase, lowercase and numeric values in a string

I am trying to learn how to write a function 'f' that takes an input string 's' and returns a named list with 3 components (the number of [0, 9] digits, of small and capital letters in s).
My answer must include a 'for' loop and to check my answer, The output of str(f3("123abA")) is:
# List of 3
# $ num: num 3
# $ l : num 2
# $ L : num 1
I did find a way to do it, but without including a 'for' loop. I know it may seem trivial to some people, but I'm just starting out and still need to develop skills using loops in R :)
f3 <- function(s){
number <- str_count(s, "[0-9]")
lower <- str_count(s, "[a-z]")
upper <- str_count(s, "[A-Z]")
return(list(num = as.numeric(number), l = as.numeric(lower), L = as.numeric(upper)))
}
Do you have an idea to help me? Thanks
To expressly ask for a for loop when there are known vectorized solutions is not very R-like but here it goes.
f4 <- function(s){
x <- unlist(strsplit(as.character(s), ""))
number <- 0L
lower <- 0L
upper <- 0L
not_valid <- 0L
for(y in x){
if("0" <= y & y <= "9"){
number <- number + 1L
} else if("A" <= y & y <= "Z"){
upper <- upper + 1L
} else if("a" <= y & y <= "z"){
lower <- lower + 1L
} else {
not_valid <- not_valid + 1L
}
}
if(not_valid){
msg <- paste("There are", not_valid, "invalid characters in input string.")
warning(msg)
}
list(
number = number,
lower = lower,
upper = upper
)
}
str(f4("123abA"))
#List of 3
# $ number: int 3
# $ lower : int 1
# $ upper : int 2
str(f4("123ab.A"))
#List of 3
# $ number: int 3
# $ lower : int 1
# $ upper : int 2
#Warning message:
#In f4("123ab.A") : There are 1 invalid characters in input string.
That is quite a weird assignment, as your current solution is quite good and efficient.
This would be a less efficient answer, but is does have a for loop:
f3 <- function(x){
y <- strsplit(x, "")[[1]]
vec_number <- c()
vec_lower <- c()
vec_upper <- c()
for(i in 1:length(y)){
vec_number[i] <- grepl("[0-9]", y[i])
vec_lower[i] <- grepl("[a-z]", y[i])
vec_upper[i] <- grepl("[A-Z]", y[i])
}
return(list(num = sum(vec_number), l = sum(vec_lower), L = sum(vec_upper)))
}
> str(f3("123abA"))
List of 3
$ num: int 3
$ l : int 2
$ L : int 1

How does a break function in the inner loop in R?

while (statement 1){
......
......
if (statement 2){
x <- x + 1
break
}
if (statement 3){
y <- y + 1
}
}
I have a pseudocode as shown above, I want to verify my understanding whether is correct or not. Is it when the statement 2 is fulfilled, the equation in the 1st if loop will still run, then it will break the if loopand never come back again even the while loop still continue going on?
I am seeking an explanation about the break function in this scenario.
In short, break stops the loop at the exact position you write it without running any of the following code. You can test this by writing some easy statements and defining x and y. message is a useful function here as you can verify which part of the code still runs.
x <- 1
y <- 1
while (x < 100){
if (x == 1){
x <- x + 1
break
}
message(x)
if (y < 100){
y <- y + 1
}
message(y)
}
In this example, the first run is already interrupted as x == 1 is true from the beginning. You will notice that no message is printed but the value for x is 2 now.
In the second example, I made up a statement which will become true after a few iterations. Messages with the value of x and y are now printed for each iteration but once y > 10 nothing is printed and the loop stops immediately.
x <- 1
y <- 1
while (x < 100){
if (y > 10){
x <- x + 1
break
}
message(x)
if (y < 100){
y <- y + 1
}
message(y)
}
The difference of break in comparison to stop for example is that it will only interrupt the inner-most loop (and that stop prints a stop/error message). Meaning that if your code sits in another loop, that outer loop will continue. For example:
for (x in 1:10) {
y <- 1
while (x < 100){
if (y > 10){
x <- x + 1
break
}
message(x)
if (y < 100){
y <- y + 1
}
message(y)
}
}
You can verify how it works with this simple example :
num <- 2
x <- 0
y<- 0
while (TRUE){
if (num %% 10 == 0){
cat('\nprinting from 1: ', num)
x <- x + 1
break
}
if (num %% 2 == 0){
cat('\nprinting from 2: ', num)
y <- y+ 1
}
num <- num + 1
}
#printing from 2: 2
#printing from 2: 4
#printing from 2: 6
#printing from 2: 8
#printing from 1: 10
x
#[1] 1
y
#[1] 4
while(TRUE) makes it run for an infinite time. Every time num is divisible by 2 y is incremented and when num is divisible by 10 it increments y and the while loop breaks.

"no function to return from, jumping to top level"

Could someone help me, I do not understand what is the problem here. I just started learning R (a few days ago). Here I have to construct a function that will give me all Marsenne primes after I created Marsenne numbers. There are 3 functions that I created:
1) factorlist simply find all the factors of a number
2) Marsenne number is a function that creates Marsenne numbers
3) CheckForMersennePrimes is a function that checks whether founded Mersenne numbers are prime or not.
***function "primes" gives all prime numers that are in interval from 0 to x
The problem is:
First 2 functions works perfectly. But third one does not work and gives the following below mistake. I cannot understand what is wrong at all. What I tried to do is since Mersenne numbers not all prime, I look into set of MersenneNumber and check every element in it whether it is prime or not and then remove it.
Can someone, please, help to find whats wrong?
Here are my functions:
factorlist<-function(x) {
if (x<2) {return ("Invalid input")}
if (x%%1!=0) {return ("Invalid input")}
if (x==2) {return(2)}
if (x==3) {return(3)}
vec<-0
for(i in 1:x){
if(x%%i==0){
vec[length(vec)]<-i
vec<-c(vec,0)
}
}
vec<-vec[-length(vec)]
vec<-vec[-length(vec)]
return(vec)
}
primes <- function(n){
primesR <- function(p, i = 1){
f <- p %% p[i] == 0 & p != p[i]
if (any(f)){
p <- primesR(p[!f], i+1)
}
p
}
primesR(2:n)
}
MarsenneNumber<-function(x){
vec<-c(0)
for (i in 3:x){
vec<-union(vec, c(2^primes(i)-1))
}
return(vec[-length(1)])
}
CheckForMersennePrimes<-function(x){
b<-length(MarsenneNumber(x)){
for (i in 1:b){
vec<-MarsenneNumber(x){
if (factorlist(vec[i])!=1){
vec<-c(-vec[i])
}
}
}
}
return(vec)
}
My mistake to last function:
Error: unexpected '}' in " }"
> }
Error: unexpected '}' in " }"
> }
Error: unexpected '}' in " }"
> return(vec)
Error: no function to return from, jumping to top level
> }
Error: unexpected '}' in "}"
Here is an example of how this functions works.
> factorlist(20)
[1] 1 2 4 5 10
> primes(20)
[1] 2 3 5 7 11 13 17 19
> MarsenneNumber(20)
[1] 3 7 31 127 2047 8191 131071 524287
CheckForMersennePrimes has extra {} on line 2 and line 4 (inside for loop) of this function, like vec<-MarsenneNumber(x){if()...}
I removed those extra braces.
CheckForMersennePrimes <- function( x ){
b <- length( MarsenneNumber( x ) )
for ( i in 1:b ){
vec <- MarsenneNumber( x )
if ( factorlist( vec[i] ) != 1 ){
vec <- c( -vec[i] )
}
}
return( vec )
}
I think, your intention is to get values of vec in which factorlist(vec[i]) is equal to 1. If this is true, then you have to initiate vec outside the for loop and check for this condition. Then finally return a1 which contains all vec values passing the if condition.
I also shortened your code by removing b variable. You do not need it. Instead you could do seq_along(vec). It will do the same thing without b variable.
CheckForMersennePrimes <- function( x ){
vec <- MarsenneNumber( x )
a1 <- c()
for ( i in seq_along( vec ) ){
if ( factorlist( vec[i] ) == 1 ){
a1 <- c( a1, vec[i ] )
}
}
return( a1 )
}
Further condensing the code will give same output. I removed seq_along and indexing of vec
CheckForMersennePrimes <- function( x ){
vec <- MarsenneNumber( x )
a1 <- c()
for ( i in vec ){
if ( factorlist( i ) == 1 ) {
a1 <- c( a1, i )
}
}
return( a1 )
}

R: Make sure default argument is evaluated early

When providing a default argument to an R function, this argument is evaluated when first used in the function. How is it possible to evaluate default argument earlier in an elegant way? Example:
f <- function(x, y = 2 * x)
{
if(x < 0) x = 10
y
}
f(1) ## Returns 2
f(-1) ## Returns 20 but I would like it to return -2
Thanks
The answer wasn't to hard to find. The function 'force' does the trick:
f <- function(x, y = 2 * x)
{
force(y)
if(x < 0) x = 10
y
}
f(1) ## Returns 2
f(-1) ## -2

Create and handle an exception in R

I want to have a function where for a particular exceptions it throws and return a message, and then simply check whether what is returned is one of my defined 'exceptions'. For example say I have the function:
divideByX <- function(x){
# If x is NA throws exception
if(is.na(x)){
return(exception('x is NA'))
}
# If x is 0 throws exception
else if(x == 0){
return(exception('Cannot divide by zero'))
}
else{
return(10/x)
}
}
So if x is 0 it returns the expception 'Cannot divide by zero', if x is NA it returns the exception 'x is NA' and for all other values of x it tries to evaluate the expression 10/x.
Then I would want to run something like this:
tempList <- list('a' = 2, 'b' = 0, 'c' = 5, 'd' = NA)
lapply(tempList, function(x){
if(is.exception(x)){
return(x)
}
else{
y <- divideByX(x)
return(y^2)
}
})
So it first checks if the value is one of my defined exceptions and if so returns the message, else it squares my value, so the above should return
$a
[1] 25
$b
[1] 'Cannot divide by zero'
$c
[1] 4
$d
[1] 'x is NA'
Does anyone know the best way to do this? Please let me know if anything is unclear.
Thanks in advance
Create a function to generate exceptions. The exceptions can be a linear hierarchy that extends the simple error class
exception <-
function(class, msg)
{
cond <- simpleError(msg)
class(cond) <- c(class, "MyException", class(cond))
stop(cond)
}
Here's your function
divideByX <- function(x){
# If x is 0 throws exception
if (length(x) != 1) {
exception("NonScalar", "x is not length 1")
} else if (is.na(x)) {
exception("IsNA", "x is NA")
} else if (x == 0) {
exception("DivByZero", "divide by zero")
}
10 / x
}
and use to generate the output you asked for
lapply(tempList, function(x) tryCatch({
divideByX(x)
}, MyException=function(err) {
conditionMessage(err)
}))
or to treat some exceptions differently from others
> lapply(list(NA, 3:5), function(x) tryCatch({
+ divideByX(x)
+ }, IsNA=function(err) {
+ warning(err) # signal a warning, return NA
+ NA
+ }, NonScalar=function(err) {
+ stop(err) # fail
+ }))
Error: x is not length 1
In addition: Warning message:
x is NA
Unless you are always dividing 10, you would want to include the numerator in yoru function.
divideByX <- function(X, num=10) {
if(is.na(X))
return('X is NA')
if(X == 0)
return('Cannot divide by zero')
return(num / X)
}
usage:
y <- 3
lapply(tempList, divideByX, num=y^2)
# $a
# [1] 4.5
#
# $b
# [1] "Cannot divide by zero"
#
# $c
# [1] 1.8
#
# $d
# [1] "X is NA"

Resources