LMU ☀️ CMSI 2130
ALGORITHMS
HOMEWORK #3 PARTIAL ANSWERS
  1. Backtracking engine:

    backtracker.py
    def solve(values, safe_up_to, size):
        """Finds a solution to a backtracking problem.
    
        values     -- a sequence of values to try, in order. For a map coloring
                      problem, this may be a list of colors, such as ['red',
                      'green', 'yellow', 'purple']
        safe_up_to -- a function with two arguments, solution and position, that
                      returns whether the values assigned to slots 0..pos in
                      the solution list, satisfy the problem constraints.
        size       -- the total number of “slots” you are trying to fill
    
        Return the solution as a list of values.
        """
        solution = [None] * size
    
        def extend_solution(position):
            for value in values:
                solution[position] = value
                if safe_up_to(solution, position):
                    if position >= size-1 or extend_solution(position+1):
                        return solution
            return None
    
        return extend_solution(0)
    

    Using it in the NEAS problem:

    neas.py
    import backtracker
    
    def no_adjacencies(string, up_to_index):
        # See if the sequence filled from indices 0 to up_to_index, inclusive, is
        # free of any adjancent substrings. We'll have to try all subsequences of
        # length 1, 2, 3, up to half the length of the string. Return False as soon
        # as we find an equal adjacent pair.
        length = up_to_index+1
        for j in range(1, length//2+1):
            if (string[length-2*j:length-j] == string[length-j:length]):
                return False
        return True
    
    print(''.join(str(v) for v in backtracker.solve(range(3), no_adjacencies, 50)))
    
    $ python3 neas.py
    01020120210120102012021020102101201020120210120102
    

    Using it in the 8-Queens problem:

    queens.py
    import backtracker
    
    def no_conflicts(board, up_to_column):
        # See if any queens in columns to the left of up_to_column interfere with
        # the queen in up_to_column. Return False as soon as you find one that does.
        for col in range(up_to_column):
            if (board[col] == board[up_to_column]                           # same row
                or board[col] == board[up_to_column] + up_to_column - col   # diagonal
                or board[col] == board[up_to_column] + col - up_to_column): # diagonal
                return False
        return True
    
    print(backtracker.solve(range(8), no_conflicts, 8))
    
    $ python3 queens.py
    [0, 4, 7, 5, 2, 6, 1, 3]
    
  2. Sorry, I’ve been asked not to post the answers to the KSP (Kirkman’s Schoolgirl Program) online. See me if you are desperate to see a solved version.