R 프로그래밍, "브리지 게임"을 해결하기위한 사용자 지정 스크립트 (모든 i에 대해)를 사용한 행 단위 데이터 프레임 계산

Nov 25 2020

"브리지 게임"을 지정하는 데이터 프레임이 있습니다 (모든 행은 하나의 독립 게임 임). 아래 4 개의 게임이있는 최소 예를 참조하십시오.

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

브리지 게임은 어떻게 작동합니까? 전 세계의 후보자들이 브리지 게임 챌린지에 참여하고 있으며, 우리는 모든 브리지 게임의 데이터를 데이터 프레임에 수집했습니다. 모든 다리는 번호가 매겨진 나무 패널 (1에서 시작하지 않아도되는 양의 정수)과 깨진 패널의 "간격"으로 구성됩니다. 후보자는 다리의 어느 쪽에서 걷기를 시작하는지 선택할 수 있습니다 (오름차순 = 걷기가 진행됨에 따라 패널 번호가 증가하거나 내림차순 = 걷기가 진행됨에 따라 패널 번호가 감소 함).

브리지 게임에 대한 더 나은 이해를위한 그래픽은 여기에서 찾을 수 있습니다 (데이터 프레임의 첫 번째 행에 대한 예시) : 여기를 클릭하십시오

모든 브리지 게임 (= 데이터 프레임의 행)에 대해 다음 정보 (= 열)가 있습니다.

  • bridge_game $ start : 전체 목재 패널의 모든 시작 위치 (무작위 순서)
  • bridge_game $ end : 전체 나무 패널의 모든 끝 위치 (무작위 순서)
  • bridge_game $ ascending : 패널의 오름차순 (+) 또는 내림차순 (-)으로 다리 건너기
  • bridge_game $ position : 후보가 표시된 패널에서 끝남

도전은 무엇입니까? 다음 출력을 얻기 위해 전체 데이터 프레임에서 행 단위로 실행할 수있는 스크립트를 작성해야합니다.

  • bridge_game $ desired_output : 후보자가 강에 떨어졌는지 테스트합니다 (패널이 깨져서 "실격"됨). 그리고 그가 실격되지 않은 경우 후보자의 워크에 포함 된 전체 목재 패널 를 계산해야합니다 (파손 된 패널은 포함되지 않음).

중요한 것은, 그것을 위해 일해야 어떤 수의 전체 책자의 나무 패널.

보다 정확하게하기 위해 요청 된 R 스크립트가 아래에서 작동하는 방법을 단계별로 설명합니다.

0) 해결

a) 문자 목록을 bridge_game $ start 및 bridge_game $ end 열의 숫자 목록으로 변환합니다.

b) i (전체 나무 패널의 전도지 수, i 는 모든 행에 대해 1 에서 i = max 로 이동 )를 계산 하고 시작 및 끝 위치를 정렬하여 모든 i에 대한 올바른 시작 및 끝 값을 얻습니다 .

1) 위치가 깨진 패널에 있는지 테스트 : end (i = 1 to max-1)> position> start (i = 2 to max)-> if TRUE if any of the test pairs-> "disqualified"

2) 아니오 인 경우 주어진 위치가있는 전체 패널의 영역을 테스트합니다 ( i = n ) : 시작 (i = 1 ~ 최대) <= 위치 <= 끝 (i = 1 ~ 최대)-> 참이면 되돌려줍니다 나는 (= n)

삼)

a) 다음 공식을 적용합니다 (방향이 "+"및 n = 1 인 경우) : 출력 = 위치-시작 (i = 1) + 1

b) 다음 공식을 적용합니다 (방향이 "-"하강하고 n = i max 인 경우) : output = end (i = max)-position + 1

c) 다음 공식을 적용합니다 (방향이 "+"오름차순이고 n> 1 인 경우) : output = position-start (i = 1) + 1-(start (i = 2 to n)-end (i = 1 to n- 1)-1x [n-1])

d) 다음 공식을 적용합니다 (방향이 "-"하강하고 n <i max) : output = end (i = max)-position + 1-(start (i = n + 1 to max)-end (i = n 최대 -1)-1x [i = 최대-n])

바로 거기에 수학이 있기를 바랍니다. 올바른 출력을 확인하기 위해 "bridge_game"데이터 프레임에 "desired_output"열을 만들었습니다.

당신의 도움을 주셔서 감사합니다!

답변

3 YaroslavDanko Nov 29 2020 at 03:01

# 3 단계에 대한 더 간단한 해결책이있는 것 같습니다. 함수 npanels는 패널 번호에서 벡터를 생성하고 그 안에서 플레이어의 정지 위치를 결정합니다. 이동 방향이 양수이면 ( ascending변수는 "+") 원하는 솔루션이고 음수이면이 벡터의 길이를 기준으로 원하는 값이 계산됩니다.

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
4 ekoam Nov 29 2020 at 02:52

