Search code examples
rfunctiondataframefor-looprowwise

R programming, row-wise data frame calculation with custom script (for every i) to solve "bridge game"


I have a data frame which specifies "bridge games" (every row is one independent game), see a minimal example with 4 games below:

start <- list(c("10","15","5"), c("5") ,c("11","6"),c("6","11"))
end <- list(c("7","17","11"), c("10"), c("8","12"),c("8","12"))
ascending <- c("+","-","+","-")
position <- c(11,6,9,8)
desired_output <- c(5,5,"disqualified",3)

bridge_game <- data.frame(start = I(start), end = I(end), ascending = ascending, position = position, desired_output = desired_output)

bridge_game

How does the bridge game work? Candidates all over the world participate in a bridge game challenge and we have collected the data of every bridge game in a data frame. Every bridge consists of numbered wooden panels (positive integers that not necessarily have to start at 1) and "gaps" of broken panels. The candidate can choose from which side of the bridge he is starting his walk (ascending = the numbering of the panel increases as the walk progresses; or descending = the numbering of the panel decreases as the walk progresses).

A graphic for a better understanding of the bridge game can be found here (exemplified for the 1st row in the data frame): click here

For every bridge game (= row in the data frame) we have the following information (= columns):

  • bridge_game$start: all start positions of tracts of whole wooden panels (random order)
  • bridge_game$end: all end positions of tracts of whole wooden panels (random order)
  • bridge_game$ascending: walk across the bridge in ascending (+) or descending (-) order of panels
  • bridge_game$position: candidate ended up at the indicated panel

What is the challenge? I need to write a script that I can run row-wise over the whole data frame to get the following output:

  • bridge_game$desired_output: test whether candidate fell down into the river (ended up at a broken panel and is "disqualified"). And if he is not disqualified I need to calculate the number of whole wooden panels covered by the candidate's walk (broken panels don't count).

Importantly, it should work for any number i of whole tracts of wooden panels.

To be more precise I give a step-by-step instruction how the requested R script should operate below:

0) solved

a) Convert list of characters into numeric list for columns bridge_game$start and bridge_game$end.

b) Calculate i (the number of tracts of whole wooden panels; i goes from 1 to i=max for every row) and sort the start and end positions to get the correct start and end values for every i.

1) Test whether the position is at a broken panel: end(i=1 to max-1) > position > start(i=2 to max) --> if TRUE for any of the tested pairs --> "disqualified"

2) If no, test in which tract of whole panels the given position lies (i = n): start(i=1 to max) <= position <= end(i=1 to max) --> if TRUE give back i (= n)

3)

a) Apply this formula (if direction is ascending "+" and n = 1): output = position - start(i=1) + 1

b) Apply this formula (if direction is descending "-" and n = i max): output = end(i=max) - position + 1

c)Apply this formula (if direction is ascending "+" and n > 1): output = position - start(i=1) + 1 - (start(i=2 to n) - end(i=1 to n-1) - 1x[n-1])

d) Apply this formula (if direction is descending "-" and n < i max): output = end(i=max) - position + 1 - (start(i=n+1 to max) - end(i=n to max-1) - 1x[i=max - n])

I hope I got the math right there. To check for the correct output I have created a "desired_output" column in the "bridge_game" data frame.

Thanks for your help!


Solution

  • It seems i have more simple solution for step #3. Function npanels creates a vector from the panel numbers, determines the position of the player's stop in it. If the direction of movement is positive (ascending variable is "+"), then this is the desired solution, if negative, then the desired value is calculated based on the length of this vector.

    start <- list(c(5,10,15), c(5) ,c(6,11),c(6,11))
    end <- list(c(7,11,17), c(10), c(8,12),c(8,12))
    position <- c(11,6,9,8)
    ascending <- c("+","-","+","-")
    game <- data.frame(start = I(start), end = I(end), position = position, ascending = ascending)
    
    npanels <- function (data) {
      v <- unlist(Map(":",
                      unlist(data[["start"]]),
                      unlist(data[["end"]])))
      p <- which(v == data[["position"]])
      l <- length(v)
      b <- 1+l-p
      d <- data[["ascending"]]
      n <- ifelse(d == "+", p, b)
      n <- if(is.na(n)) "disqualified" else n
      return(n)
    }
    
    game$solution <- apply(game, 1, npanels)
    
    game