Skip to content

hope this works #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 59 commits into
base: comments
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
40b5179
Add project files.
galjs Mar 18, 2020
25315ae
added cell and maze classes
galjs Mar 18, 2020
16f8d1b
created cell class and maze class
galjs Mar 18, 2020
f01f2b7
fixed a bug with the proportions of the board
galjs Mar 18, 2020
ed26f6d
added board verification
galjs Mar 18, 2020
6bd7ef9
changed printing functions to __str__ format
galjs Mar 19, 2020
faaa9c5
added junction calss
galjs Mar 19, 2020
763d554
added Connection class
galjs Mar 19, 2020
7716b6b
add Position class
galjs Mar 19, 2020
eaeb37e
adding to_graph methods to Maze
galjs Mar 19, 2020
d06c8cc
changed junction
galjs Mar 19, 2020
4f2e383
sorting things out
galjs Mar 19, 2020
3539bb1
graph ready
galjs Mar 19, 2020
933a65f
graph is complete. cell has mark attribute
galjs Mar 19, 2020
00618e6
new bfs_maze and discovered attribute for junction
galjs Mar 19, 2020
d8f3949
all is complete except the algorithm
galjs Mar 19, 2020
56b33c2
bfs_maze is ready
galjs Mar 19, 2020
0b333d2
algorithem finds the finish
galjs Mar 19, 2020
71370c8
maze solved
galjs Mar 19, 2020
4b7cd96
raise an error if no solution available
galjs Mar 19, 2020
7f87257
new missing_number file
galjs Mar 19, 2020
86d2aa1
try #2
galjs Mar 19, 2020
8ef491a
working up to "this function should be in Graph"
galjs Mar 22, 2020
d588f5f
workung up to "This also can be a function of Graph"
galjs Mar 22, 2020
548f237
test_maze, cell, bfs_graph now working
galjs Mar 22, 2020
5afa6be
graph also working now
galjs Mar 22, 2020
b24fee5
junction working
galjs Mar 22, 2020
ac50ec9
maze is working
galjs Mar 22, 2020
09e4cda
all corrections done
galjs Mar 22, 2020
883b151
trying to ignore pyproj files
galjs Mar 22, 2020
4afb869
middle of correction
galjs Mar 22, 2020
753f8e4
fix complete
galjs Mar 22, 2020
47ee6d1
back to original graph
galjs Mar 22, 2020
1577598
original state
galjs Mar 23, 2020
e1cb587
trying to excule files
galjs Mar 23, 2020
5b576d6
remove pyproj and sln?
galjs Mar 23, 2020
9ae8386
maybe now?
galjs Mar 23, 2020
b665acc
no changes yet
galjs Mar 23, 2020
c153e56
no more changes
galjs Mar 23, 2020
25f113c
working state
galjs Mar 23, 2020
bf75af5
halfway through...
galjs Mar 23, 2020
804f53b
bfs_maze complete
galjs Mar 23, 2020
c66e111
complete
galjs Mar 23, 2020
6f280b7
deleted trailing lines
galjs Mar 23, 2020
61a52b4
bfs_search corrected
galjs Mar 23, 2020
c7ad1eb
everything except _update_junctions
galjs Mar 23, 2020
f8e32a7
more algorithms
galjs Mar 23, 2020
cca3508
all changes made
galjs Mar 24, 2020
80d7f71
iterator permutations
galjs Mar 24, 2020
b02bccd
variable names changes
galjs Mar 24, 2020
b107665
recursive permutations
galjs Mar 24, 2020
93f5db1
all changes complete
galjs Mar 24, 2020
ba682d4
all algorithms complete
galjs Mar 25, 2020
2863363
more readable and with new test class
galjs Mar 25, 2020
d622bf9
completed all changes + algorithms are now in a package
galjs Mar 25, 2020
d88d695
all cahnges made
galjs Mar 26, 2020
51364e0
fixed
galjs Mar 26, 2020
34435ca
fixed again
galjs Mar 26, 2020
f4e4563
fixed the mistake
galjs Mar 26, 2020
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
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,8 @@ ASALocalRun/
.localhistory/

# BeatPulse healthcheck temp database
healthchecksdb
healthchecksdb

# visual studio project
*.pyproj
*.sln
1 change: 1 addition & 0 deletions clean_code/algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

70 changes: 70 additions & 0 deletions clean_code/algorithms/creation_algorithms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from math import factorial

"""This module supplies fast algorithms for pattern-related creations:
all permutations of a staring, duplicate-deletion."""

