2 files in total
n_queens_checker.py
A PDF that contains your self-assessment & reflection
To prepare for lab, if you plan on using your own personal computer to develop code, be sure to have installed and set up VS Code.
You'll be creating a program in a file that must be named (EXACTLY, no spaces, respecting capitalization):
n_queens_checker.py
Review the solutions to perform a self-assessment and write your reflection.
You may write up your self-assessment and reflection in whatever format is most comfortable for you (written on paper, typed in a Word or Google Doc, etc.), but you must convert it to a PDF before submitting. Please ask if you need help with this!
Submit the PDF to Gradescope and name it SelfAssessmentReflection.pdf.
Homeworks are an opportunity to engage with the material and practice your programming skills. To support you, solutions will be available on moodle. It is your responsibility to engage with them in a way that strategically moves your learning forward. You should:
Attempt the homework without looking at the solutions.
Review the solutions; if you were stuck, you may revise your homework. You may find yourself iteratively reviewing and revising to best support your learning.
When you submit your homework, you will be required to complete a self-assessment and reflection:
Give yourself an assessment mark on the initial attempt:
✘ if you did not complete it
✓- if you completed it, but were very far from the solution
✓ if you completed it and essentially had the solution
✓+ if you completed it correctly, including precise communication
? if you are unsure as to whether or not you completed it
Provide a short reflection as to why you earned that mark, such as:
I did not understand how to get started, and it was too close to the deadline to visit support hours.
I got stumped by a bug where my program entered an infinite loop.
If you used the solutions to revise your work, describe what you needed to change, as in:
I modified the style of my conditional when I saw a simpler approach in the solutions.
I was so stuck that the majority of my submission is based on the solutions.
Ask specific questions on portions that are still confusing, such as:
Why does it cause an error when I returned "1" instead of 1?
[Optional] Provide one hint for the homework (to your past self or future student).
While Coding Rooms has been a nice IDE, it has a few limitations. In particular, it lacks a "debugger" which allows you to pause execution of your program and inspect memory (similar to how Python Tutor supports visualization). For the remainder of the semester, we'll shift to using a more standard IDE and, for consistency, choose the freely available and widely-used IDE VSCode.
If you plan on developing your projects on your personal machines, in advance of your lab next week (Wednesday 3/30 or Thursday 3/31), please make sure to download and install VSCode to support Python programming. You can use these two videos that Charlie created to help you:
This homework will give you a chance to practice with 2D lists. In an earlier module led by your mentors in lab, you worked on the "Paranoid Prof" challenge. This problem is known as the n-Queens problem, based on how a Queen piece can attack on a chessboard (a Queen can attack another piece in the same row or in the same column or in the same diagonal). To refresh your memory, here is the setup you saw in the module:
You show up to a final for one of your classes. For some reason your professor is super paranoid about the possibility of cheating. You and your classmates decide to try to reassure your professor by sitting as far apart as possible. There are 8 students in your class (including you), and there are 8 rows and columns of desks. You and your classmates decide to make sure no two students occupy the same row, or the same column. But your professor is still paranoid! So you also decide to make sure no two students are sitting in the same diagonal. Task: Place all 8 students at a desk in a way that reduces the number of students in the same row, column or diagonal.
When you worked on this, you probably had two different processes that you were balancing:
Checking if a (partial) configuration of students was valid or invalid
Solving to find a valid configuration
In this homework, we'll focus on the first process of checking for valid/invalid configurations. We'll need to specify this a little more to be able to write a program. Often, we have a modeling phase, where we decide how to model the problem in code. Here is a how we can model the n-Queens problem:
We can use a 2D grid of boolean values to model an nxn chess board
Each cell of the 2D grid models a square of the chess board
A True value in a cell models that a Queen is placed in that square
A False value in a cell models that the square is empty
Based on this model, we can then specify the problem for this homework:
Given a 2D list of boolean values of True and False values, determine if any row, column or diagonal contains more than one True value. If so, return True; otherwise, return False.
practice with 2D lists
practice designing a solution to a problem and implement your solution
continue practicing type-hinting and using mypy to make sure types are consistent
Be strategic!
Start early!
Ask questions!
Leave time for questions by... starting early :)
When you're stuck, pause and evaluate what could be going on. Remember the self-regulated learning cycle!
Do you have a plan?
Are you evaluating your plan? How will you test your code as you go?
How will you revise? What will you do when you're confused? Stuck?
Before you attempt to write any Python code, you should start with a plan and move towards pseudocode. Here are some prompts to help you think about your plan:
How will you break the problem into smaller subproblems (perhaps you could check by row, then by column, then by diagonal)?
For each subproblem, consider:
What function do you need to write?
What are the expected interactions with that function (remember, this helps you identify its parameters and return value)?
What is its expected behavior?
How will you implement the behavior? Write your approach in pseudocode; you have many examples from prior homeworks and projects. Strive to have pseudocode where you feel confident you can implement each line with a couple lines of Python code.
Requirements
You must support checking whether two (or more) queens are in the same row or column.
It is a bonus to check if two (or more) queens are in the same diagonal.
When working with indices of a 2D grid, it's incredibly helpful to have pen/pencil and paper. Draw out a sample grid (e.g., a 4x4 board) and label the rows and columns (the way you did in Lab 8). Then write down the row and column indices for a particular example before looking for a pattern that you can generalize with variables.
Implement your design and pseudocode, remembering that it's best to have stubs and test as you go.
Requirements
To make sure that the autograder can run, you will need to have your highest-level function have this signature:
def validQueensConfiguration( grid:list ) -> bool:
""" Given a 2D grid of boolean values, determine if
any row, column or diagonal contains more than 1 True value.
If so, return False; otherwise (when it is a valid n-Queens
configuration), return True. """
Diagonal checking
It is a bonus (great experience, but not required!) to check if there are two or more queens in a diagonal. It is a little tricky to figure out the indices, so you can use the code below to solve this part of the problem.
Diagonal checking code
def validQueensDiagonals( grid:list ) -> bool:
""" Given a 2D grid of boolean values, determine if
any diagonal contains more than 1 True value.
If so, return False; otherwise (when it is a valid n-Queens
configuration in terms of diagonals), return True. """
# first check diagonals that are the same direction as a forward /
forwardCheck:bool = validQueensForwardDiagonals( grid )
# then check diagonals that are the same direction as a backslash \
backwardCheck:bool = validQueensBackwardDiagonals( grid )
return forwardCheck and backwardCheck
def validQueensForwardDiagonals( grid:list ) -> bool:
""" Given a 2D grid of boolean values, determine if
any forward (/) diagonal contains more than 1 True value.
If so, return False; otherwise (when it is a valid n-Queens
configuration in terms of forward diagonals), return True. """
n:int = len(grid)
# we'll traverse diagonals in terms of offset from the main
for offset in range( -(n-2),n-1 ):
numTrues:int = 0
for row in range( n ):
col:int = n - 1 - row + offset
# if in bounds
if (col >= 0) and (col < n):
# check if it has a queen
if grid[row][col]:
numTrues += 1
# if we found more than 1 True, this is not a valid configuration
if numTrues > 1:
return False
# if we make it through the whole grid, we never found a column with > 1 True
return True
def validQueensBackwardDiagonals( grid:list ) -> bool:
""" Given a 2D grid of boolean values, determine if
any forward (/) diagonal contains more than 1 True value.
If so, return False; otherwise (when it is a valid n-Queens
configuration in terms of forward diagonals), return True. """
n:int = len(grid)
# we'll traverse diagonals in terms of offset from the main
for offset in range( -(n-2),n-1 ):
numTrues:int = 0
for row in range( n ):
col:int = row + offset
# if in bounds
if (col >= 0) and (col < n):
# check if it has a queen
if grid[row][col]:
numTrues += 1
# if we found more than 1 True, this is not a valid configuration
if numTrues > 1:
return False
# if we make it through the whole grid, we never found a column with > 1 True
return True
To help you with testing, here is some starting code for your main function. You should add a few more test grids, though we will work more on how to test effectively during Lab 9.
Testing code
def main():
# test invalid configurations
invalidTests:list = [
# two in last row
[[False,False, True],
[False,False,False],
[ True, True,False]],
# two in middle col
[[False, True,False],
[False,False,False],
[False, True,False]],
# backward diagonal
[[ True,False,False],
[False, True,False],
[False,False, True]],
# backward upper diagonal
[[False, True,False],
[False,False, True],
[ True,False,False]],
# backward lower diagonal
[[False,False, True],
[ True,False,False],
[False, True,False]],
# forward diagonal
[[False,False, True],
[False, True,False],
[True,False,False]],
# forward upper diagonal
[[False, True,False],
[ True,False,False],
[False,False, True]],
# forward lower diagonal
[[ True,False,False],
[False,False, True],
[False, True,False]],
# larger grid
[[False, True,False, True],
[False,False,False,False],
[False,False, True,False],
[False, True,False,False]]]
for invalidGrid in invalidTests:
print( f"Expected: False, Actual: {validQueensConfiguration(invalidGrid)}")
# test valid configurations
validTests:list = [
[[ True,False,False],
[False,False, True],
[False,False,False]],
[[False,False,False],
[False,False, True],
[ True,False,False]],
[[False, True,False,False],
[False,False,False, True],
[ True,False,False,False],
[False,False, True,False]],
[[False,False,False, True,False],
[False, True,False,False,False],
[False,False,False,False, True],
[False,False, True,False,False],
[ True,False,False,False,False]]]
for validGrid in validTests:
print( f"Expected: True, Actual: {validQueensConfiguration(validGrid)}")
Some bugs are "easy" to detect in that Python will actually print out an error.
Use the error message to identify where the bug is.
The line number is a great starting point!
Some bugs are "logical" bugs, which are a bit harder to identify and fix. For the buggy code given to you, identify them by looking at the
Focus on examples where the expected output does not match the actual output to help isolate the bug(s)
Draw memory and trace the program to understand how Python is interpreting the code
Use print statements to gain insight into memory and narrow down the source(s) of the bug(s)
Use the comments to help you understand the high-level approach; there is a logical bug whenever the Python code does not implement the high-level approach