'Is there a way to convert Python to R?
Hey I am trying to convert my python code to R and can't seem to figure out the last part of the recursion. If anyone who has experience in both languages could help that would be great!
def robber(nums):
    if len(nums) == 0: return 0
    elif len(nums) <= 2: return max(nums)
    else:
        A = [nums[0], max(nums[0:2])]
        for i in range(2, len(nums)):
            A.append(max(A[i-1], A[i-2] + nums[i]))
    return A[-1]
Above is the Python version and below is my attempt so far on converting to R
robbing <- function(nums) {
    if (length(nums) == 0){
        result <- 0      
    }
    else if(length(nums) <= 2){
        result <- max(nums)     
    }
    else{
      a <- list(nums[0], max(nums(0:2)))
      for (i in range(2, length(nums))){
          result <- max(a[i-1], a[i-2] + nums[i])
      }
    }
    #result <- a[-1]
}
Solution 1:[1]
You have a couple of problems.
- You are zero-indexing your vectors. R is 1-indexed (first element of yisy[1]noty[0].
- Ranges (slices in python) in R are inclusive. Eg: 0:2 = c(0, 1, 2)while python is right-exclusive0:2 = [0, 1].
- R uses minus elements to "remove" elements of vectors, while Python uses these to extract from reverse order. Eg: y[-1] = y[2:length(y)]in R.
- R's rangefunction is not the same as Python'srangefunction. The equivalent inRwould beseqora:b(example3:n). Not again that it is right-inclusive while pythons is right-exclusive!
- You are not storing your intermediary results in aas you are doing in python. You need to do this at run-time
And last: R functions will return the last evaluation by default. So there is no need to explicitly use return. This is not a problem per-say, but something that can make code look cleaner (or less clean in some cases). So one option to fix you problem would be:
robber <- function(nums){
  n <- length(nums) # <= Only compute length **once** =>
  if(n == 0)
    0 # <= Returned because no more code is run after this =>
  else if(n <= 2)
    max(nums) # <= Returned because no more code is run after this =>
  else{
    a <- numeric(n) # <= pre-allocate our vector =>
    a[1:2] <- cummax(nums[1:2]) # <= Cummax instead of c(nums[1], max(nums[1:2])) =>
    for(i in 3:n){ # <= Note that we start at 3, because of R's 1-indexing =>
      a[i] <- max(a[i - 1], a[i - 2] + nums[i])
    }
    a[n]
  }
}
Note 3 things:
- I use that R vectors are 1-indexed, and my range goes from 3as a consequence of this.
- I pre-allocate my avector (here usingnumeric(n)). R vector expansion is slow while python lists are constant in time-complexity. So preallocation is the recommended way to go in all cases.
- I extract my length once and store it in a variable. n <- length(nums). It is inherently unnecessary to evaluate this multiple times, and it is recommended to store these intermediary results in a variable. This goes for any language such as R, Python and even in compild languages such as C++ (while for the latter, in many cases the compiler is smart enough to not recompute the result).
Last I use cummax where I can. I feel there is an optimized way to get your result almost immediately using vectorization, but I can't quite see it.
Solution 2:[2]
I would avoid to use a list. Because appending lists is slow. (Especially in R! - Vector is much better. But we don't need any sequence and indexing, if we use variables like I show you here). You don't need to build a list. All you need to keep in memory is the previous and the preprevious value for res.
def robber(nums, res=0, prev=0, preprev=0): # local vars predefined here
    for x in nums:
        prev, preprev = res, prev
        res = max(prev, preprev + x)
    return res
This python function does the same like your given. (Try it out!).
In R this would be:
robber <- function(nums, res=0, prev=0, preprev=0) {
  for (x in nums) {
    preprev <- prev
    prev <- res       # correct order important!
    res <- max(prev, preprev + x)
  }
  res
}
Taking the local variable definitions into the argument list saves in R 3 lines of code, therefore I did it.
Solution 3:[3]
I suggest you can change result to return() and renaming object a outside the function, also change len to length() by the end of the function.
a <- list(nums[0], max(nums(0:2)))
robbing <- function(nums) {
  if (length(nums) == 0){
    return(0)    
  }
  else if(length(nums) <= 2){
    return(max(nums))     
  }
  else{
    
    for (i in range(2, length(nums))){
      return(max(a[i-1], a[i-2] + nums[i]))
    }
  }
  return(a[length(a)])
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | TheFunSideofData | 