def create_trimmed_string(base_string):
"""deletes duplicates in a string. example: aaabbaac -> abac"""
trimmed_elements = []
trimmed_elements.append(base_string[:1])
for index in range(1, len(base_string)):
if base_string[index] != base_string[index-1]:
trimmed_elements.append(base_string[index])
return ''.join(trimmed_elements)


def generate_permutations_iterably(elements):
"""returns all the permutations of a string. the function is non-recursive"""
permutations = set()
final_set = set()
expectd_permutations_number = factorial(len(elements))

new_combinations = _first_cell_permutations(elements)
permutations.update(new_combinations)

while len(final_set) < expectd_permutations_number:
permutations_copy = permutations.copy()
permutations = set()

for permutation in permutations_copy:
new_combinations = _first_cell_permutations(permutation)
# the first permutation is the same as "permutation", so there
# is no need to add it again

permutations.update(new_combinations[1:])

final_set.update(permutations)

return final_set


def _first_cell_permutations(base_state):
new_permutations = []
for index in range(len(base_state)):
splitted_base_state = list(base_state)
_switch_cells(splitted_base_state, 0, index)
new_permutations.append(''.join(splitted_base_state))

return new_permutations


def _switch_cells(elements, first, second):
elements[first], elements[second] = elements[second], elements[first]


def generate_permutations_recursively(base_string):
"""returns all the permutations of a string. the function is recursive"""
return _generate_permutations_recursively(list(base_string))


def _generate_permutations_recursively(elements):
permutations = []
if len(elements) == 1:
return elements

for permutation in _first_cell_permutations(elements):
for combination in _generate_permutations_recursively(permutation[1:]):
new_permutation = permutation[0] + combination
permutations.append(new_permutation)

return permutations
57 changes: 57 additions & 0 deletions clean_code/algorithms/pattern_algorithms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from bisect import insort


"""This module supplies fast algorithms for pattern-related searches:
longest palindrome, biggest elements in a list."""

def find_n_biggest_numbers(numbers, amount=20):
"""return the nth biggest elements in the list"""
if len(numbers) <= amount:
return numbers
biggest_numbers = sorted(numbers[:amount])

for number in numbers:
if number > biggest_numbers[0]:
insort(biggest_numbers, number)
del biggest_numbers[0]

return biggest_numbers


def find_longest_palindrome(base_string):
"""returns the longest palindrome in a string"""
longest_length = 0
start_index = 0

for index in range(len(base_string) - 1):
for check_even in [True, False]:
current_length = _palindrome_length(base_string, index, check_even)
longest_length, start_index = max((longest_length, start_index), (current_length, index))


return _rebuild_palindrome(base_string, start_index, longest_length)


def _palindrome_length(base_string, middle, check_even):
function_offset = 1 if check_even else 0

distance_from_middle = 1
right_end = distance_from_middle + middle + function_offset
left_end = middle - distance_from_middle

while right_end < len(base_string) and left_end >= 0 and base_string[right_end] == base_string[left_end]:
distance_from_middle += 1
right_end = distance_from_middle + middle + function_offset
left_end = middle - distance_from_middle

if not check_even:
return (distance_from_middle * 2) - 1
return (distance_from_middle * 2)


def _rebuild_palindrome(base_string, start_index, length):
begining = start_index - int(length/2)
if length % 2 == 0:
begining += 1
end = start_index + int(length / 2) + 1
return base_string[begining:end]
65 changes: 65 additions & 0 deletions clean_code/bfs_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from exceptions import BoardIntegrityError



class BFS_search():
"""Implements BFS algorithm to find the shortest path in the maze.
for more inforamtion visit:
https://en.wikipedia.org/wiki/Breadth-first_search."""

def __init__(self, graph):
self._graph = graph
self._finish_junction = self._graph.get_finish_junction()
self._start_junction = self._graph.get_start_junction()

def best_route_in_positions(self):
self._map_best_route()
best_route = self._create_best_route()
positions = self._graph.convert_junctions_to_positions(best_route)
return positions

def _map_best_route(self):
"""adds all nodes connected to the current node to a queue.
repeats the process for every node in the queue
until it reaches the desired node (end of maze)"""
sequence_number = 0
nodes = [self._start_junction]

self._start_junction.set_discovered(sequence_number)

while not len(nodes) == 0:
current_junction = nodes[0]
del nodes[0]

neighbours = current_junction.get_connections()
for neighbour in neighbours:
if neighbour.is_finish():
neighbour.set_discovered(sequence_number)
return

if not neighbour.is_discovered():
nodes.append(neighbour)
sequence_number += 1
neighbour.set_discovered(sequence_number)


# if the algorithm checked all nodes without finding the finish node
# it means there is no solution
raise BoardIntegrityError("no solution!")

def _create_best_route(self):
best_route = []
current_junction = self._finish_junction

best_route.append(current_junction)

while not current_junction.is_start():
next_junction = self._get_smallest_sequence_number_neighbour(current_junction)
best_route.append(next_junction)
current_junction = next_junction

return best_route

def _get_smallest_sequence_number_neighbour(self, current_junction):
visited_junctions = filter(lambda connection: connection.is_discovered(), current_junction.get_connections())
return min(visited_junctions, key=lambda junction: junction.get_sequence_number())
19 changes: 19 additions & 0 deletions clean_code/cell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Cell():
"""Represents a square in the maze that can be a wall or a path."""
def __init__(self):
self._blocked = False
self._mark = None

def __str__(self):
if self._blocked:
return 'X'
return self._mark or ' '

def set_mark(self, _mark):
self._mark = _mark

def set_blocked(self):
self._blocked = True

def is_blocked(self):
return self._blocked
3 changes: 3 additions & 0 deletions clean_code/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

class BoardIntegrityError(Exception):
"""An exception to indicate an illegal board"""
78 changes: 78 additions & 0 deletions clean_code/graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from junction import Junction
from position import Position


class Graph():
"""Stores the junction structure in graph form
that a search algorithm can process."""
def __init__(self, start, finish, maze):
self._start = start
self._finish = finish
self._maze = maze
self._graph = []

self._create_graph()
self._update_junctions()

self._set_start()
self._set_finish()

def _create_graph(self):
for row in range(self._maze.get_rows()):
self._graph.append([])
for column in range(self._maze.get_columns()):
if self._maze.get_board()[row][column].is_blocked():
self._graph[row].append(None)
else:
current_junction = Junction(Position(row, column))
self._graph[row].append(current_junction)

def _update_junctions(self):
junctions = filter(None, [node for row in self._graph for node in row])
for junction in junctions:
position = junction.get_position()

# by only connecting two at a time, no duplicate calls to
# get_junction_relative_to_position are made
upper_junction = self._get_junction_relative_to_position(position, -1, 0)
left_junction = self._get_junction_relative_to_position(position, 0, -1)

if upper_junction is not None:
junction.add_connection(upper_junction)
upper_junction.add_connection(junction)

if left_junction is not None:
junction.add_connection(left_junction)
left_junction.add_connection(junction)

def _get_junction_relative_to_position(self, position, row_offset=0, column_offset=0):
try:
return self._graph[position.get_row()+row_offset][position.get_column()+column_offset]
except IndexError:
return None


def __str__(self):
display = ""
for row in self._graph:
for node in row:
display += str(node) if node else ' '
display += '\n'
return display

def _set_start(self):
designated_start = self.get_start_junction()
designated_start.set_is_start()

def _set_finish(self):
designated_finish = self.get_finish_junction()
designated_finish.set_is_finish()

def get_finish_junction(self):
return self._get_junction_relative_to_position(self._finish)

def get_start_junction(self):
return self._get_junction_relative_to_position(self._start)

def convert_junctions_to_positions(self, junctions):
return [junction.get_position() for junction in junctions]
57 changes: 57 additions & 0 deletions clean_code/junction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from position import Position

class Junction():
"""Represents a path square in the maze.
connected to all the path-squares that are adjacent to it."""
def __init__(self, position):
self._connections = []
self._position = position
self._discovered = False
self._finish = False
self._start = False
self._sequence_number = None

def __str__(self):
if self._finish:
return ' f '
if self._start:
return ' s '
return ' ' + str(self._sequence_number) + ' '

def get_position(self):
return Position(self._position.get_row(), self._position.get_column())

def get_connections(self):
return self._connections

def get_sequence_number(self):
return self._sequence_number

def set_postion(self, position):
self._position.set_row(position.get_row())
self._position.set_column(position.get_column())

def set_discovered(self, sequence_number):
self._discovered = True
self._sequence_number = sequence_number

def set_is_finish(self):
self._finish = True

def set_is_start(self):
self._start = True

def has_connections(self):
return len(self._connections) > 0

def add_connection(self, connection):
self._connections.append(connection)

def is_start(self):
return self._start

def is_finish(self):
return self._finish

def is_discovered(self):
return self._discovered
Loading