Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Chapter1/fib2.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@


def fib2(n: int) -> int:
if n < 2: # base case
return n
return fib2(n - 2) + fib2(n - 1) # recursive case
return n if n < 2 else fib2(n - 2) + fib2(n - 1)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function fib2 refactored with the following changes:

This removes the following comments ( why? ):

# base case
# recursive case



if __name__ == "__main__":
Expand Down
4 changes: 1 addition & 3 deletions Chapter1/fib4.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@

@lru_cache(maxsize=None)
def fib4(n: int) -> int: # same definition as fib2()
if n < 2: # base case
return n
return fib4(n - 2) + fib4(n - 1) # recursive case
return n if n < 2 else fib4(n - 2) + fib4(n - 1)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function fib4 refactored with the following changes:

This removes the following comments ( why? ):

# base case
# recursive case



if __name__ == "__main__":
Expand Down
20 changes: 11 additions & 9 deletions Chapter1/trivial_compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,22 @@ def _compress(self, gene: str) -> None:
elif nucleotide == "T": # change last two bits to 11
self.bit_string |= 0b11
else:
raise ValueError("Invalid Nucleotide:{}".format(nucleotide))
raise ValueError(f"Invalid Nucleotide:{nucleotide}")
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CompressedGene._compress refactored with the following changes:


def decompress(self) -> str:
gene: str = ""
for i in range(0, self.bit_string.bit_length() - 1, 2): # - 1 to exclude sentinel
bits: int = self.bit_string >> i & 0b11 # get just 2 relevant bits
if bits == 0b00: # A
if bits == 0b00:
gene += "A"
elif bits == 0b01: # C
elif bits == 0b01:
gene += "C"
elif bits == 0b10: # G
elif bits == 0b10:
gene += "G"
elif bits == 0b11: # T
elif bits == 0b11:
gene += "T"
else:
raise ValueError("Invalid bits:{}".format(bits))
raise ValueError(f"Invalid bits:{bits}")
Comment on lines -41 to +50
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CompressedGene.decompress refactored with the following changes:

This removes the following comments ( why? ):

# C
# T
# G
# A

return gene[::-1] # [::-1] reverses string by slicing backwards

def __str__(self) -> str: # string representation for pretty printing
Expand All @@ -57,8 +57,10 @@ def __str__(self) -> str: # string representation for pretty printing
if __name__ == "__main__":
from sys import getsizeof
original: str = "TAGGGATTAACCGTTATATATATATAGCCATGGATCGATTATATAGGGATTAACCGTTATATATATATAGCCATGGATCGATTATA" * 100
print("original is {} bytes".format(getsizeof(original)))
print(f"original is {getsizeof(original)} bytes")
compressed: CompressedGene = CompressedGene(original) # compress
print("compressed is {} bytes".format(getsizeof(compressed.bit_string)))
print(f"compressed is {getsizeof(compressed.bit_string)} bytes")
print(compressed) # decompress
print("original and decompressed are the same: {}".format(original == compressed.decompress()))
print(
f"original and decompressed are the same: {original == compressed.decompress()}"
)
5 changes: 1 addition & 4 deletions Chapter2/dna_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ def string_to_gene(s: str) -> Gene:


def linear_contains(gene: Gene, key_codon: Codon) -> bool:
for codon in gene:
if codon == key_codon:
return True
return False
return key_codon in gene
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function linear_contains refactored with the following changes:



acg: Codon = (Nucleotide.A, Nucleotide.C, Nucleotide.G)
Expand Down
5 changes: 1 addition & 4 deletions Chapter2/generic_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@


def linear_contains(iterable: Iterable[T], key: T) -> bool:
for item in iterable:
if item == key:
return True
return False
return key in iterable
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function linear_contains refactored with the following changes:



