old_contents: # Time:  O(1)
  # Space: O(min(f, r * c))
  
  # You are given the number of rows n_rows and
  # number of columns n_cols of a 2D binary matrix
  # where all values are initially 0.
  # Write a function flip which chooses a 0 value uniformly at random,
  # changes it to 1, and then returns the position [row.id, col.id] of
  # that value. Also, write a function reset which sets all values back to 0.
  # Try to minimize the number of calls to system's Math.random()
  # and optimize the time and space complexity.
  #
  # Note:
  # - 1 <= n_rows, n_cols <= 10000
  # - 0 <= row.id < n_rows and 0 <= col.id < n_cols
  # - flip will not be called when the matrix has no 0 values left.
  # - the total number of calls to flip and reset will not exceed 1000.
  # Example 1:
  #
  # Input: 
  # ["Solution","flip","flip","flip","flip"]
  # [[2,3],[],[],[],[]]
  # Output: [null,[0,1],[1,2],[1,0],[1,1]]
  # Example 2:
  #
  # Input: 
  # ["Solution","flip","flip","reset","flip"]
  # [[1,2],[],[],[],[]]
  # Output: [null,[0,0],[0,1],null,[0,0]]
  # Explanation of Input Syntax:
  #
  # The input is two lists:
  # the subroutines called and their arguments.
  # Solution's constructor has two arguments, n_rows and n_cols.
  # flip and reset have no arguments.
  # Arguments are always wrapped with a list, even if there aren't any.
  
  import random
  
  
  class Solution(object):
  
      def __init__(self, n_rows, n_cols):
          """
          :type n_rows: int
          :type n_cols: int
          """
          self.__n_rows = n_rows
          self.__n_cols = n_cols
          self.__n = n_rows*n_cols
          self.__lookup = {}
          
  
      def flip(self):
          """
          :rtype: List[int]
          """
          self.__n -= 1
          target = random.randint(0, self.__n)
          x = self.__lookup.get(target, target)
          self.__lookup[target] = self.__lookup.get(self.__n, self.__n)
          return divmod(x, self.__n_cols)
          
  
      def reset(self):
          """
          :rtype: void
          """
          self.__n = self.__n_rows*self.__n_cols
          self.__lookup = {}
          
  
  # Your Solution object will be instantiated and called as such:
  # obj = Solution(n_rows, n_cols)
  # param_1 = obj.flip()
  # obj.reset()
  
new_contents: # Time:  ctor:  O(1)
  #        flip:  O(1)
  #        reset: O(min(f, r * c))
  # Space: O(min(f, r * c))
  
  # You are given the number of rows n_rows and
  # number of columns n_cols of a 2D binary matrix
  # where all values are initially 0.
  # Write a function flip which chooses a 0 value uniformly at random,
  # changes it to 1, and then returns the position [row.id, col.id] of
  # that value. Also, write a function reset which sets all values back to 0.
  # Try to minimize the number of calls to system's Math.random()
  # and optimize the time and space complexity.
  #
  # Note:
  # - 1 <= n_rows, n_cols <= 10000
  # - 0 <= row.id < n_rows and 0 <= col.id < n_cols
  # - flip will not be called when the matrix has no 0 values left.
  # - the total number of calls to flip and reset will not exceed 1000.
  # Example 1:
  #
  # Input: 
  # ["Solution","flip","flip","flip","flip"]
  # [[2,3],[],[],[],[]]
  # Output: [null,[0,1],[1,2],[1,0],[1,1]]
  # Example 2:
  #
  # Input: 
  # ["Solution","flip","flip","reset","flip"]
  # [[1,2],[],[],[],[]]
  # Output: [null,[0,0],[0,1],null,[0,0]]
  # Explanation of Input Syntax:
  #
  # The input is two lists:
  # the subroutines called and their arguments.
  # Solution's constructor has two arguments, n_rows and n_cols.
  # flip and reset have no arguments.
  # Arguments are always wrapped with a list, even if there aren't any.
  
  import random
  
  
  class Solution(object):
  
      def __init__(self, n_rows, n_cols):
          """
          :type n_rows: int
          :type n_cols: int
          """
          self.__n_rows = n_rows
          self.__n_cols = n_cols
          self.__n = n_rows*n_cols
          self.__lookup = {}
          
  
      def flip(self):
          """
          :rtype: List[int]
          """
          self.__n -= 1
          target = random.randint(0, self.__n)
          x = self.__lookup.get(target, target)
          self.__lookup[target] = self.__lookup.get(self.__n, self.__n)
          return divmod(x, self.__n_cols)
          
  
      def reset(self):
          """
          :rtype: void
          """
          self.__n = self.__n_rows*self.__n_cols
          self.__lookup = {}
          
  
  # Your Solution object will be instantiated and called as such:
  # obj = Solution(n_rows, n_cols)
  # param_1 = obj.flip()
  # obj.reset()
  
subject: Update random-flip-matrix.py