0

translating a Python function to R I try to add more data while iterating through values which I split using strsplit() in R. The return value of the original Python function is a list of lists so this should be the same in the R version (vector of vectors). The Python function is

anbaudauer = 12
planzen_list = [
                    'tomaten_6',
                    'karotten_4',
                    'paprika_7',
                    'erdbeeren_5',
                    'koriander_2',
                    'salat_3',
                    'zucchini_4',
                    'gurke_5',
                    'petersilie_2',
                    'radieschen_3'
                ]

def possible_combinations(values, target, with_replacement=True):
    def sub_combinations(index, l, r, t, w):
        if t == sum(filter(lambda i: isinstance(i, int), l)):
            r.append(l)
        elif t < sum(filter(lambda i: isinstance(i, int), l)):
            return
        for u in range(index, len(values)):
            sub_combinations(u if w else (u + 1), l + [values[u].split('_')[0], int(values[u].split('_')[1])], r, t, w)
        return r
    return sub_combinations(0, [], [], target, with_replacement)

raw_combinations = possible_combinations(planzen_list, anbaudauer)

# returns [['tomaten', 6, 'tomaten', 6], ['tomaten', 6, 'karotten', 4, 'koriander', 2], ['tomaten', 6, 'karotten', 4, 'petersilie', 2], ...]

the current state of the R function is

w <- c(
  'tomaten_6',
  'karotten_4',
  'paprika_7',
  'erdbeeren_5',
  'koriander_2',
  'salat_3',
  'zucchini_4',
  'gurke_5',
  'petersilie_2',
  'radieschen_3'
)
n <- length(w)
t <- 12
D <- list()
for (j in 0:n) D[[paste(0, j)]] <- list(c())
for (i in 1:t) D[[paste(i, 0)]] <- list()
for (j in 1:n) {
  for (i in 1:t) {
    D[[paste(i, j)]] <- do.call(c, lapply(0:floor(i/as.numeric(strsplit(w[j], '_')[[1]][2])), function(r) {
      lapply(D[[paste(i-r*as.numeric(strsplit(w[j], '_')[[1]][2]), j-1)]], function(x) c(x, rep(strsplit(w[j], '_')[[1]][1]), r))
    }))
  }
}
D[[paste(t, n)]]

at as.numeric(strsplit(w[j], '_')[[1]][2])I would like to add the name of the vegetable before the number. In essence the R function should return the same as the Python function. Transforming the R functions return value was tricky so far. Basically I tried taking everything apart and stitching it together again. As I haven't used R in a long time I'm sure there is a convenient method to get the same data returned as from the Python function.

Aaron Scheib
  • 358
  • 4
  • 18

1 Answers1

1

Why not go with good old RegEx here? For a start:

#first drop the text before the '_' 
w_int <- as.integer(gsub(pattern = ".*_", replacement = "", w))
#repeat the replacement for the numbers at the end to get the vegetable names
w_names <- gsub(pattern = '_[0-9]*$', "", w)
#assign the vegetable names to the Anbaudauer-vector as names 
names(w_int) <- w_names 
w_int
tomaten   karotten    paprika  erdbeeren  koriander      salat ...
     6          4          7          5          2          3 ...
Anbaudauer <- 12

And from there on just check all combinations that add up to Anbaudauer. Potentially something like this ... combinations of numbers to reach a given sum - recursive implementation in R don't want to repeat that here.

GWD
  • 1,387
  • 10
  • 22
  • thanks, the issue here is that some plants have the same Anbaudauer (e.g. koriander and petersilie) and that plants can be reused. The suggested implementations gives correctly 103 possible combinations but I want to have the plant names included and not just the numbers that sum to the Anbaudauer as the plants are the distinguishing factor I'm looking for. – Aaron Scheib Feb 10 '20 at 06:51
  • you can always access vector name attributes via the names() function; additionally the l|s|v*apply family of functions has a USE.NAMES = TRUE|FALSE parameter available, where the names can get preserved - in case you reuse the function in the linked answer; I think there are also package "purrr" functions that help handle this problem – GWD Feb 10 '20 at 11:19
  • but using ```w_int``` as input for the function does not get the correct result as it is ignoring that e.g. a plant with 2 days is occurring twice. Using ```w_int``` as input for the function results in only 50 combinations instead of the 103. – Aaron Scheib Feb 10 '20 at 16:23
  • Hi ... have you tried using something like `combn(w_int, min(which(cumsum(w_int)>Anbaudauer), simplify = FALSE)` – GWD Feb 11 '20 at 21:41
  • I am also not sure how you define correctly in your context - since you were originally asking how to split out names and numbers. The question has changed somewhat or is a different/new one. – GWD Feb 11 '20 at 22:41
  • BUT if you have all combinations defined as above `comb(...)` it is an exercise of applying something like this `veggies <- sapply(lapply(Combs, function(x) which(cumsum(x) <= target)), names)` to get the veggie names out PLUS removing the duplicates - serch for that on SO – GWD Feb 11 '20 at 22:49