I was trying to create a function that will pick up the 2 numbers in a list which have the sum of a target number.
Can someone let me know why my code isn't working?
Thank you!
TwoSum <- function(num, target) {
for (i in 1:length(num) - 1) {
for (j in i+1:length(num)) {
if (num[i] + num[j] == target) {
print("the numbers are:")
print(paste0(num[i], num[j]))
a <- a - 1
}
}
}
if (a == 1) {
print("No pairs")
}
}
a <- 1
num <- c(1,2,3,4,5)
target <- 7
TwoSum(num,target)
You should not use a loop for this. Use combn instead:
combs <- combn(num, 2)
combs[,colSums(combs) == target]
# [,1] [,2]
#[1,] 2 3
#[2,] 5 4
Introduce braces in the second and third line.
TwoSum <- function(num, target) {
for (i in 1:(length(num) - 1)) {
for (j in (i+1):length(num)) {
if (num[i] + num[j] == target) {
print("the numbers are:")
print(paste0(num[i], num[j]))
a <- a - 1
}
}
Related
I am trying to find Previous Prime number of given value. The mentioned code works fine if I pass prime Number straight away as input lp(7) returns 7. But if I pass lp(6) none are displaying. I am expecting 5 to return.
How do I find the previous prime Number for given one.
Suggestions / Corrections are much appreciated
lp <- function(x){
temp <- x:2
while (x == 2L || all(x %% 2L:max(2,floor(sqrt(x))) != 0))
{
return(x)
}
}
If you run this function a lot of times, probably most efficient is to generate a list of primes once, and search where your value lies in that sequence
library(primes)
primes = generate_primes(2, 1e6)
find_lower_prime = function(x) {
primes[findInterval(x, primes)]
}
find_lower_prime(6)
# [1] 5
You can use the following
lp <- function(x){
previousNumbers <- 2:x
previousPrimes <- sapply(previousNumbers, function(num) {
divisorsToCheck <- 2:max(2,floor(sqrt(num)))
if(num == 2 | all(num %% divisorsToCheck != 0)) {
return(num)
} else {
return(NA)
}
})
previousPrimes[!is.na(previousPrimes)]
}
to get all previous primes.
lp(18) # 2 3 5 7 11 13 17
lp(5) #2 3 5
You can try the code lie below
lp <- function(x) {
p <- x - 1
repeat {
if (p %in% c(2, 3) | all(p %% ceiling(sqrt(2:p)) != 0)) {
return(p)
}
p <- p - 1
}
}
and you will see
> lp(5)
[1] 3
> lp(6)
[1] 5
> lp(7)
[1] 5
> lp(8)
[1] 7
> lp(11)
[1] 7
Hi All this worked for me ..
lp <- function(x){
for(i in x:2)
{
while (i == 2L || all(i %% 2L:max(2,floor(sqrt(i))) != 0))
{
return(i)
}
}
}
Find the number of entries in each row which are greater than 4.
set.seed(75)
aMat <- matrix( sample(10, size=60, replace=T), nr=6)
rowmax=function(a)
{
x=nrow(a)
y=ncol(a)
i=1
j=1
z=0
while (i<=x) {
for(j in 1:y) {
if(!is.na(a[i][j])){
if(a[i][j]>4){
z=z+1
}
}
j=j+1
}
print(z)
i=i+1
}
}
rowmax(aMat)
It is showing the error. I don't want to apply in built function
You could do this easier counting the x that are greater than 4 using length.
rowmax2 <- function(x) apply(x, 1, function(x) {x <- na.omit(x);length(x[x > 4])})
rowmax2(aMat)
# [1] 8 7 8 7 4 3
If you wanted to do this absolutely without any shortcut you could use two for loops. 1 for each row and another for each value in the row.
rowmax = function(a) {
y=nrow(a)
result <- numeric(y)
for(j in seq_len(y)) {
count = 0
for(val in a[j, ]) {
if(!is.na(val) && val > 4)
count = count + 1
}
result[j] <- count
}
return(result)
}
rowmax(aMat)
#[1] 8 7 8 7 4 3
If you wanted to do this using in-built functions in base R you could use rowSums.
rowSums(aMat > 4, na.rm = TRUE)
#[1] 8 7 8 7 4 3
There are several errors in you code:
You should put z <- 0 inside while loop
You should use a[i,j] for the matrix indexing, rather than a[i][j]
Below is a version after fixing the problems
rowmax <- function(a) {
x <- nrow(a)
y <- ncol(a)
i <- 1
j <- 1
while (i <= x) {
z <- 0
for (j in 1:y) {
if (!is.na(a[i, j])) {
if (a[i, j] > 4) {
z <- z + 1
}
}
j <- j + 1
}
print(z)
i <- i + 1
}
}
and then we get
> rowmax(aMat)
[1] 8
[1] 7
[1] 8
[1] 7
[1] 4
[1] 3
A concise approach to make it is using rowSums, e.g.,
rowSums(aMat, na.rm = TRUE)
*> csort <- function(c){
i<-1
for (i in 1:length(c)-1) {
j <- i+1
for (j in 2:length(c)) {
if(c[i] >= c[j])c[c(i,j)] <- c[c(j,i)]
j = j + 1
}
i = i + 1
}
}
> csort(a)
Error in if (c[i] >= c[j]) c[c(i, j)] <- c[c(j, i)] :
argument is of length zero*
This is what RStudio do when I run it. I do not know what cause the zero here.
csort <- function(c){
p <- 1
povit <- c[1]
c <- c[-1]
left <- c()
right <- c()
left <- c[which(c <= povit)]
right <- c[which(c > povit)]
if(length(left) > 1){
left <- csort(left)
}
if(length(right) > 1){
right <- csort(right)
}
return(c(left ,povit,right))
}
I viewed more about sorting online and this is a pivot sort way.
your mistake is in this line
for (i in 1:length(c)-1)
and should be
for (i in 1:(length(c)-1))
since $:$ operator precedes $-$.
an example is
1:(5-1)
#[1] 1 2 3 4
1:5-1
#[1] 0 1 2 3 4
so error happen in index with Zero value.
csort <- function(d){
for (i in 1:(length(d)-1)) {
for (j in (i+1):length(d)) {
if(d[i] >= d[j])d[c(i,j)] <- d[c(j,i)]
}
}
return(d)
}
d<-c(5:1,-1:3,-9,-3,10,9,-20,1,20,-6,5)
any((csort(d)==sort(d))==F)
#[1] FALSE
you can improve this function.
I would like to ask how I can overwrite the variables v and ind in the following function:
repcomb <- function(v,n,ind)
{
k <- length(v)
if(ind == 0)
{
for (i in 1:k) v[i] <- 1
ind <- 1
return
}
for (i in k:1)
{
if(v[i] != n)
{
for (j in k:i) v[j] <- v[i] + 1
return
}
}
ind = 0
}
What is the easiest way for updating v and ind?
This is the easiest way:
repcomb <- function(v,n,ind)
{
k <- length(v)
if(ind == 0)
{
for (i in 1:k) v[i] <- 1
ind <- 1
return(list(v=v, ind=ind))
}
for (i in k:1)
{
if(v[i] != n)
{
for (j in i+1:k) v[j] <- v[i] + 1
v[i] <- v[i] + 1
return(list(v=v, ind=ind))
}
}
ind = 0
return(list(v=v, ind=ind))
}
res <- repcomb(1:5, 4, 2)
v <- res$v
ind <- res$ind
If you want to get back the value of a parameter set inside a function, you can use eval.parent(substitute(val<-new_val)), for example:
f_sqr <- function(val){
new_val <- val^2
eval.parent(substitute(val<-new_val))
}
If you call it:
val <- 5
f_sqr(val)
val
#[1] 25
Please bear in mind that you should not change the value of the parameter inside the function, instead, you copy it to a new variable, do what you want to do in your code and finally set the value of new variable into your parameter variable as it is the case inside the function.
For your own function, this is what you have to do for your first if:
repcomb <- function(v, n, ind)
{
k <- length(v)
if (ind == 0)
{
new_v <- v
for (i in 1:k) new_v[i] <- 1
# ind <- 1
new_ind <- 1
eval.parent(substitute(ind<-new_ind))
eval.parent(substitute(v<-new_v))
}
}
Then if you call it, you will get the changes back:
v <- 1:5
n <- 3
ind <- 0
repcomb(v, n, ind)
v
#[1] 1 1 1 1 1
ind
#[1] 1
Correspondingly, the other part can be changed to meet what you want.
I have written a function to store the diagonal elements of a matrix into a vector. but the output is not as I expected. The code is:
diagonal <- function(x) {
for (i in nrow(x)) {
for (j in ncol(x)) {
if (i == j) {
a <- x[i, j]
}
}
}
print(a)
}
I am passing a matrix to the function.
What is wrong with the code?
We can use the diag function
diag(m1)
#[1] 1 5 9
Or
m1[col(m1)==row(m1)]
#[1] 1 5 9
If we are using the for loop, we are looping by the sequence of rows and columns i.e 1:nrow(x)/1:ncol(x) and not by nrow(x)/ncol(x).
diagonal <- function(x) {
a <- numeric(0)
for( i in 1:nrow(x)){
for(j in 1:ncol(x)){
if(i == j) {
a <- c(a, x[i,j])
}
}
}
a
}
diagonal(m1)
#[1] 1 5 9
data
m1 <- matrix(1:9, ncol=3)