hhoppe

Advent of code 2021 day 23 compact

Dec 23rd, 2021 (edited)
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.58 KB | None | 0 0
  1. def process1(s, part2=False):
  2.   lines = s.strip('\n').split('\n')
  3.   letters = [[line[3], line[5], line[7], line[9]] for line in lines[2:4]]
  4.   if part2:
  5.     letters[1:1] = [list('DCBA'), list('DBAC')]  # Insert two middle rows.
  6.   nrows = len(letters)
  7.   # State consists of the 7 eligible hallway locations and the room locations.
  8.   start_state = tuple(['.'] * 7 + list(itertools.chain(*letters)))
  9.   end_state = tuple(['.'] * 7 + list('ABCD') * nrows)
  10.   cost_for_id = {'A': 1, 'B': 10, 'C': 100, 'D': 1000}
  11.  
  12.   @functools.lru_cache(maxsize=None)
  13.   def compute_cost(state):
  14.     if state == end_state:
  15.       return 0
  16.     min_cost = 10**8
  17.  
  18.     # Explore moving an item from position i0 to i1, and update min cost.
  19.     def consider(i0, i1, distance):
  20.       nonlocal min_cost
  21.       id = state[i0]  # id in 'ABCD'
  22.       state2 = list(state)
  23.       state2[i0] = '.'
  24.       state2[i1] = id  # (previously '.')
  25.       candidate_cost = distance * cost_for_id[id] + compute_cost(tuple(state2))
  26.       min_cost = min(min_cost, candidate_cost)
  27.  
  28.     # Move from the hallway position `i0` to a room `j`.
  29.     for i0 in range(7):
  30.       id = state[i0]
  31.       if id not in 'ABCD':
  32.         continue
  33.       j = ord(id) - 65
  34.       row = max((i for i in range(nrows) if state[7 + i * 4 + j] == '.'),
  35.                 default=None)
  36.       if (row is None or
  37.           not all(state[7 + i * 4 + j] == id for i in range(row + 1, nrows))):
  38.         continue
  39.       i1 = 7 + row * 4 + j
  40.       move_right = i0 <= j + 1
  41.       if all(state[k] == '.' for k in (
  42.           range(i0 + 1, 2 + j) if move_right else range(2 + j, i0))):
  43.         distance = ((j - i0 + 2) * 2 - (i0 == 0) + row if move_right else
  44.                     (i0 - j - 1) * 2 - (i0 == 6) + row)
  45.         consider(i0, i1, distance)
  46.  
  47.     # Move from a room `j` to the hallway position `i1`.
  48.     for j in range(4):
  49.       row = min((i for i in range(nrows) if state[7 + i * 4 + j] != '.'),
  50.                 default=None)
  51.       if row is None:
  52.         continue
  53.       i0 = 7 + row * 4 + j
  54.       id = state[i0]
  55.       if (id in ['.', chr(65 + j)] and not any(
  56.           state[7 + i * 4 + j] != id for i in range(row + 1, nrows))):
  57.         continue
  58.       for i1 in range(2 + j, 7):  # Move right in hallway.
  59.         if all(state[k] == '.' for k in range(2 + j, i1 + 1)):
  60.           consider(i0, i1, (i1 - j - 1) * 2 - (i1 == 6) + row)
  61.       for i1 in range(0, 2 + j):  # Move left in hallway
  62.         if all(state[k] == '.' for k in range(i1, 2 + j)):
  63.           consider(i0, i1, (j - i1 + 2) * 2 - (i1 == 0) + row)
  64.  
  65.     return min_cost
  66.  
  67.   return compute_cost(start_state)
Add Comment
Please, Sign In to add comment