이 문제를 너무 복잡하게 만들었습니다. 다음 구현을 고려하십시오.

parse_pos <- function(x) sort(as.integer(x))

construct_bridge <- function(starts, ends) {
  starts <- parse_pos(starts); ends <- parse_pos(ends)
  bridge <- logical(tail(ends, 1L))
  whole_panels <- sequence(ends - starts + 1L, starts)
  bridge[whole_panels] <- TRUE
  bridge
}

count_steps <- function(bridge, direction, stop_pos) {
  if (isFALSE(bridge[[stop_pos]]))
    return("disqualified")
  start_pos = c("+" = 1L, "-" = length(bridge))[[direction]]
  sum(bridge[start_pos:stop_pos])
}

play_games <- function(starts, ends, direction, stop_pos) {
  mapply(function(s, e, d, sp) {
    bridge <- construct_bridge(s, e)
    count_steps(bridge, d, sp)
  }, starts, ends, direction, stop_pos)
}

산출

> with(bridge_game, play_games(start, end, ascending, position))
[1] "5"            "5"            "disqualified" "3" 

여기서 핵심은 논리 벡터를 사용하여 브리지를 나타낼 수 있다는 것입니다. 여기서 파손 / 전체 패널은 F/ 로 인덱싱됩니다 T. 그런 다음 정지 위치가 전체 패널에 있는지 여부를 테스트합니다. 그럴 경우 시작 위치부터 끝 ​​위치까지 패널의 합계를 반환하거나 (깨진 패널은 0 일 뿐이므로 합계에 영향을주지 않음) 그렇지 않으면 "실격"됩니다.

2 Ben Nov 29 2020 at 02:09

이것은 세 번째 단계에 필요한 것을 제공 할 수 있습니다. 다른 게시물 에서 기능을 수정했습니다 .

먼저 n(또는 region)이 인지 확인합니다 NA. 그렇다면 과 position사이에 일치하는 항목이없는 것 입니다.startend

그렇지 않으면, 당신의 2 × 2 조합을 포함 할 수 있습니다 if else보고 ascendingn. 방정식은에서 유사한 값 추출을 사용합니다 x. 당신이 원하는 것처럼 참고로, 그것은 보이는 sum인덱스의 범위가 값 (당신이 말할 때 예를 들어, 당신이 원하는 "(내가 n으로 = 2) 시작" sum같은 값 sum(start[2:n])).

이것은 원하는 것처럼 방정식을 코드로 직접 변환합니다. 그러나 다른 답변에 설명 된 논리를 기반으로 한 더 간단한 대안이 있습니다.

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))
ascending <- c("+","-","+","-")
imax <- c(3,1,2,2)
position <- c(11,6,9,8)

example <- data.frame(start = I(start), end = I(end), ascending = ascending, imax = imax, position = position)

my_fun <- function(x) {
  n <- NA
  out <- NA
  start <- as.numeric(unlist(x[["start"]]))
  end <- as.numeric(unlist(x[["end"]]))
  for (i in 1:x[["imax"]]) {
    if (between(x[["position"]], start[i], end[i])) n <- i
  }
  if (!is.na(n)) {
    if (x[["ascending"]] == "+") {
      if (n == 1) {
        out <- x[["position"]] - start[1] + 1
      } else if (n > 1) {
        out <- x[["position"]] - start[1] + 1 - (sum(start[2:n]) - sum(end[1:(n-1)]) - (n - 1))
      }
    } else if (x[["ascending"]] == "-") {
      if (n == x[["imax"]]) {
        out <- end[x[["imax"]]] - x[["position"]] + 1  
      } else if (n < x[["imax"]]) {
        out <- end[x[["imax"]]] - x[["position"]] + 1 - (sum(start[(n+1):x[["imax"]]]) - sum(end[n:(x[["imax"]] - 1)]) - (x[["imax"]] - n))
      }
    }
  }
  out
}

example$desired_output <- apply(example, 1, my_fun) 

산출

      start       end ascending imax position desired_output
1 5, 10, 15 7, 11, 17         +    3       11              5
2         5        10         -    1        6              5
3     6, 11     8, 12         +    2        9             NA
4     6, 11     8, 12         -    2        8              3
Quad89 Nov 27 2020 at 01:05

최신 정보:

0) 단계가 완료되었습니다.

#Change to numeric
bridge_game$start <- lapply(bridge_game$start, as.numeric)
bridge_game$end <- lapply(bridge_game$end, as.numeric)

#Calculate number of tracts of whole wooden panels
bridge_game$tracts <- lapply(bridge_game$start, length)

#Sort start and end positions
bridge_game$start <- lapply(bridge_game$start, sort)
bridge_game$end <- lapply(bridge_game$end, sort)

#Calculate number of tracts of whole wooden panels
bridge_game$tracts <- lapply(bridge_game$start, length)

1) 단계부터 어려움을 겪고 있습니다.