C = TypeVar("C", bound="Comparable")
Expand Down
16 changes: 8 additions & 8 deletions Chapter2/maze.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ def __init__(self, rows: int = 10, columns: int = 10, sparseness: float = 0.2, s
self.start: MazeLocation = start
self.goal: MazeLocation = goal
# fill the grid with empty cells
self._grid: List[List[Cell]] = [[Cell.EMPTY for c in range(columns)] for r in range(rows)]
self._grid: List[List[Cell]] = [
[Cell.EMPTY for _ in range(columns)] for _ in range(rows)
]

Comment on lines -44 to +47
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function Maze.__init__ refactored with the following changes:

# populate the grid with blocked cells
self._randomly_fill(rows, columns, sparseness)
# fill the start and goal locations in
Expand All @@ -56,10 +59,7 @@ def _randomly_fill(self, rows: int, columns: int, sparseness: float):

# return a nicely formatted version of the maze for printing
def __str__(self) -> str:
output: str = ""
for row in self._grid:
output += "".join([c.value for c in row]) + "\n"
return output
return "".join("".join([c.value for c in row]) + "\n" for row in self._grid)
Comment on lines -59 to +62
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function Maze.__str__ refactored with the following changes:


def goal_test(self, ml: MazeLocation) -> bool:
return ml == self.goal
Expand All @@ -68,11 +68,11 @@ def successors(self, ml: MazeLocation) -> List[MazeLocation]:
locations: List[MazeLocation] = []
if ml.row + 1 < self._rows and self._grid[ml.row + 1][ml.column] != Cell.BLOCKED:
locations.append(MazeLocation(ml.row + 1, ml.column))
if ml.row - 1 >= 0 and self._grid[ml.row - 1][ml.column] != Cell.BLOCKED:
if ml.row >= 1 and self._grid[ml.row - 1][ml.column] != Cell.BLOCKED:
locations.append(MazeLocation(ml.row - 1, ml.column))
if ml.column + 1 < self._columns and self._grid[ml.row][ml.column + 1] != Cell.BLOCKED:
locations.append(MazeLocation(ml.row, ml.column + 1))
if ml.column - 1 >= 0 and self._grid[ml.row][ml.column - 1] != Cell.BLOCKED:
if ml.column >= 1 and self._grid[ml.row][ml.column - 1] != Cell.BLOCKED:
Comment on lines -71 to +75
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function Maze.successors refactored with the following changes:

locations.append(MazeLocation(ml.row, ml.column - 1))
return locations

Expand All @@ -93,7 +93,7 @@ def euclidean_distance(goal: MazeLocation) -> Callable[[MazeLocation], float]:
def distance(ml: MazeLocation) -> float:
xdist: int = ml.column - goal.column
ydist: int = ml.row - goal.row
return sqrt((xdist * xdist) + (ydist * ydist))
return sqrt(xdist**2 + ydist**2)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function euclidean_distance.distance refactored with the following changes:

return distance


Expand Down
2 changes: 1 addition & 1 deletion Chapter2/missionaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def successors(self) -> List[MCState]:


def display_solution(path: List[MCState]):
if len(path) == 0: # sanity check
if not path: # sanity check
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function display_solution refactored with the following changes:

return
old_state: MCState = path[0]
print(old_state)
Expand Down
8 changes: 4 additions & 4 deletions Chapter3/csp.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ def add_constraint(self, constraint: Constraint[V, D]) -> None:
# Check if the value assignment is consistent by checking all constraints
# for the given variable against it
def consistent(self, variable: V, assignment: Dict[V, D]) -> bool:
for constraint in self.constraints[variable]:
if not constraint.satisfied(assignment):
return False
return True
return all(
constraint.satisfied(assignment)
for constraint in self.constraints[variable]
)
Comment on lines -58 to +61
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CSP.consistent refactored with the following changes:


def backtracking_search(self, assignment: Dict[V, D] = {}) -> Optional[Dict[V, D]]:
# assignment is complete if every variable is assigned (our base case)
Expand Down
7 changes: 4 additions & 3 deletions Chapter3/map_coloring.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ def satisfied(self, assignment: Dict[str, str]) -> bool:
if __name__ == "__main__":
variables: List[str] = ["Western Australia", "Northern Territory", "South Australia",
"Queensland", "New South Wales", "Victoria", "Tasmania"]
domains: Dict[str, List[str]] = {}
for variable in variables:
domains[variable] = ["red", "green", "blue"]
domains: Dict[str, List[str]] = {
variable: ["red", "green", "blue"] for variable in variables
}

Comment on lines -39 to +42
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 39-41 refactored with the following changes:

csp: CSP[str, str] = CSP(variables, domains)
csp.add_constraint(MapColoringConstraint("Western Australia", "Northern Territory"))
csp.add_constraint(MapColoringConstraint("Western Australia", "South Australia"))
Expand Down
7 changes: 4 additions & 3 deletions Chapter3/queens.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ def satisfied(self, assignment: Dict[int, int]) -> bool:

if __name__ == "__main__":
columns: List[int] = [1, 2, 3, 4, 5, 6, 7, 8]
rows: Dict[int, List[int]] = {}
for column in columns:
rows[column] = [1, 2, 3, 4, 5, 6, 7, 8]
rows: Dict[int, List[int]] = {
column: [1, 2, 3, 4, 5, 6, 7, 8] for column in columns
}

Comment on lines -41 to +44
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 41-43 refactored with the following changes:

csp: CSP[int, int] = CSP(columns, rows)
csp.add_constraint(QueensConstraint(columns))
solution: Optional[Dict[int, int]] = csp.backtracking_search()
Expand Down
7 changes: 4 additions & 3 deletions Chapter3/send_more_money.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ def satisfied(self, assignment: Dict[str, int]) -> bool:

if __name__ == "__main__":
letters: List[str] = ["S", "E", "N", "D", "M", "O", "R", "Y"]
possible_digits: Dict[str, List[int]] = {}
for letter in letters:
possible_digits[letter] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
possible_digits: Dict[str, List[int]] = {
letter: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for letter in letters
}

Comment on lines -49 to +52
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 49-51 refactored with the following changes:

possible_digits["M"] = [1] # so we don't get answers starting with a 0
csp: CSP[str, int] = CSP(letters, possible_digits)
csp.add_constraint(SendMoreMoneyConstraint(letters))
Expand Down
9 changes: 5 additions & 4 deletions Chapter3/word_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class GridLocation(NamedTuple):

def generate_grid(rows: int, columns: int) -> Grid:
# initialize grid with random letters
return [[choice(ascii_uppercase) for c in range(columns)] for r in range(rows)]
return [[choice(ascii_uppercase) for _ in range(columns)] for _ in range(rows)]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function generate_grid refactored with the following changes:



def display_grid(grid: Grid) -> None:
Expand Down Expand Up @@ -74,9 +74,10 @@ def satisfied(self, assignment: Dict[str, List[GridLocation]]) -> bool:
if __name__ == "__main__":
grid: Grid = generate_grid(9, 9)
words: List[str] = ["MATTHEW", "JOE", "MARY", "SARAH", "SALLY"]
locations: Dict[str, List[List[GridLocation]]] = {}
for word in words:
locations[word] = generate_domain(word, grid)
locations: Dict[str, List[List[GridLocation]]] = {
word: generate_domain(word, grid) for word in words
}

Comment on lines -77 to +80
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 77-79 refactored with the following changes:

csp: CSP[str, List[GridLocation]] = CSP(words, locations)
csp.add_constraint(WordSearchConstraint(words))
solution: Optional[Dict[str, List[GridLocation]]] = csp.backtracking_search()
Expand Down
10 changes: 3 additions & 7 deletions Chapter4/dijkstra.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,16 @@ def dijkstra(wg: WeightedGraph[V], root: V) -> Tuple[List[Optional[float]], Dict

# Helper function to get easier access to dijkstra results
def distance_array_to_vertex_dict(wg: WeightedGraph[V], distances: List[Optional[float]]) -> Dict[V, Optional[float]]:
distance_dict: Dict[V, Optional[float]] = {}
for i in range(len(distances)):
distance_dict[wg.vertex_at(i)] = distances[i]
return distance_dict
return {wg.vertex_at(i): distances[i] for i in range(len(distances))}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function distance_array_to_vertex_dict refactored with the following changes:



# Takes a dictionary of edges to reach each node and returns a list of
# edges that goes from `start` to `end`
def path_dict_to_path(start: int, end: int, path_dict: Dict[int, WeightedEdge]) -> WeightedPath:
if len(path_dict) == 0:
if not path_dict:
return []
edge_path: WeightedPath = []
e: WeightedEdge = path_dict[end]
edge_path.append(e)
edge_path: WeightedPath = [e]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function path_dict_to_path refactored with the following changes:

while e.u != start:
e = path_dict[e.u]
edge_path.append(e)
Expand Down
8 changes: 4 additions & 4 deletions Chapter4/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ def edges_for_vertex(self, vertex: V) -> List[Edge]:

# Make it easy to pretty-print a Graph
def __str__(self) -> str:
desc: str = ""
for i in range(self.vertex_count):
desc += f"{self.vertex_at(i)} -> {self.neighbors_for_index(i)}\n"
return desc
return "".join(
f"{self.vertex_at(i)} -> {self.neighbors_for_index(i)}\n"
for i in range(self.vertex_count)
)
Comment on lines -85 to +88
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function Graph.__str__ refactored with the following changes:



if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion Chapter4/mst.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@


def total_weight(wp: WeightedPath) -> float:
return sum([e.weight for e in wp])
return sum(e.weight for e in wp)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function total_weight refactored with the following changes:



def mst(wg: WeightedGraph[V], start: int = 0) -> Optional[WeightedPath]:
Expand Down
16 changes: 8 additions & 8 deletions Chapter4/weighted_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ def add_edge_by_vertices(self, first: V, second: V, weight: float) -> None:
self.add_edge_by_indices(u, v, weight)

def neighbors_for_index_with_weights(self, index: int) -> List[Tuple[V, float]]:
distance_tuples: List[Tuple[V, float]] = []
for edge in self.edges_for_index(index):
distance_tuples.append((self.vertex_at(edge.v), edge.weight))
return distance_tuples
return [
(self.vertex_at(edge.v), edge.weight)
for edge in self.edges_for_index(index)
]
Comment on lines -38 to +41
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function WeightedGraph.neighbors_for_index_with_weights refactored with the following changes:


def __str__(self) -> str:
desc: str = ""
for i in range(self.vertex_count):
desc += f"{self.vertex_at(i)} -> {self.neighbors_for_index_with_weights(i)}\n"
return desc
return "".join(
f"{self.vertex_at(i)} -> {self.neighbors_for_index_with_weights(i)}\n"
for i in range(self.vertex_count)
)
Comment on lines -44 to +47
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function WeightedGraph.__str__ refactored with the following changes:



if __name__ == "__main__":
Expand Down
9 changes: 4 additions & 5 deletions Chapter5/simple_equation.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ def mutate(self) -> None:
self.x += 1
else:
self.x -= 1
else: # otherwise mutate y
if random() > 0.5:
self.y += 1
else:
self.y -= 1
elif random() > 0.5:
self.y += 1
else:
self.y -= 1
Comment on lines -49 to +52
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function SimpleEquation.mutate refactored with the following changes:

This removes the following comments ( why? ):

# otherwise mutate y


def __str__(self) -> str:
return f"X: {self.x} Y: {self.y} Fitness: {self.fitness()}"
Expand Down
8 changes: 5 additions & 3 deletions Chapter6/data_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ def distance(self, other: DataPoint) -> float:
return sqrt(sum(differences))

def __eq__(self, other: object) -> bool:
if not isinstance(other, DataPoint):
return NotImplemented
return self.dimensions == other.dimensions
return (
self.dimensions == other.dimensions
if isinstance(other, DataPoint)
else NotImplemented
)
Comment on lines -36 to +40
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function DataPoint.__eq__ refactored with the following changes:


def __repr__(self) -> str:
return self._originals.__repr__()
12 changes: 7 additions & 5 deletions Chapter7/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ def __init__(self, previous_layer: Optional[Layer], num_neurons: int, learning_r
self.previous_layer: Optional[Layer] = previous_layer
self.neurons: List[Neuron] = []
# the following could all be one large list comprehension, but gets a bit long that way
for i in range(num_neurons):
if previous_layer is None:
random_weights: List[float] = []
else:
random_weights = [random() for _ in range(len(previous_layer.neurons))]
for _ in range(num_neurons):
random_weights = (
[]
if previous_layer is None
else [random() for _ in range(len(previous_layer.neurons))]
)

Comment on lines -28 to +34
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function Layer.__init__ refactored with the following changes:

neuron: Neuron = Neuron(random_weights, learning_rate, activation_function, derivative_activation_function)
self.neurons.append(neuron)
self.output_cache: List[float] = [0.0 for _ in range(num_neurons)]
Expand Down
4 changes: 2 additions & 2 deletions Chapter7/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ def normalize_by_feature_scaling(dataset: List[List[float]]) -> None:
column: List[float] = [row[col_num] for row in dataset]
maximum = max(column)
minimum = min(column)
for row_num in range(len(dataset)):
dataset[row_num][col_num] = (dataset[row_num][col_num] - minimum) / (maximum - minimum)
for item in dataset:
item[col_num] = (item[col_num] - minimum) / (maximum - minimum)
Comment on lines -42 to +43
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function normalize_by_feature_scaling refactored with the following changes:


Loading