Prison Cells After N Days

medium array simulation cycle detection

Problem

There are 8 prison cells in a row, each either occupied (1) or vacant (0). Every day the cells change at once: a cell becomes occupied if its two adjacent neighbors are both occupied or both vacant, otherwise it becomes vacant. The two cells at the ends have only one neighbor, so they always become vacant. Given the initial state and an integer n, return the state after n days. Because the state space is tiny, the sequence is eventually periodic, so we detect the cycle and skip ahead instead of simulating every day.

Inputcells = [0,1,0,1,1,0,0,1], n = 7
Output[0,0,1,1,0,0,0,0]
After day 1 the cells become [0,1,1,0,0,0,0,0]; applying the rule seven times gives the result.

def prison_after_n_days(cells, n):
    def step(c):
        return [0] + [1 if c[i - 1] == c[i + 1] else 0
                      for i in range(1, 7)] + [0]
    seen = {}
    while n > 0:
        key = tuple(cells)
        if key in seen:
            n %= seen[key] - n
        seen[key] = n
        if n >= 1:
            n -= 1
            cells = step(cells)
    return cells
function prisonAfterNDays(cells, n) {
  const step = (c) => c.map((_, i) =>
    (i === 0 || i === 7) ? 0 : (c[i - 1] === c[i + 1] ? 1 : 0));
  const seen = new Map();
  while (n > 0) {
    const key = cells.join("");
    if (seen.has(key)) n %= seen.get(key) - n;
    seen.set(key, n);
    if (n >= 1) {
      n -= 1;
      cells = step(cells);
    }
  }
  return cells;
}
class Solution {
    public int[] prisonAfterNDays(int[] cells, int n) {
        Map<String, Integer> seen = new HashMap<>();
        while (n > 0) {
            String key = Arrays.toString(cells);
            if (seen.containsKey(key)) n %= seen.get(key) - n;
            seen.put(key, n);
            if (n >= 1) {
                n--;
                int[] next = new int[8];
                for (int i = 1; i < 7; i++)
                    next[i] = cells[i - 1] == cells[i + 1] ? 1 : 0;
                cells = next;
            }
        }
        return cells;
    }
}
vector<int> prisonAfterNDays(vector<int>& cells, int n) {
    unordered_map<string, int> seen;
    while (n > 0) {
        string key(cells.begin(), cells.end());
        if (seen.count(key)) n %= seen[key] - n;
        seen[key] = n;
        if (n >= 1) {
            n--;
            vector<int> next(8, 0);
            for (int i = 1; i < 7; i++)
                next[i] = cells[i - 1] == cells[i + 1] ? 1 : 0;
            cells = next;
        }
    }
    return cells;
}
Time: O(1) (at most 2⁸ distinct states) Space: O(1)