'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
y
isy[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
range
function is not the same as Python'srange
function. The equivalent inR
would beseq
ora:b
(example3:n
). Not again that it is right-inclusive while pythons is right-exclusive! - You are not storing your intermediary results in
a
as 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
3
as a consequence of this. - I pre-allocate my
a
vector (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 |