mirror of
https://github.com/caperren/school_archives.git
synced 2025-11-09 21:51:15 +00:00
Added missing classes from final year at OSU
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from time import time
|
||||
|
||||
|
||||
def run_hanoi_algorithm(hanoi_function, num_disks, print_steps=False, print_stack=False):
|
||||
stacks = get_starting_stack(num_disks)
|
||||
|
||||
if print_stack:
|
||||
pretty_print_stacks(stacks)
|
||||
|
||||
hanoi_function(len(stacks["left"]), stacks, "left", "middle", "right", print_steps, print_stack)
|
||||
|
||||
|
||||
def pretty_print_stacks(hanoi_stacks):
|
||||
to_print = "Left:%s\tMiddle:%s\tRight:%s" % (hanoi_stacks["left"], hanoi_stacks["middle"], hanoi_stacks["right"])
|
||||
print(to_print.expandtabs(40))
|
||||
|
||||
|
||||
def get_starting_stack(num_start_disks):
|
||||
stacks = {
|
||||
"left": [i for i in range(1, num_start_disks + 1)],
|
||||
"middle": [],
|
||||
"right": []
|
||||
}
|
||||
|
||||
return stacks
|
||||
|
||||
|
||||
def move_disk(hanoi_stacks, starting_post, ending_post, print_steps=False, print_stack=False):
|
||||
hanoi_stacks[ending_post].insert(0, hanoi_stacks[starting_post].pop(0))
|
||||
|
||||
if print_steps:
|
||||
print("Moved disk from %s to %s" % (starting_post, ending_post))
|
||||
|
||||
if print_stack:
|
||||
pretty_print_stacks(hanoi_stacks)
|
||||
|
||||
|
||||
def hanoi_recursive(height, hanoi_stacks, starting_post, temp_post, ending_post, print_steps=False, print_stack=False):
|
||||
if height > 0:
|
||||
hanoi_recursive(height - 1, hanoi_stacks, starting_post, ending_post, temp_post, print_steps, print_stack)
|
||||
|
||||
move_disk(hanoi_stacks, starting_post, ending_post, print_steps, print_stack)
|
||||
|
||||
hanoi_recursive(height - 1, hanoi_stacks, temp_post, starting_post, ending_post, print_steps, print_stack)
|
||||
|
||||
|
||||
def make_legal_move(height, hanoi_stacks, starting_post, ending_post, print_steps=False, print_stack=False):
|
||||
if len(hanoi_stacks["right"]) == height or \
|
||||
(len(hanoi_stacks[starting_post]) == 0 and len(hanoi_stacks[ending_post]) == 0):
|
||||
return
|
||||
elif len(hanoi_stacks[starting_post]) == 0:
|
||||
larger = starting_post
|
||||
smaller = ending_post
|
||||
elif len(hanoi_stacks[ending_post]) == 0:
|
||||
larger = ending_post
|
||||
smaller = starting_post
|
||||
else:
|
||||
larger = starting_post if hanoi_stacks[starting_post][0] > hanoi_stacks[ending_post][0] else ending_post
|
||||
smaller = starting_post if larger != starting_post else ending_post
|
||||
|
||||
move_disk(hanoi_stacks, smaller, larger, print_steps, print_stack)
|
||||
|
||||
|
||||
def hanoi_iterative(height, hanoi_stacks, starting_post, temp_post, ending_post, print_steps=False, print_stack=False):
|
||||
while len(hanoi_stacks["right"]) != height:
|
||||
if height % 2 == 0:
|
||||
make_legal_move(height, hanoi_stacks, starting_post, temp_post, print_steps, print_stack)
|
||||
make_legal_move(height, hanoi_stacks, starting_post, ending_post, print_steps, print_stack)
|
||||
else:
|
||||
make_legal_move(height, hanoi_stacks, starting_post, ending_post, print_steps, print_stack)
|
||||
make_legal_move(height, hanoi_stacks, starting_post, temp_post, print_steps, print_stack)
|
||||
|
||||
make_legal_move(height, hanoi_stacks, temp_post, ending_post, print_steps, print_stack)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# ##### Variables for Later #####
|
||||
recursive_timings = [[], []]
|
||||
iterative_timings = [[], []]
|
||||
num_timing_iterations = 25
|
||||
|
||||
# ##### Problem 1 #####
|
||||
print("CS 325 - Homework 2 - Corwin Perren")
|
||||
|
||||
print("\n\n########## Problem 1 ##########")
|
||||
print("Recursive and iterative version of hanoi made...")
|
||||
# Recursive and iterative version made. See the two immediate functions above.
|
||||
|
||||
# ##### Problem 2 #####
|
||||
print("\n\n########## Problem 2 ##########")
|
||||
|
||||
# Recursive 3 disks
|
||||
print("### Hanoi Recursive - 3 Disks - Printed Steps ###")
|
||||
run_hanoi_algorithm(hanoi_recursive, 3, True, False)
|
||||
|
||||
# Recursive 4 disks
|
||||
print("\n\n### Hanoi Recursive - 4 Disks - Printed Steps ###")
|
||||
run_hanoi_algorithm(hanoi_recursive, 4, True, False)
|
||||
|
||||
# Iterative 3 disks
|
||||
print("\n\n### Hanoi Iterative - 3 Disks - Printed Steps ###")
|
||||
run_hanoi_algorithm(hanoi_iterative, 3, True, False)
|
||||
|
||||
# Iterative 4 disks
|
||||
print("\n\n### Hanoi Iterative - 4 Disks - Printed Steps ###")
|
||||
run_hanoi_algorithm(hanoi_iterative, 4, True, False)
|
||||
|
||||
# Verified that these are the correct steps
|
||||
|
||||
# ##### Problem 3 #####
|
||||
print("\n\n########## Problem 3 ##########")
|
||||
print("### 4 Disks - Print Out Successive Contents from Recursion ###")
|
||||
run_hanoi_algorithm(hanoi_recursive, 4, False, True)
|
||||
|
||||
# ##### Problem 4 #####
|
||||
print("\n\n########## Problem 4 ##########")
|
||||
print("### Recursive Timings For Small n ###")
|
||||
for current_n in range(1, num_timing_iterations):
|
||||
start_time = time()
|
||||
run_hanoi_algorithm(hanoi_recursive, current_n)
|
||||
run_time = time() - start_time
|
||||
|
||||
recursive_timings[0].append(current_n)
|
||||
recursive_timings[1].append(run_time)
|
||||
print("%s disks: %.10f seconds" % (current_n, run_time))
|
||||
|
||||
print("### Iterative Timings For Small n ###")
|
||||
for current_n in range(1, num_timing_iterations):
|
||||
start_time = time()
|
||||
run_hanoi_algorithm(hanoi_iterative, current_n)
|
||||
run_time = time() - start_time
|
||||
|
||||
iterative_timings[0].append(current_n)
|
||||
iterative_timings[1].append(run_time)
|
||||
print("%s disks: %.10f seconds" % (current_n, run_time))
|
||||
|
||||
# ##### Problem 5 #####
|
||||
print("\n\n########## Problem 5 ##########")
|
||||
print("### Plots shown below, or printouts for spreadsheet if run from code ###")
|
||||
|
||||
for i in range(len(recursive_timings[0])):
|
||||
print("%s\t%s" % (recursive_timings[0][i], recursive_timings[1][i]))
|
||||
|
||||
for i in range(len(iterative_timings[0])):
|
||||
print("%s\t%s" % (iterative_timings[0][i], iterative_timings[1][i]))
|
||||
|
||||
# ##### Problem 6 #####
|
||||
print("\n\n########## Problem 6 ##########")
|
||||
print("Recursive C Value is approximately equal to 7.42E-07")
|
||||
print("Iterative C Value is approximately equal to 1.13E-06")
|
||||
|
||||
# ##### Problem 7 #####
|
||||
print("\n\n########## Problem 7 ##########")
|
||||
print("The recursive algorithm will be faster for large n.")
|
||||
|
||||
# ##### Problem 8 #####
|
||||
print("\n\n########## Problem 8 ##########")
|
||||
print("The recursive algorithm would take approximately 434027 years for 64 disks.")
|
||||
print("The iterative algorithm would take approximately 660985 years for 64 disks.")
|
||||
|
||||
# ##### Problem 9 #####
|
||||
print("\n\n########## Problem 9 ##########")
|
||||
print("The recursive algorithm could solve approximately 29 disks in ten minutes.")
|
||||
print("The iterative algorithm could solve approximately 28 disks in ten minutes.")
|
||||
@@ -0,0 +1,219 @@
|
||||
from random import randint
|
||||
import numpy as np
|
||||
from time import time
|
||||
|
||||
|
||||
# Edit this section to change runtime parameters for solvers below
|
||||
MAX_TILING_K_VALUE = 12
|
||||
NUM_RAND_TILING_GAMES = 10
|
||||
TILING_K_VALUES = [i for i in range(1, MAX_TILING_K_VALUE)]
|
||||
|
||||
MAX_RAND_COIN_VALUE = 21
|
||||
NUM_RAND_COIN_GAMES = 10
|
||||
COINS_K_VALUES = [i for i in range(1, MAX_RAND_COIN_VALUE)]
|
||||
# End adjustment section
|
||||
|
||||
|
||||
class TilingSolver(object):
|
||||
EMPTY_CELL = " "
|
||||
REMOVED_CELL = " X "
|
||||
|
||||
USE_POSITION = 1
|
||||
EXISTING_POSITION = 0
|
||||
|
||||
CELL_OPTIONS = {
|
||||
"tl": [[USE_POSITION, USE_POSITION],
|
||||
[USE_POSITION, EXISTING_POSITION]],
|
||||
"tr": [[USE_POSITION, USE_POSITION],
|
||||
[EXISTING_POSITION, USE_POSITION]],
|
||||
"bl": [[USE_POSITION, EXISTING_POSITION],
|
||||
[USE_POSITION, USE_POSITION]],
|
||||
"br": [[EXISTING_POSITION, USE_POSITION],
|
||||
[USE_POSITION, USE_POSITION]]
|
||||
}
|
||||
|
||||
def __init__(self, k_value, special_print=False, removed_cell=None):
|
||||
self.k_value = k_value
|
||||
self.removed_cell = removed_cell
|
||||
|
||||
self.two_to_k = 2 ** self.k_value
|
||||
|
||||
self.tile_table = []
|
||||
self.current_tile_number = "001"
|
||||
|
||||
self.generate_starting_table()
|
||||
|
||||
self.start_time = time()
|
||||
self.tile(self.two_to_k, self.tile_table, self.removed_cell)
|
||||
self.total_time = time() - self.start_time
|
||||
|
||||
self.print_tile_table(special_print)
|
||||
|
||||
def generate_starting_table(self):
|
||||
# noinspection PyTypeChecker
|
||||
self.tile_table = np.full((self.two_to_k, self.two_to_k), self.EMPTY_CELL)
|
||||
|
||||
if not self.removed_cell:
|
||||
self.removed_cell = randint(0, self.two_to_k - 1), randint(0, self.two_to_k - 1)
|
||||
|
||||
x, y = self.removed_cell
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.tile_table[y][x] = self.REMOVED_CELL
|
||||
|
||||
def print_tile_table(self, special_print):
|
||||
if not special_print:
|
||||
print("Solved k=%s in %0.5f seconds." % (self.k_value, self.total_time))
|
||||
for row in self.tile_table:
|
||||
print("|", end="")
|
||||
for column in row:
|
||||
print(column, end="|")
|
||||
print()
|
||||
print()
|
||||
else:
|
||||
print("%s\t%s\t%f" % (self.k_value, self.two_to_k, self.total_time))
|
||||
|
||||
def tile(self, size, table, missing_cell_location):
|
||||
table_min = 0
|
||||
table_half = size // 2
|
||||
table_max = size
|
||||
|
||||
top_left = table[table_min: table_half, table_min: table_half]
|
||||
top_right = table[table_min: table_half, table_half: table_max]
|
||||
bottom_left = table[table_half: table_max, table_min: table_half]
|
||||
bottom_right = table[table_half: table_max, table_half: table_max]
|
||||
|
||||
missing_x, missing_y = missing_cell_location
|
||||
|
||||
x_option = "r" if missing_x < table_half else "l"
|
||||
y_option = "b" if missing_y < table_half else "t"
|
||||
|
||||
tile_placement_option = y_option + x_option
|
||||
|
||||
option = self.CELL_OPTIONS[tile_placement_option]
|
||||
|
||||
if option[0][0] == self.USE_POSITION:
|
||||
table[table_half - 1][table_half - 1] = self.current_tile_number
|
||||
|
||||
if option[0][1] == self.USE_POSITION:
|
||||
table[table_half - 1][table_half] = self.current_tile_number
|
||||
|
||||
if option[1][0] == self.USE_POSITION:
|
||||
table[table_half][table_half - 1] = self.current_tile_number
|
||||
|
||||
if option[1][1] == self.USE_POSITION:
|
||||
table[table_half][table_half] = self.current_tile_number
|
||||
|
||||
self.increment_tile_number()
|
||||
|
||||
if size == 2:
|
||||
return
|
||||
|
||||
self.tile(table_half, top_left, self.get_missing_tile_location(table_half, top_left))
|
||||
self.tile(table_half, top_right, self.get_missing_tile_location(table_half, top_right))
|
||||
self.tile(table_half, bottom_left, self.get_missing_tile_location(table_half, bottom_left))
|
||||
self.tile(table_half, bottom_right, self.get_missing_tile_location(table_half, bottom_right))
|
||||
|
||||
def increment_tile_number(self):
|
||||
self.current_tile_number = "%03d" % (int(self.current_tile_number) + 1)
|
||||
|
||||
def get_missing_tile_location(self, size, table):
|
||||
for row_index in range(size):
|
||||
for column_index in range(size):
|
||||
if table[row_index][column_index] != self.EMPTY_CELL:
|
||||
return column_index, row_index
|
||||
|
||||
|
||||
class ODDSolver(object):
|
||||
GOOD_COIN_WEIGHT = randint(1, 100)
|
||||
BAD_COIN_WEIGHT_MIN = GOOD_COIN_WEIGHT + 1
|
||||
BAD_COIN_WEIGHT_MAX = 5 * BAD_COIN_WEIGHT_MIN
|
||||
|
||||
HEAVIER = "heavier"
|
||||
LIGHTER = "lighter"
|
||||
EQUAL = "equal"
|
||||
|
||||
def __init__(self, k_value, special_print=False):
|
||||
self.k_value = k_value
|
||||
|
||||
self.three_to_k = 3 ** self.k_value
|
||||
|
||||
self.coins = []
|
||||
|
||||
self.setup_coins()
|
||||
|
||||
start_left_range = 0, self.three_to_k // 3
|
||||
start_mid_range = self.three_to_k // 3, (self.three_to_k * 2) // 3
|
||||
start_right_range = (self.three_to_k * 2) // 3, self.three_to_k
|
||||
|
||||
self.start_time = time()
|
||||
self.bad_coin_at_position = self.run_solver(start_left_range, start_mid_range, start_right_range)
|
||||
self.total_time = time() - self.start_time
|
||||
|
||||
self.print_result(special_print)
|
||||
|
||||
def setup_coins(self):
|
||||
self.coins = np.full(self.three_to_k, self.GOOD_COIN_WEIGHT)
|
||||
|
||||
self.coins[randint(0, self.three_to_k - 1)] = randint(self.BAD_COIN_WEIGHT_MIN, self.BAD_COIN_WEIGHT_MAX)
|
||||
|
||||
def run_solver(self, left_range, mid_range, right_range):
|
||||
left_mid = self.weigh(left_range, mid_range)
|
||||
mid_right = self.weigh(mid_range, right_range)
|
||||
left_right = self.weigh(left_range, right_range)
|
||||
|
||||
heaviest = None
|
||||
|
||||
if left_mid != self.EQUAL:
|
||||
heaviest = left_range if left_mid == self.HEAVIER else mid_range
|
||||
|
||||
if mid_right != self.EQUAL:
|
||||
heaviest = mid_range if mid_right == self.HEAVIER else right_range
|
||||
|
||||
if left_right != self.EQUAL:
|
||||
heaviest = left_range if left_right == self.HEAVIER else right_range
|
||||
|
||||
if left_range[-1] - left_range[0] == 1 or \
|
||||
mid_range[-1] - mid_range[0] == 1 or \
|
||||
right_range[-1] - right_range[0] == 1:
|
||||
return heaviest[0]
|
||||
|
||||
range_min = heaviest[0]
|
||||
range_max = heaviest[-1]
|
||||
range_diff = range_max - range_min
|
||||
|
||||
start_left_range = range_min, (range_diff // 3) + range_min
|
||||
start_mid_range = (range_diff // 3) + range_min, ((2 * range_diff) // 3) + range_min
|
||||
start_right_range = ((2 * range_diff) // 3) + range_min, range_max
|
||||
|
||||
return self.run_solver(start_left_range, start_mid_range, start_right_range)
|
||||
|
||||
def weigh(self, left_range, right_range):
|
||||
left_sum = self.coins[left_range[0]: left_range[1]].sum()
|
||||
right_sum = self.coins[right_range[0]: right_range[1]].sum()
|
||||
|
||||
if left_sum > right_sum:
|
||||
return self.HEAVIER
|
||||
elif left_sum < right_sum:
|
||||
return self.LIGHTER
|
||||
else:
|
||||
return self.EQUAL
|
||||
|
||||
def print_result(self, special_print):
|
||||
if not special_print:
|
||||
print("Solved odd coin problem with k=%s in %0.5f seconds. Bad coin at position %s." %
|
||||
(self.k_value, self.total_time, self.bad_coin_at_position))
|
||||
else:
|
||||
print("%s\t%s\t%f" % (self.k_value, self.three_to_k, self.total_time))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for current_k in TILING_K_VALUES:
|
||||
for _ in range(NUM_RAND_TILING_GAMES):
|
||||
TilingSolver(current_k, True)
|
||||
|
||||
print()
|
||||
|
||||
for current_k in COINS_K_VALUES:
|
||||
for _ in range(NUM_RAND_COIN_GAMES):
|
||||
ODDSolver(current_k, True)
|
||||
@@ -0,0 +1,66 @@
|
||||
from time import time
|
||||
from random import randint
|
||||
|
||||
|
||||
def generate_polynomials(k_input):
|
||||
n = 2 ** k_input
|
||||
|
||||
left = [randint(0, 10) for _ in range(n)]
|
||||
right = [randint(0, 10) for _ in range(n)]
|
||||
|
||||
return left, right
|
||||
|
||||
|
||||
def iterative_poly_solver(left_coefficients, right_coefficients):
|
||||
result_coefficients = [0 for _ in range(len(left_coefficients) + len(right_coefficients) - 1)]
|
||||
|
||||
for left_index, left_val in enumerate(left_coefficients):
|
||||
for right_index, right_val in enumerate(right_coefficients):
|
||||
result_coefficients[left_index + right_index] = left_val * right_val + result_coefficients[left_index + right_index]
|
||||
return result_coefficients
|
||||
|
||||
|
||||
def recursive_poly_solver(left_coefficients, right_coefficients):
|
||||
if len(left_coefficients) == 1 and len(right_coefficients) == 1:
|
||||
return [left_coefficients[0] * right_coefficients[0]]
|
||||
|
||||
halfway = len(left_coefficients) // 2
|
||||
|
||||
left_lower_half = left_coefficients[:halfway]
|
||||
left_higher_half = left_coefficients[halfway:]
|
||||
|
||||
right_lower_half = right_coefficients[:halfway]
|
||||
right_higher_half = right_coefficients[halfway:]
|
||||
|
||||
sum_low_high_left = [0 for _ in range(len(left_lower_half))]
|
||||
sum_low_high_right = [0 for _ in range(len(right_lower_half))]
|
||||
|
||||
for i in range(len(left_lower_half)):
|
||||
sum_low_high_left[i] = left_lower_half[i] + left_higher_half[i]
|
||||
sum_low_high_right[i] = right_lower_half[i] + right_lower_half[i]
|
||||
|
||||
low_left_low_right_multiply = recursive_poly_solver(left_lower_half, right_lower_half)
|
||||
sums_multiple = recursive_poly_solver(sum_low_high_left, sum_low_high_right)
|
||||
high_left_high_right_multiply = recursive_poly_solver(left_higher_half, right_higher_half)
|
||||
|
||||
combined = [0 for _ in range(len(left_coefficients) + len(right_coefficients) - 1)]
|
||||
|
||||
for i in range(len(left_coefficients) - 1):
|
||||
combined[i] += low_left_low_right_multiply[i]
|
||||
combined[i + halfway] += sums_multiple[i] - low_left_low_right_multiply[i] - high_left_high_right_multiply[i]
|
||||
combined[i + 2 * halfway] += high_left_high_right_multiply[i]
|
||||
|
||||
return combined
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for i in range(20):
|
||||
left, right = generate_polynomials(i)
|
||||
|
||||
start = time()
|
||||
iterative_poly_solver(left, right)
|
||||
print("%s\t%s" % (2 ** i, time()-start))
|
||||
|
||||
# for i in range(10):
|
||||
# left, right = generate_polynomials(i)
|
||||
# print(recursive_poly_solver(left[0], right[1]))
|
||||
Reference in New Issue
Block a user