Advertisement
Guest User

Untitled

a guest
Dec 23rd, 2021
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
R 7.32 KB | None | 0 0
  1. library(purrr)
  2. library(stringr)
  3. library(collections)
  4.  
  5. cost <- c('A' = 1, 'B' = 10, 'C' = 100, 'D' = 1000)
  6. entrance = c('A' = 3, 'B' = 5, 'C' = 7, 'D' = 9)
  7.  
  8. # moves from room r to corridor tile c, returns -1 is the move is illegal
  9. move_r2c <- function(rooms, corridor, r, c) {
  10.   i_max <- length(rooms[[1]])
  11.   if (c %in% c(3, 5, 7, 9) |
  12.       all(rooms[[r]] == '.') |
  13.       (2 * r + 1 >= c & any(corridor[c:(2 * r + 1)] != '.')) |
  14.       (c >= 2 * r + 1 & any(corridor[(2 * r + 1):c] != '.'))) {
  15.     return(-1)
  16.   }
  17.   steps <- abs(2 * r + 1 - c)
  18.  
  19.   found <- FALSE
  20.   for (i in 1:i_max) {
  21.     if (rooms[[r]][i] != '.' & !found) {
  22.       pawn <- rooms[[r]][i]
  23.       rooms[[r]][i] <- '.'
  24.       steps <- steps + i
  25.       found <- TRUE
  26.     }
  27.   }
  28.  
  29.   if ( (pawn == 'A' & r == 1 & all(rooms[[r]] %in% c('.', 'A'))) |
  30.        (pawn == 'B' & r == 2 & all(rooms[[r]] %in% c('.', 'B'))) |
  31.        (pawn == 'C' & r == 3 & all(rooms[[r]] %in% c('.', 'C'))) |
  32.        (pawn == 'D' & r == 4 & all(rooms[[r]] %in% c('.', 'D'))) ) {
  33.     return(-1)
  34.   }
  35.  
  36.   corridor[c] <- pawn
  37.  
  38.   return(list(rooms, corridor, steps * cost[pawn]))
  39. }
  40.  
  41. # moves from room r to room s, returns -1 is the move is illegal
  42. move_r2r <- function(rooms, corridor, r, s) {
  43.   i_max <- length(rooms[[1]])
  44.   if (all(rooms[[r]] == '.') |
  45.       r == s |
  46.       (r < s & any(corridor[(2 * r + 1):(2 * s + 1)] != '.')) |
  47.       (r > s & any(corridor[(2 * s + 1):(2 * r + 1)] != '.'))) {
  48.     return(-1)
  49.   }
  50.   steps <- abs(2 * abs(r - s))
  51.  
  52.   found <- FALSE
  53.   for (i in 1:i_max) {
  54.     if (rooms[[r]][i] != '.' & !found) {
  55.       pawn <- rooms[[r]][i]
  56.       rooms[[r]][i] <- '.'
  57.       steps <- steps + i
  58.       found <- TRUE
  59.     }
  60.   }
  61.  
  62.   if ( (pawn == 'A' & r == 1 & all(rooms[[r]] %in% c('.', 'A'))) |
  63.        (pawn == 'B' & r == 2 & all(rooms[[r]] %in% c('.', 'B'))) |
  64.        (pawn == 'C' & r == 3 & all(rooms[[r]] %in% c('.', 'C'))) |
  65.        (pawn == 'D' & r == 4 & all(rooms[[r]] %in% c('.', 'D'))) ) {
  66.     return(-1)
  67.   }
  68.  
  69.   if ( (pawn == 'A' & !(s == 1 & all(rooms[[s]] %in% c('.', 'A')))) |
  70.        (pawn == 'B' & !(s == 2 & all(rooms[[s]] %in% c('.', 'B')))) |
  71.        (pawn == 'C' & !(s == 3 & all(rooms[[s]] %in% c('.', 'C')))) |
  72.        (pawn == 'D' & !(s == 4 & all(rooms[[s]] %in% c('.', 'D')))) ) {
  73.     return(-1)
  74.   }
  75.  
  76.   dots <- which(rooms[[s]] == '.')
  77.   rooms[[s]][dots[length(dots)]] <- pawn
  78.   steps <- steps + dots[length(dots)]
  79.  
  80.   return(list(rooms, corridor, steps * cost[pawn]))
  81. }
  82.  
  83. # moves from corridor tile c to room r, returns -1 if the move is illegal
  84. move_c2r <- function(rooms, corridor, c, r) {
  85.   i_max <- length(rooms[[1]])
  86.   if(corridor[c] == '.' |
  87.      all(rooms[[r]] != '.') |
  88.      (c < 2 * r + 1 & any(corridor[(c + 1):(2 * r + 1)] != '.')) |
  89.      (c > 2 * r + 1 & any(corridor[(2 * r + 1):(c - 1)] != '.'))){
  90.     return(-1)
  91.   }
  92.  
  93.   steps <- abs(c - (2 * r + 1))
  94.   pawn <- corridor[c]
  95.   corridor[c] <- '.'
  96.  
  97.   if ( !((pawn == 'A' & r == 1 & all(rooms[[r]] %in% c('.', 'A'))) |
  98.          (pawn == 'B' & r == 2 & all(rooms[[r]] %in% c('.', 'B'))) |
  99.          (pawn == 'C' & r == 3 & all(rooms[[r]] %in% c('.', 'C'))) |
  100.          (pawn == 'D' & r == 4 & all(rooms[[r]] %in% c('.', 'D')))) ) {
  101.     return(-1)
  102.   }
  103.  
  104.   found <- FALSE
  105.   for (i in i_max:1) {
  106.     if (rooms[[r]][i] == '.' & !found) {
  107.       rooms[[r]][i] <- pawn
  108.       steps <- steps + i
  109.       found <- TRUE
  110.     }
  111.   }
  112.  
  113.   return(list(rooms, corridor, steps * cost[pawn]))
  114. }
  115.  
  116. # Gets neighboring states, prioritising c2r.
  117. # Returns c2r if any are found, else r2r if any are found, else r2c.
  118. get_neighbors <- function(rooms, corridor) {
  119.   neighbors <- list()
  120.  
  121.   found_c2r <- FALSE
  122.   for (r in 1:length(rooms)) {
  123.     for (c in 1:length(corridor)) {
  124.       c2r <- move_c2r(rooms, corridor, c, r)
  125.       if (!is.numeric(c2r)) {
  126.         found_c2r <- TRUE
  127.         neighbors[[length(neighbors) + 1]] <- c2r
  128.       }
  129.     }
  130.   }
  131.  
  132.   if (!found_c2r) {
  133.     found_r2r <- FALSE
  134.     for (r in 1:length(rooms)) {
  135.       for (s in 1:length(rooms)) {
  136.         r2r <- move_r2r(rooms, corridor, r, s)
  137.         if (!is.numeric(r2r)) {
  138.           found_r2r <- TRUE
  139.           neighbors[[length(neighbors) + 1]] <- r2r
  140.         }
  141.       }
  142.     }
  143.    
  144.     if (!found_r2r) {
  145.       for (r in 1:length(rooms)) {
  146.         for (c in 1:length(corridor)) {
  147.           r2c <- move_r2c(rooms, corridor, r, c)
  148.           if (!is.numeric(r2c)) {
  149.             neighbors[[length(neighbors) + 1]] <- r2c
  150.           }
  151.         }
  152.       }
  153.     }
  154.   }
  155.  
  156.   return(neighbors)
  157. }
  158.  
  159. # convenience functions for going from lists to arrays and viceversa
  160. as.flat <- function(rooms, corridor) {
  161.   paste0(paste0(map_chr(rooms, ~ paste0(., collapse = '')), collapse = ''),
  162.          paste0(corridor, collapse = ''),
  163.          collapse = '')
  164. }
  165.  
  166. unflat <- function(flat, n = 2) {
  167.   split <- unlist(str_split(flat, ''))
  168.  
  169.   if (n == 2) {
  170.     rooms <- list(c(split[1], split[2]), c(split[3], split[4]),
  171.                   c(split[5], split[6]), c(split[7], split[8]))
  172.     corridor <- split[9:19]
  173.   } else if (n == 4) {
  174.     rooms <- list(c(split[1], split[2], split[3], split[4]),
  175.                   c(split[5], split[6], split[7], split[8]),
  176.                   c(split[9], split[10], split[11], split[12]),
  177.                   c(split[13], split[14], split[15], split[16])
  178.     )
  179.     corridor <- split[17:27]
  180.   }
  181.  
  182.   return(list(rooms, corridor))
  183. }
  184.  
  185. # Heuristic for the A* algorithm.
  186. # Masures how far the corridor pawns are from their room.
  187. heuristic <- function(current, n) {
  188.   corridor <- unflat(current, n = n)[[1]]
  189.   h <- 0
  190.   for (pawn in c('A', 'B', 'C', 'D')) {
  191.     pos <- which(corridor == pawn)
  192.     if (length(pos)) {
  193.       h <- h + abs(pos - entrance[pawn]) * cost[pawn]
  194.     }
  195.   }
  196.   h
  197. }
  198.  
  199. a_star <- function(start_rooms, start_corridor, goal) {
  200.   start <- as.flat(start_rooms, start_corridor)
  201.   frontier <- priority_queue(start, 0)
  202.   came_from <- 'none' %>% setNames(start)
  203.   cost_so_far <- c(0) %>% setNames(start)
  204.   n <- length(start_rooms[[1]])
  205.  
  206.   i = 0
  207.   while (frontier$size()) {
  208.     if (i %% 1000 == 0) print(paste0('iter = ', i, '; max_cost = ', max(cost_so_far)))
  209.     current <- frontier$pop()
  210.     if (current == goal) {
  211.       return(cost_so_far[goal])
  212.     }
  213.    
  214.     neighbors <- get_neighbors(unflat(current, n = n)[[1]], unflat(current, n = n)[[2]])
  215.     for (neighbor in neighbors) {
  216.       flat_neighbor <- as.flat(neighbor[[1]], neighbor[[2]])
  217.       new_cost <- cost_so_far[current] + neighbor[[3]]
  218.       if (!(flat_neighbor %in% names(cost_so_far)) | new_cost < cost_so_far[flat_neighbor]) {
  219.         cost_so_far[flat_neighbor] <- new_cost
  220.         priority <- new_cost + heuristic(current, n = n)
  221.         frontier <- frontier$push(flat_neighbor, -priority)
  222.         came_from[flat_neighbor] <- current
  223.       }
  224.     }
  225.     i = i + 1
  226.   }
  227. }
  228.  
  229. # part 1
  230. t0 <- Sys.time()
  231. a_star(start_rooms = list(c('D', 'B'), c('D', 'A'), c('C', 'A'), c('B','C')),
  232.          start_corridor = rep('.', 11),
  233.          goal = 'AABBCCDD...........')
  234. print(Sys.time() - t0)
  235.  
  236. # part 2
  237. t0 <- Sys.time()
  238.   a_star(start_rooms = list(c('D', 'D', 'D', 'B'),
  239.                           c('D', 'C', 'B', 'A'),
  240.                           c('C','B', 'A', 'A'),
  241.                           c('B', 'A', 'C', 'C')),
  242.        start_corridor = rep('.', 11),
  243.        goal = 'AAAABBBBCCCCDDDD...........')
  244. print(Sys.time() - t0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement