MuroBBS Programming Challenge 1

It’s been a while since the last post. I started my studies as a statistics major in university and have been doing little with R but mostly just reading other blogs and taking our university’s R course which was just the basics so nothing new there.

I mentioned earlier that the Jets are back and they’re doing pretty nice. Teemu Selänne returned to Winnipeg to play against Jets a while ago and it was awesome night.

This post is about programming “challenge” in a Finnish computer themed forum MuroBBS  (in Finnish) where people write different programming challenges and others write solutions with different languages. I chose R since it’s not so familiar there.

First warm up was to create following sequence given the amount of maximum stars
*
**
***
****
*****
****
***
**
*
My code for that:

# MuroBBS Ohjelmointipähkinä 1
# http://murobbs.plaza.fi/1707865276-post2.html
stars <- function(n) {
sequence <- c(1:n, (n-1):1)
for (i in sequence) {
# Changed from print to cat, thanks for commenting Tal!
cat(rep('*', i), "\n")
}
}

When called, it gives output:

> stars(5)
*
* *
* * *
* * * *
* * * * *
* * * *
* * *
* *
*

However, I started thinking that is there a solution which doesn’t require a loop but that uses some of R’s own vector/list handling techniques?

edit
I wanna add Tony Breyal’s solution from comments as it’s pretty much superior to my unefficient for-loop:

stars2 <- function(n) {
myseq <- c(1:n, (n-1):1)
stars <- sapply(myseq, function(i) paste(rep("*", i), collapse = ""))
cat(stars, sep = "\n")
}

 

I’ve read about for-loop being really slow so after testing with Tony’s solution, I did little benchmarking to see that my solution really was terrible:

library(rbenchmark)
benchmark(stars(100), stars2(100), columns= c("test", "elapsed", "relative"))<strong>
</strong>
#       test    elapsed    relative
#1  stars(100)   20.72       26.5641
#2 stars2(100)    0.78       1.0000

So as you can see, mine was over 26 times slower than Tony’s.

More challenges and solutions in later posts.

12 responses to “MuroBBS Programming Challenge 1

  1. BTW, you might prefer to use cat instead of print…

  2. Thanks for pointing it out, Tal! My background is from Java and Python so print was the first one to come to my mind but it seems like cat() really does the job better.

    • Another and often better choice (not in this example but just generally speaking regarding console output) is message() as it allows for toggling (on/off)

  3. stars <- function(n) {
    s <- c(1:n,(n-1):1)
    noquote(t(apply(cbind(s, n-s),1,function(r){c(rep("*",r[1]),rep("",r[2]))})))
    }

  4. stars <- function(n) {
    dummy<-sapply(c(1:n,(n-1):1),FUN=function(t) {cat(paste(c(rep("*",t),"\n"),collapse="",sep=""))})
    }

  5. Example with recursion as c(1:n, (n-1):1) doesn’t work with n=1.
    star_tree <- function(n=10){
    seq_star <- function(n){
    min_n <- min(n)
    if(min_n==1) return(n) else seq_star(c(min_n-1, n, min_n-1))
    }
    cat(paste(unlist(lapply(seq_star(n), function(x)
    paste(rep("*", x), sep="", collapse=""))), "\n",
    sep="", collapse=""))
    }

  6. Another solution:

    sequence <- c(1:n, (n-1):1)
    stars <- sapply(sequence, function(i) paste(rep("*", i), collapse = ""))
    cat(stars, sep = "\n")
    
  7. Another solution:

    stars <- function(n) {
      myseq <- c(1:n, (n-1):1)
      stars <- sapply(myseq, function(i) paste(rep("*", i), collapse = ""))
      cat(stars, sep = "\n")  
    }
    
    stars(5)
    # *
    # **
    # ***
    # ****
    # *****
    # ****
    # ***
    # **
    # *
    
  8. @Wojtek makes a good point about n < 2. With my solution, this special case can be handled with a simple if statement (sorry for the multiple comment posts as I can't see an option for editing):

    stars <- function(n) {
    if(n < 1) return(cat(""))
    if(n == 1) return(cat("*"))
    myseq <- c(1:n, (n-1):1)
    stars.seq <- sapply(myseq, function(i) paste(rep("*", i), collapse = ""))
    cat(stars.seq, sep = "\n")
    }

  9. ok. I don’t know where to post this, but this is another R programming challenge:
    I have k sorted numeric vectors, and I want to merge them into one sorted vector. concatenating them and then sorting is too slow (sorting is o(nlogn), but merging should be just o(n)). yet, writing the regular code (which use looping), is ineffective in R. loops are really slow. n is large (around 10^7, k is about 5). I’m looking for an efficient R implementation for this merge. any idea?

  10. stars <- function(N) do.call(rbind, lapply( c(seq_len(N), rev(seq_len(N-1))), function (x) paste(rep("*", x), collapse="")))

Leave a comment