程序代写案例-CSC148H1-Assignment 2

欢迎使用51辅导,51作业君孵化低价透明的学长辅导平台,服务保持优质,平均费用压低50%以上! 51fudao.top
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 1/15
Assignment 2
Automated Puzzle Solving
Due date: Thursday, April 8, 2021, before 1:00 pm sharp, Toronto time.
You may complete this assignment individually or with a partner who can be from any section of the course.
Learning goals
By the end of this assignment, you should be able to:
read complex code you didn’t write and understand its design and implementation, including:
reading the class and method docstrings carefully (including attributes, representation invariants, preconditions, etc.)
understanding relationships between classes, by applying your knowledge of composition and inheritance
complete a partial implementation of a class, including:
reading the representation invariants to enforce important facts about implementation decisions
reading the preconditions to factor in assumptions that they permit
writing the required methods according to their docstrings
use inheritance to define a subclass of an abstract parent class
implementing algorithms by translating their steps into python code by:
choosing an appropriate ADT to solve the problem
deciding if recursion is appropriate
implement recursive methods for trees when provided with their specifications.
perform unit testing on a program to verify correctness
And more specifically:
implement depth and breadth first searches to solve logic puzzles
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 2/15
implement a simple expression tree class
be able to implement additional logic puzzles beyond those in this assignment
explore the behaviour of depth and breadth first solvers on various logic puzzles
Coding Guidelines
These guidelines are designed to help you write well-designed code that will adhere to the interfaces we have defined.
You must:
write each method in such a way that the docstrings you have been given in the starter code accurately describe the body of the
method.
avoid writing duplicate code.
write a docstring for any class, function, or method that lacks one. *clarification added March 24th - you aren't required to add
docstrings to any of the provided code*
You must NOT:
change the parameters, parameter type annotations, or return types in any of the methods or functions you have been given in the
starter code.
add or remove any parameters in any of the methods you have been given in the starter code.
change the type annotations of any public or private attributes you have been given in the starter code.
create any new public attributes.
create any new public methods or functions.
write a method or function that mutates an object if the docstring doesn’t say that it will be mutated.
add any more import statements to your code, except for imports from the typing module and the modules you’re implementing in
this assignment.
You may find it helpful to:
create new private helper methods or functions for the classes you have been given.
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 3/15
if you create new private methods or functions you must provide type annotations for every parameter and return value. You
must also write a full docstring for each method as described in the function design recipe
(https://www.teach.cs.toronto.edu/~csc148h/winter/notes/python-recap/function_design_recipe.pdf)
create new private attributes for the classes you have been given.
if you create new private attributes you must give them a type annotation and include a description of them in the class’s
docstring as described in the class design recipe (https://www.teach.cs.toronto.edu/~csc148h/winter/notes/object-oriented-
programming/class_design_recipe.pdf)
import more types from the typing module
All code that you write should follow the function and class design recipes.
While writing your code you can assume that all arguments passed to the methods and functions you have been given in the
starter code will respect the preconditions and type annotations outlined in the provided docstrings.
Introduction: Problem Domain
Puzzle solving is a typically human activity that, in recent decades, has been explored in the context of computers. There are many
potential benefits to this. For example, we can offload some puzzle-solving tasks to computers, we may better understand human
puzzle-solving by programming computer puzzle solvers, or we might generate novel puzzles using a computer program.
This assignment investigates a class of puzzles that have the following features in common:
feature description
full information
all information about the puzzle state at any given point is visible to the solver; there
are no hidden or random aspects
well-defined extensions a definition of legal "extensions" from a given puzzle state to new states is given
well-defined solution a definition of what it means for the puzzle to be in a solved state is given
These features are common to a very large class of puzzles: crosswords, sudoku, peg solitaire, verbal arithmetic, and so on. This
assignment generalizes the required features into an abstract superclass Puzzle and solving such puzzles is written in terms of this
abstract class.
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 4/15
Once this is done, particular concrete puzzles can be modelled as subclasses of Puzzle and solved using the solve method of a
subclass of the Solver abstract class, which will be described later.
Although there may be faster puzzle-specific solvers for a particular puzzle that take advantage of specific features of that puzzle, the
general solvers you will build are designed to work for all puzzles of this sort.
The Puzzles
We will start by introducing how the puzzles will be represented and what specific puzzles we will consider in this assignment.
abstract Puzzle class
The abstract class Puzzle has the following methods: , which are not implemented, but meant to be implemented in subclasses:
method description
is_solved (abstract) returns True iff the puzzle is in a solved state
extensions (abstract)
returns a list of extensions from the current puzzle state to new states that are a single
‘move’ away
fail_fast (has a default implementation in
Puzzle )
returns True if it is clear that the puzzle can never, through a sequence of extensions,
move into a solved state
And that’s it! Note: each subclass will need its own __init__ method in order to represent that particular puzzle’s state information.
Sudoku
This puzzle commonly appears in print media and online. You are presented with an n × n grid with some symbols, for example digits
or letters, filled in. The symbols must be from a set of n symbols. The goal is to fill in the remaining symbols in such a way that each
row, column, and subsquare, contains each symbol exactly once. In order for all of that to make sense, n must be a square
integer such as 4, 9, 16, or 25.
×n


n


2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 5/15
You may want to read more about sudoku (https://en.wikipedia.org/wiki/Sudoku) to get a feel for the puzzle if you aren’t already
familiar with it.
Word Ladder
This puzzle involves transforming one word into a target word by changing one letter at a time. Each word must belong to a specified
set of valid words. Here’s an example where we assume that the set of valid words is a rather large set of common English words, and
the goal is to get from the word ‘cost’ to the word ‘save’:
cost → cast → case → cave → save
Expression Tree Puzzle
This puzzle consists of an algebraic equation containing one or more variables, and a target value. The puzzle is solved when the
variables are assigned values such that the expression evaluates to the target value.
The Solvers
Now that we know a bit about the puzzles that we will be implementing, we will turn our attention to how we will implement the solvers.
Searching
Solving a puzzle can be done by systematically searching for a solution, starting from its current state. To make this daunting task even
possible, we have to be sure that we have a systematic way of exploring all possible puzzle states - without needlessly re-visiting the
same state twice.
You will implement two systematic searching techniques.
The implicit tree underlying our search
To understand our searching techniques, it helps to think of the tree that is defined by all the possible states of a puzzle: each node is
one puzzle state, the root is the initial state of the puzzle, and the children of a node are its extensions (puzzle states that are one
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 6/15
move away).
When we actually implement the algorithms, we don't need to explicitly form this tree, but it is useful to remember that it is there. (The
A2: Search Algorithms Visual Guide (https://q.utoronto.ca/courses/204422/pages/a2-search-algorithms-visual-guide) examples for the
Word Ladder do a good job helping us visualize this tree.)
The search algorithms
Depth-first search and breadth-first search are two approaches to searching through the space of possibilities for a solution.
With depth-first search, we search deeply before we search broadly. We exhaustively search the first subtree before considering any
other subtree. And we use the same strategy when we search that subtree: exhaustively searching its first subtree before considering
any other subtree. And so on - think recursively!
With breadth-first search, we search broadly before we search deeply. We consider all puzzle states at depth 1, then all puzzle states
at depth 2, and so on until we have searched all puzzle states in our tree. (You will find a queue is helpful for keeping track of puzzles
states to be checked when their turn comes.) Because we consider states that are “closer” to the starting state before those that are
“farther”, we are guaranteed to find the shortest path to a puzzle’s solution.
For both solvers, we run the risk of encountering a puzzle state that we've already seen, and which already failed to produce a solution.
To avoid exploring that state all over again, we will keep track of states we've seen before and just ignore them if we encounter them
again.
For certain puzzle types, we might also be able to check whether we can quickly tell if a puzzle state is unsolvable. Such a check can
be incorporated into our search algorithms and you will do so in your implementation.
Rather than spell out the algorithms in full detail and simply have you translate them into code, we have put together some worked
examples (https://q.utoronto.ca/courses/204422/pages/a2-search-algorithms-visual-guide) - one of your tasks in this assignment will be
to turn the above high level descriptions and the concrete examples into 2 algorithms you can implement in Python!
The Solver Class
The abstract class Solver defines the interface for the following method:
method description
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 7/15
method description
solve
returns a path to a solution of a given puzzle. This
method is abstract and must be implemented in a
subclass.
You will create two subclasses of the Solver class - DfsSolver , which uses the depth first search strategy in its implementation of
solve , and BfsSolver , which uses the breadth first search strategy in its implementation of solve .
Setup and Starter Code
To get started:
1. Download a2.zip (https://q.utoronto.ca/courses/204422/files/13398949?wrap=1)
(https://q.utoronto.ca/courses/204422/files/13398949/download?download_frd=1) . It contains the starter code.
2. Unzip the file and place the contents in PyCharm in your a2 folder (remember to set your a2 folder as a sources root)
*NEW*
Note: In order to run the provided a2_starter_tests.py module, you will need to install the python package networkx , which is
imported by the expression_tree.py module in Task 4 (since the starter tests file contains tests for each of the tasks you will
complete).
Please follow the instructions at the bottom of the Software Guide’s Installing Python libraries section
(https://q.utoronto.ca/courses/204422/pages/software-guide#part-3-installing-python-libraries) to install the networkx package. Ask on
Piazza or visit office hours if you need help with this.
Tasks
We have broken down the assignment into several tasks. For the most part you, can tackle the assignment in any order that you want,
but note that Task 5 requires Task 4 and part of Task 3 requires Task 2. Task 6 is optional, but is a great way to try out your code and
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 8/15
see it in action!
After reading the handout, docstring examples, and comments in the starter code, please ask for clarification on Piazza if you
still find any of the specifications below to be unclear.
Any official clarifications will be added to the Assignment 2 FAQ (https://piazza.com/class/ki8belwj4u65yb?cid=2353) on Piazza.
Task 1: SudokuPuzzle
We provide you with a mostly-implemented subclass SudokuPuzzle of class Puzzle .
1. Read and understand the provided code in puzzle.py for the abstract Puzzle class.
2. Read through the SudokuPuzzle class. Understand how the puzzle is represented, how extensions is implemented, and familiarize
yourself with the provided helper methods. Note that some parts of the code use list comprehensions, as well as the functions any
and all . You do not need to use list comprehensions, but you may find them helpful in making your code simpler in the next step.
These are covered in a worksheet on list comprehensions (https://q.utoronto.ca/courses/204422/files/12900032?wrap=1) if you are
looking for a quick reference.
3. Implement fail_fast for the SudokuPuzzle class by having it return True for any sudoku where there is at least one empty position
that will be impossible to fill in because the set of symbols has been completely used up by other positions in the same row, column
or subsquare. You should run the provided doctests to test your code, but you are encouraged to add more doctests to fail_fast
(or write pytests) for further testing.
Task 2: solver.py
1. Read the docstrings provided in solver.py and familiarize yourself with the interface that the Puzzle class provides.
2. Go through the A2: Search Algorithms Visual Guide (https://q.utoronto.ca/courses/204422/pages/a2-search-algorithms-visual-
guide) (courtesy of Sophia!) to make sure you understand how the depth first and breadth first search algorithms work.
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 9/15
3. Implement the DfsSolver and BfsSolver classes in solver.py , based on the depth first search and breadth first search
algorithms described earlier.
The provided starter tests test_dfs_solver_example and test_bfs_solver_example in a2_starter_tests.py can be used as a starting
point for testing your solvers.
4. Many logic puzzles, like Sudoku, actually require their solution to be unique. Implement the has_unique_solution method in the
SudokuPuzzle class, based on its docstring description.
We'll be posting an additional play_sudoku.py module later (now available here
(https://q.utoronto.ca/courses/204422/files/13362316?wrap=1) (https://q.utoronto.ca/courses/204422/files/13362316/download?
download_frd=1) !) which will make use of this method to generate random sudoku for you!
Task 3: WordLadderPuzzle
1. Read and understand the provided code in word_ladder_puzzle.py .
2. Override the __str__ and __eq__ methods.
3. Override extensions . A legal extension of a WordLadderPuzzle is a new puzzle state where the new from_word differs by a single letter
from the previous from_word .
4. Override is_solved . The puzzle is solved when from_word is the same as to_word .
5. Implement method get_difficulty according to its docstring. (Requires Task 2)
Once you have completed the above methods and Task 2, you can try running the provided play_word_ladder.py module.
Note: We do NOT require you to implement fail_fast for this puzzle type, as it isn't entirely obvious what it should look like! Of course,
you are certainly welcome to attempt to devise a strategy to quickly check if a WordLadderPuzzle has no solution. Feel free to discuss
your approach on Piazza if you come up with anything good!
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 10/15
Task 4: ExprTree
Note: This part of the assignment requires you to install two python packages in order for your code to run (you don’t need to
write any code using them, but the code we have provided makes use of them): networkx and pygame_gui. You don’t need
pygame_gui except for in the optional Task 6, but you can install them both now.
Please follow the instructions at the bottom of the Software Guide’s Installing Python libraries section
(https://q.utoronto.ca/courses/204422/pages/software-guide#part-3-installing-python-libraries) to install these two packages. Ask on
Piazza or visit office hours if you need help with this.
Before we can implement the ExpressionTreePuzzle class, we need to develop an ExprTree class to represent an Expression Tree.
1. Read and understand the provided code in expression_tree.py .
2. Implement the methods in the ExprTree class, as specified in the starter code. Some additional details are provided below to help
you get started.
3. Implement the construct_from_list function at the bottom of expression_tree.py . (See below for a description of how this function
works.)
Expression Tree Specification
In this assignment, an expression tree can contain the single digit constants (1-9), single letter variables containing only the letters a-z,
and the operations: addition (+) and multiplication (*).
Numbers and variables are leaves of the tree.
Operators must have at least 2 children.
The same variable name may appear more than once in the expression tree.
Variables can be given single digit values 0-9. Note that unlike constants, variables can have a value of 0. (As we will see, in the
context of the ExpressionTreePuzzle class, the value 0 corresponds to an "unassigned variable".)
A Convenient Way to Construct Expression Trees
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 11/15
It is cumbersome to create a substantial expression tree using the initializer from class ExprTree . Function construct_from_list allows
client code to create one from a list of lists instead. Here is a simple example:
[['+'], [3, '*', 'a', '+'], ['a', 'b'], [5, 'c']]
The first '+' will be the root of the tree.
The next list contains the children of '+' : 3 , '*' , 'a' , and '+' . Of these, only the operators have children.
The next list contains the children of '*' : 'a' and 'b' . Neither has children itself.
And the last list contains the children of the second '+' : 5 and 'c' . Neither has children itself.
Hint: A queue can help keep track of whose children the next list contains.
Visually, the resulting expression tree looks like this (note we use the symbol to denote multiplication in the diagram):

This expression tree’s string representation would be: (3 + (a * b) + a + (5 + c))
Evaluating an ExprTree
In order to evaluate an expression tree, a variable lookup dictionary is provided to specify the value of each variable (see the eval
method). All variables in the expression must appear in the lookup dictionary.
For our example above, if the lookup dictionary was {'a': 0, 'b': 0, 'c': 0} , then the expression tree would evaluate to 8 .
×
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 12/15
If the lookup dictionary was instead {'a': 2, 'b': 5, 'c': 6} , then the expression tree would evaluate to 26 .
Task 5: ExpressionTreePuzzle
Once your ExprTree class is complete, you can implement the ExpressionTreePuzzle class in expression_tree_puzzle.py .
1. Read and understand the provided code in expression_tree_puzzle.py .
2. Override the __str__ method for the ExpressionTreePuzzle subclass in expression_tree_puzzle.py .
3. Override extensions . Legal extensions of a state assign a value from 1-9 to a single variable that has no assigned value. For
example, if the variables dictionary was formerly {'v': 0} , then each extension would assign a different value from 1-9 to 'v' . If
the variables dictionary was formerly {'v': 5} , then the puzzle would have no extensions, as all variables have been assigned a
non-zero value.
4. Override is_solved as specified in the code.
5. Implement fail_fast for the ExpressionTreePuzzle class. The exact implementation is up to you, but we have provided a couple of
hints in the code if you aren’t sure how to approach this.
Task 6: Try out your code!
Once you have completed the first 5 tasks you will be able to run:
play_sudoku.py (requires Tasks 1 and 2)
play_word_ladder.py (requires Tasks 2 and 3),
experiment.py (requires Tasks 2 and 3), and
play_expression_tree.py (requires Tasks 2, 4, and 5)
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 13/15
There are no marks for this part, but it can be a fun way to debug your code and further explore what you
can do with the code you have written.
Module play_sudoku.py (now posted! - download a2-play-sudoku.zip
(https://q.utoronto.ca/courses/204422/files/13362316?wrap=1)
(https://q.utoronto.ca/courses/204422/files/13362316/download?download_frd=1) and copy
the files into your a2 directory)
This module contains a simple GUI to let you try playing the sudoku puzzle you implemented. It makes use of your solvers in two ways:
(1) to create a random SudokuPuzzle of a selected difficulty level and (2) to provide you with hints as you try solving the puzzle. The
code also has a nice application of inheritance to let us add randomness to the puzzles we generate.
Module play_word_ladder.py
This module contains a simple text UI to let you try playing the word ladder puzzle you implemented. It makes use of your solvers in
two ways: (1) to create a random WordLadderPuzzle of a selected difficulty level and (2) to provide you with hints if you get stuck solving
the puzzle.
Module experiment.py
This module runs a small experiment and produces output that you can review to verify your understanding of how the solvers perform
on different puzzles. Feel free to add your own experiments and share any interesting observations you make with the class!
Sample Output:
Puzzle Type Solver len(sol) time
Sudoku Bfs 13 0.01907
Sudoku Dfs 13 0.00139
Sudoku Bfs 54 0.43171
Sudoku Dfs 54 0.15584
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 14/15
Puzzle Type Solver len(sol) time
WordLadder Bfs 5 0.03384
WordLadder Dfs 703 0.04225
Module play_expression_tree.py
This module contains a simple GUI to let you try playing the expression tree puzzle you implemented. It makes use of your solvers to
provide you with hints.
You are free to modify or add to any of the code provided in these 4 modules.
Polish!
Take some time to polish up. This step will improve your mark, but it also feels so good. Here are some things you can do:
In each module you are submitting, run the provided python_ta.check_all() code to check for errors and violations of the “PEP8”
Python style guidelines. Fix them!
Check your docstrings to make sure that they are precise, complete, and that they follow the conventions of the Function and Class
Design Recipes.
Read through and polish your internal comments.
Remove any code you added just for debugging, such as print statements.
Remove the word “TODO” wherever you have completed the task.
Take pride in your gorgeous code!
Submitting your work
Submit the following files on MarkUs (https://markus148.teach.cs.toronto.edu/csc148-2021-01/)
sudoku_puzzle.py
solver.py
2021/4/5 Assignment 2: CSC148H1 S (All Sections) 20211:Introduction to Computer Science
https://q.utoronto.ca/courses/204422/pages/assignment-2 15/15
Category Weight
pyTA 10 marks
MarkUs self tests 20 marks
hidden tests 70 marks
word_ladder_puzzle.py
expression_tree.py
expression_tree_puzzle.py
We strongly recommend that you submit early and run the provided self tests on MarkUs as you go.
We will grade the latest version you submit within the permitted submission period.
Be sure to run the tests we’ve provided within MarkUs one last time before the due date. This will make sure that you didn’t
accidentally submit the wrong version of your code, or worse yet, the starter code!
How your assignment will be marked
There will be no marks associated with defining your own test cases with pytest or hypothesis.
The marking scheme will be approximately as follows:


欢迎咨询51作业君
51作业君

Email:51zuoyejun

@gmail.com

添加客服微信: abby12468