Reducing memory usage for FizzBuzz in R I've been trying all night to get my fizzbuzz to use below 20 MB of RAM but I can't seem to get it much smaller than this.

# Sample code to read test cases
args &lt;- commandArgs(trailingOnly=TRUE)
test.cases &lt;- strsplit(readLines(args[[1]], warn=FALSE), '\n')
args &lt;- NULL
for (test in test.cases) {
    if (length(test) &gt; 0) {
        # ignore test if it is an empty line
        # 'test' represents the test case, do something with it
        test &lt;- as.numeric(unlist(strsplit(test, " ")))
        x &lt;- 0
        y &lt;- 0
        for(i in 1: test[3]) {
            if(i != 1) cat(" ")
            flag &lt;- TRUE
            out &lt;- i
            x &lt;- x + 1
            y &lt;- y + 1 
            if( x == test[1] ) {
                cat("F")
                x &lt;- 0
                flag &lt;- FALSE
            }
            if( y == test[2] ) {
                cat("B")
                y &lt;- 0
                flag &lt;- FALSE
            }
            if(flag) cat(out)
        }

        cat("\n")
    }
}
Thanks for providing the link, it helped a lot in understanding what you were after. I will provide two versions for you to consider. The first one is algorithmically similar to yours, except written a little more in the "R style". The second one will make a more efficient use of memory since that seems to be important too.

I will also assume that the input file in args[[1]] is like the one in the link, i.e. contains lines like the two below:

3 5 10
2 7 15


Version 1:

args &lt;- commandArgs(trailingOnly = TRUE)
input.file &lt;- args[[1]]
test.cases &lt;- strsplit(readLines(input.file, warn=FALSE), ' ')
for (test in test.cases) {
   stopifnot(length(test) == 3L)
   XYN &lt;- as.integer(test)
   X &lt;- XYN[1]
   Y &lt;- XYN[2]
   N &lt;- XYN[3]
   i &lt;- seq_len(N)
   is.divisible.by.X &lt;- (i %% X) == 0L
   is.divisible.by.Y &lt;- (i %% Y) == 0L
   out &lt;- as.character(i)
   out[is.divisible.by.X &amp; is.divisible.by.Y] &lt;- "FB"
   out[is.divisible.by.X] &lt;- "F"
   out[is.divisible.by.Y] &lt;- "B"
   cat(out, sep = " ")
   cat("\n")
}


Some noticeable improvements are:


some assumption checking with stopifnot
the use of variable names that are closer to the problem write-up (X, Y, N) or more descriptive, e.g., is.divisible.by.X
the use of %% for finding if a number is divisible by X or Y
vectorization (notice how one of your for loops is gone), which should make your code faster
The use of seq_len(N) instead of 1:N is more robust in the case when N is zero.




Version 2:

args &lt;- commandArgs(trailingOnly = TRUE)
input.file &lt;- args[[1]]
file.handle &lt;- file(input.file, open = "r")
repeat {
   line &lt;- readLines(file.handle, n = 1)
   if (length(line) == 0L) break  # end of file
   test &lt;- strsplit(line, " ")[[1]]
   XYN &lt;- as.integer(test)
   X &lt;- XYN[1]
   Y &lt;- XYN[2]
   N &lt;- XYN[3]
   i &lt;- 1L
   while (i &lt;= N) {
      is.divisible.by.X &lt;- (i %% X) == 0L
      is.divisible.by.Y &lt;- (i %% Y) == 0L
      out &lt;- if (is.divisible.by.X &amp; is.divisible.by.Y) "FB" else
             if (is.divisible.by.X) cat("F") else
             if (is.divisible.by.Y) cat("B") else as.character(i)
      cat(out, "")
      i &lt;- i + 1L
   }
   cat("\n")
}
close(file.handle)


How is that different from version 1? Here we are careful to read the file and process it line-by-line instead of reading the whole file in memory. Also, when processing each line, we are careful not to generate the seq_len(N) vector in memory and pre-compute the output for all the values. Instead, we are counting from 1 to N and processing each value one at a time.

Because version 2 uses a while loop in place of the vectorization happening in version 1, it will be slower. But it will use a lot less memory, especially if the file contains a large number of rows or large values for N, both things could make version 1 fail.

I hope this helps. Let me know if you have questions.