initial commit

This commit is contained in:
Rushil Umaretiya 2020-12-15 03:02:42 -05:00
commit c6a3c96242
38 changed files with 78136 additions and 0 deletions

104
Unit 0/Umaretiya_r_cb1.py Normal file
View File

@ -0,0 +1,104 @@
# Rushil Umaretiya
# Sept 8, 2020
# Here is my comment!!!! Hello!!
# Warmup-1
def sleep_in(weekday, vacation):
return not weekday or vacation
def monkey_trouble(a_smile, b_smile):
return a_smile == b_smile
def sum_double(a, b):
return (a+b)*2 if a == b else a+b
def diff21(n):
return abs(21-n)*2 if n > 21 else abs(21-n)
def parrot_trouble(talking, hour):
return talking and (hour < 7 or hour > 20)
def makes10(a, b):
return True if a == 10 or b == 10 else a + b == 10
def near_hundred(n):
return abs(100-n) <= 10 or abs(200-n) <= 10
def pos_neg(a, b, negative):
return a < 0 and b < 0 if negative else (a < 0 and b > 0) or (a > 0 and b < 0)
# String-1
def hello_name(name):
return "Hello " + name + "!"
def make_abba(a, b):
return a+b*2+a
def make_tags(tag, word):
return "<"+tag+">"+word+"</"+tag+">"
def make_out_word(out, word):
return out[:len(out)//2]+word+out[len(out)//2:]
def extra_end(str):
return str[-2:]+str[-2:]+str[-2:]
def first_two(str):
return str if len(str)<2 else str[:2]
def first_half(str):
return str[:len(str)//2]
def without_end(str):
return str[1:-1]
# List-1
def first_last6(nums):
return str(nums[0]) == '6' or str(nums[len(nums)-1]) == '6'
def same_first_last(nums):
return False if len(nums) < 1 else nums[0] == nums[len(nums)-1]
def make_pi(n):
return [3,1,4,1,5,9,2,6,5,3,5,8,9,7][:n]
def common_end(a, b):
return a[len(a)-1] == b[len(b)-1] or a[0] == b[0]
def sum3(nums):
return sum(nums)
def rotate_left3(nums):
return nums[1:]+nums[:1]
def reverse3(nums):
return [i for i in reversed(nums)]
def max_end3(nums):
return [max(nums[0],nums[len(nums)-1])]*len(nums)
# Logic-1
def cigar_party(cigars, is_weekend):
return not (cigars < 40 or (not is_weekend and cigars > 60))
def date_fashion(you, date):
return 0 if you <= 2 or date <= 2 else 2 if you >= 8 or date >= 8 else 1
def squirrel_play(temp, is_summer):
return temp >= 60 and ((is_summer and temp <= 100) or (not is_summer and temp <= 90))
def caught_speeding(speed, is_birthday):
return 0 if speed <= 60 or (is_birthday and speed <= 65) else 1 if speed <= 80 or (is_birthday and speed <= 85) else 2
def sorta_sum(a, b):
return 20 if a+b in range(10,20) else a+b
def alarm_clock(day, vacation):
return "7:00" if day in range(1,6) and not vacation else "10:00" if not vacation or day in range(1,6) else "off"
def love6(a, b):
return a == 6 or b == 6 or a+b == 6 or abs(a-b) == 6
def in1to10(n, outside_mode):
return n in range (1,11) if not outside_mode else n <= 1 or n >= 10

209
Unit 0/Umaretiya_r_exer.py Normal file
View File

@ -0,0 +1,209 @@
# Name: Rushil Umaretiya
# Date: 09/10/2020
# Do not forget to change the file name -> Save as
from PIL import Image
from collections import Counter
from itertools import permutations
''' Tasks '''
# 1. Given an input of a space-separated list of any length of integers, output the sum of them.
# 2. Output the list of those integers (from #1) that are divisible by three.
list = input("list of numbers: ")
print (f"1. sum = {sum([int(x) for x in list.strip().split()])}")
print (f"2. list of multiples of 3: {[int(x) for x in list.strip().split() if int(x) % 3 == 0]}")
# 3. Given an integer input, print the first n Fibonacci numbers. eg. n=6: 1, 1, 2, 3, 5, 8
n = int(input ("Type n for Fibonacci sequence: "))
def fib(n):
if n <= 0:
return None
elif n <= 2:
return 1
else:
return fib(n-1) + fib(n-2)
list = []
for i in range(1,n+1): list.append(fib(i))
print (f"3. fibonacci: ", end='')
print (*list)
# 4. Given an input, output a string composed of every other character. eg. Aardvark -> Arvr
print ('4. every other str: ', ((lambda str: ''.join([str[x*2] for x in range(len(str)//2)]))(input("Type a string: "))))
# 5. Given a positive integer input, check whether the number is prime or not.
n = int(input("Type a number to check prime: "))
isPrime = False
if n != 1:
for i in range (2, n):
if n % i == 0:
break
else:
isPrime = True
print (f'5. Is prime? {isPrime}')
# 6. Calculate the area of a triangle given three side lengths. eg. 13 14 15 -> 84
list = []
for x in input("Type three sides of a triangle: ").strip().split():
list.append(int(x))
p = sum(list)/2
print("6. The area of", *list, "is", (p*(p-list[0])*(p-list[1])*(p-list[2]))**(1/2))
# 7. Given a input of a string, remove all punctuation from the string.
# eg. "Don't quote me," she said. -> Dontquotemeshesaid)
str = input("Type a sentence: ")
nopunct = ''.join([i for i in str if i not in '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '])
print (f'7. Punct removed: {nopunct}')
# 8. Check whether the input string (from #7, lower cased, with punctuation removed) is a palindrome.
palindrome = nopunct.lower() == nopunct[::-1].lower()
print (f'8. Is palindrome? {palindrome}')
# 9. Count the number of each vowel in the input string (from #7).
vowels = {
'a':len([i for i in nopunct if i in 'a']),
'e':len([i for i in nopunct if i in 'e']),
'i':len([i for i in nopunct if i in 'i']),
'o':len([i for i in nopunct if i in 'o']),
'u':len([i for i in nopunct if i in 'u'])
}
print (f'9. Count each vowel: {vowels}')
# 10. Given two integers as input, print the value of f\left(k\right)=k^2-3k+2 for each integer between the two inputs.
# eg. 2 5 -> 0, 2, 6, 12
ints = input ("Type two integers (lower bound and upper bound): ")
list = ints.strip().split()
ans = []
for i in range(int(list[0]),int(list[1]) + 1):
ans.append(int(i)**2-(3*int(i))+2)
print (f'10. Evaluate f(k)=k^2 - 3k + 2 from {list[0]} to {list[1]}:', *ans)
# 11. Given an input of a string, determines a character with the most number of occurrences.
str = input ("Type a string: ")
freq = {}
for char in str.lower():
if char in freq:
freq[char] += 1
else:
freq[char] = 1
max_freq = max(freq.values())
max_letters = []
for char in freq.keys():
if freq[char] == max_freq:
max_letters.append(char)
print ('11. Most occurred char:', *max_letters)
# 12. With the input string from #11, output a list of all the words that start and end in a vowel.
vowels = []
for word in str.strip().split():
if len(word) > 0 and word[0] in 'aeiou' and word[len(word)-1] in 'aeiou':
vowels.append(word)
print (f'12. List of words starting and ending with vowels: {vowels}')
# 13. With the input string from #11, capitalizes the starting letter of every word of the string and print it.
words = [word.capitalize() for word in str.strip().split()]
print ('13. Capitalize starting letter of every word:', *words)
# 14. With the input string from #11, prints out the string with each word in the string reversed.
words = [word[::-1] for word in str.strip().split()]
print ('14. Reverse every word:', *words)
# 15. With the input string from #11, treats the first word of the input as a search string to be found in the rest
# of the string, treats the second word as a replacement for the first, and treats the rest of the input as the string to be searched.
# eg. b Ba baby boy -> BaaBay Baoy
words = str.strip().split()
search = words[0]
replace = words[1]
for i in range(2, len(words)):
words[i] = words[i].replace(search, replace)
print ('15. Find the first and replace with the second:', *words[2:])
# 16. With an input of a string, removes all duplicate characters from a string. Eg. detection -> detcion
str = input('Type a string to remove all duplicate chars: ')
letters = []
out = ''
for char in str:
if char not in letters:
letters.append(char)
out += char
print (f'16. Remove all duplicate chars: {out}')
# 17. Given an input of a string, determines whether the string contains only digits.
str = input('Type a string to check if it has only digits or not: ')
print (f'17. Is a number?: {str.isnumeric()}')
# 18. If #17 prints True, determines whether the string contains only 0 and 1 characters, and if so assumes it is a binary string,
# converts it to a number, and prints out the decimal value.
out = "No"
if str.isnumeric():
if len([i for i in str if i in '23456789']) == 0:
out = int(str, 2)
print (f'18. It is a binary number: {out}')
# 19. Write a script that accepts two strings as input and determines whether the two strings are anagrams of each other.
first = input("Type the first string to check anagram: ").strip().replace(' ', '')
second = input("Type the second string to check anagram: ").strip().replace(' ', '')
print(f'19. Are {first} and {second} anagrams?:', len(first) == len(second) and sorted(first) == sorted(second))
# 20. Given an input filename, if the file exists and is an image, find the dimensions of the image.
url = input("Type the image file name: ").strip()
try:
img = Image.open(url)
print (f"20. Image dimension: {img.width} by {img.height}")
except:
print ("20. Image dimension: Image file does not exist or file is not an image")
# 21. Given an input of a string, find the longest palindrome within the string.
str = input ("Type a string to find the longest palindrome: ")
str = ''.join([i for i in str if i not in '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '])
longest = ''
for i in range(len(str)):
for j in range(len(str)):
if str[j:i+j] == str[j:i+j][::-1] and len(str[j:i+j]) > len(longest):
longest = str[j:i+j]
print (f'21. Longest palindrome within the string: {longest}')
# 22. Given an input of a string, find all the permutations of a string.
str = input ("Type a string to do permutation: ")
def permute(str):
if len(str) <= 1:
return str
perm_list = []
for substr in permute(str[1:]): # Generate all of the permutations of the string excluding the first letter
for pos in range(len(substr)+1): # Generate all of the positions that first letter can go
perm_list.append(substr[:pos] + str[0] + substr[pos:]) # Put it in all of those positions
return perm_list
perms = permute(str)
print (f'22. all permutations {perms}')
# 23. Given the input string from #22, find all the unique permutations of a string.
print (f'23. all unique permutations {set(perms)}')
# 24. Given an input of a string, find a longest non-decreasing subsequence within the string (according to ascii value).
str = input('Type a string to find the longest non-decreasing sub: ').strip().replace(' ', '')
longest = ''
for i in range(len(str)):
temp = str[i]
for j in range(i+1, len(str)):
if temp[-1] <= str[j]:
temp += str[j]
else:
break
if len(temp) > len(longest):
longest = temp
print (f'24. longest non-decreasing sub: {longest}')

4
Unit 0/graph.txt Normal file
View File

@ -0,0 +1,4 @@
A C
B A
C C
C A

17
Unit 0/testing.py Normal file
View File

@ -0,0 +1,17 @@
str = input ("Type a string to do permutation: ")
def permute(str):
if len(str) <= 1:
return str
perm_list = []
for substr in permute(str[1:]): # Generate all of the permutations of the string excluding the first letter
for pos in range(len(substr)+1): # Generate all of the positions that first letter can go
perm_list.append(substr[:pos] + str[0] + substr[pos:]) # Put it in all of those positions
return perm_list
perms = permute(str)
print (f'22. all permutations {perms}')
# 23. Given the input string from #22, find all the unique permutations of a string.
print (f'23. all unique permutations {set(perms)}')

BIN
Unit 0/version.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Binary file not shown.

145
Unit 1/Umaretiya_r_U1_L1.py Normal file
View File

@ -0,0 +1,145 @@
import random
def getInitialState():
x = "_12345678"
l = list(x)
random.shuffle(l)
y = ''.join(l)
return y
'''precondition: i<j
swap characters at position i and j and return the new state'''
def swap(state, i, j):
state = list(state)
state[i], state[j] = state[j], state[i]
return "".join(state)
'''Generate a list which hold all children of the current state
and return the list'''
def generate_children(state):
empty = state.find("_")
children = []
if empty == 4: # Center Case
children.append(swap(state, empty, empty+1))
children.append(swap(state, empty, empty+3))
children.append(swap(state, empty, empty-1))
children.append(swap(state, empty, empty-3))
elif empty % 2 != 0: # Edge Case
children.append(swap(state, empty, 4)) # Always attach center
if empty - 3 >= 0 and empty + 3 < len(state):
children.append(swap(state, empty, empty+3))
children.append(swap(state, empty, empty-3))
else:
children.append(swap(state, empty, empty+1))
children.append(swap(state, empty, empty-1))
else: # Corner Case
if empty < 4:
children.append(swap(state, empty, empty+3))
if empty < 1:
children.append(swap(state, empty, empty+1))
else:
children.append(swap(state, empty, empty-1))
else:
children.append(swap(state, empty, empty-3))
if empty > 7:
children.append(swap(state, empty, empty-1))
else:
children.append(swap(state, empty, empty+1))
return children
def display_path(n, explored): #key: current, value: parent
l = []
while explored[n] != "s": #"s" is initial's parent
l.append((n, direction(n, explored[n])))
n = explored[n]
print ()
l = l[::-1]
for d in l:
print (d[1], end = " ")
print()
for i in l:
print (i[0][0:3], end = " ")
print ()
for j in l:
print (j[0][3:6], end = " ")
print()
for k in l:
print (k[0][6:9], end = " ")
print ("\n\nThe shortest path length is :", len(l))
return ""
def direction(parent, state):
parent = parent.find("_")
state = state.find("_")
directions = {
3: "D",
1: "R",
-1: "L",
-3: "U"
}
return directions[parent-state]
'''Find the shortest path to the goal state "_12345678" and
returns the path by calling display_path() function to print all steps.
You can make other helper methods, but you must use dictionary for explored.'''
def BFS(initial_state):
Q = [initial_state]
explored = {}
explored[initial_state] = 's' # Put init state in queue
while Q:
state = Q.pop(0) # Pop off current state
if goal_test(state): # Check if we hit the goal
return display_path(state, explored) # Show the path
for neighbor in generate_children(state): # Add all the children to the queue
if neighbor not in explored:
Q.append(neighbor)
explored[neighbor] = state # And make sure the children are explored
return ("No solution")
def goal_test (state):
return state == "_12345678"
'''Find the shortest path to the goal state "_12345678" and
returns the path by calling display_path() function to print all steps.
You can make other helper methods, but you must use dictionary for explored.'''
def DFS(initial): # Same exact code as BFS except pop() instead of pop(0)
Q = [initial]
explored = {}
explored[initial] = 's'
while Q:
state = Q.pop()
if goal_test(state):
return display_path(state, explored)
for neighbor in generate_children(state):
if neighbor not in explored:
Q.append(neighbor)
explored[neighbor] = state
return ("No solution")
def main():
initial = getInitialState()
print ("BFS start with:\n", initial[0:3], "\n", initial[3:6], "\n", initial[6:], "\n")
print (BFS(initial))
print ("DFS start with:\n", initial[0:3], "\n", initial[3:6], "\n", initial[6:], "\n")
print (DFS(initial))
if __name__ == '__main__':
main()

View File

@ -0,0 +1,85 @@
# Name: Rushil Umaretiya
# Date: 9/29/2020
import random
# print all items in one line with a tab or 3 to 4 spaces.
def display(array):
[print(i, end=" ") for i in array if i != 0]
print()
# sort the array by using heapsort algorithm.
# use swap and heapDown
def sort(array):
sortHelper(array, 1, len(array)-1)
def sortHelper (array, start, end):
if end < 1:
return
swap(array, start, end)
heapDown(array, start, end-1)
sortHelper(array, start, end-1)
# swap two items at position a and b in array
# array is a list, a and b are integers
def swap(array, a, b):
array[a], array[b] = array[b], array[a]
# heap down from k to size
def heapDown(array, k, size):
left, right = 2*k, 2*k+1
if left == size and array[k] < array[size]: # One child
swap(array, k, left)
elif right <= size:
child = (left if array[left] >= array[right] else right)
if array[k] < array[child]:
swap(array, k, child)
heapDown(array, child, size)
# check all items in array.
# Returns True if all items are in ascending order.
def isSorted(array):
if len(array) <= 1:
return True
return array[1:] == sorted(array[1:])
# use round(random.unifrom(from, to), 2) to assign new values in each cell
def createRandom(array):
for i in range(len(array)-1):
array[i+1] = round(random.uniform(1,100), 2)
# Make the given array as a max heap. Use heapDown.
def makeHeap(array, size):
for k in range(size//2, 0, -1):
heapDown(array, k, size)
def main():
array = [0.0]*101
createRandom(array)
display(array)
makeHeap(array, len(array)-1)
display(array)
sort(array)
display(array)
print(isSorted(array))
if __name__ == '__main__':
main()
''' Sample output
15.36 38.17 58.13 59.72 84.46 6.77 72.38 92.32 48.53 46.59 12.68 15.6 36.55 55.51 68.78 91.3 96.35 53.01 62.4 4.12 53.27 36.61 87.25 98.7 58.46 7.19 36.51 31.73 61.75 43.94 76.1 7.55 46.47 14.9 75.97 4.39 96.78 32.97 3.86 55.28 40.99 76.06 33.9 17.0 82.2 30.35 49.85 54.93 78.24 19.22 98.36 20.73 55.19 17.98 61.77 3.77 17.16 29.2 64.7 49.35 13.44 97.75 21.87 55.29 77.09 70.75 31.78 90.42 86.74 26.31 92.45 7.44 97.05 42.43 22.97 92.51 39.43 38.58 15.27 57.41 78.49 55.65 89.27 84.8 75.52 65.33 58.08 3.86 32.1 90.31 91.24 32.41 65.28 19.51 84.68 69.37 5.51 68.73 12.86 21.51
98.7 97.05 98.36 96.78 91.24 78.24 97.75 96.35 92.51 89.27 90.31 69.37 61.77 64.7 76.1 91.3 92.45 59.72 62.4 78.49 84.8 84.46 87.25 68.73 58.46 55.19 36.55 31.73 61.75 49.35 72.38 77.09 70.75 90.42 92.32 53.01 48.53 39.43 38.58 57.41 55.65 76.06 65.33 32.1 82.2 65.28 84.68 58.13 15.6 21.51 6.77 20.73 7.19 17.98 36.51 3.77 17.16 29.2 55.51 43.94 13.44 68.78 21.87 55.29 7.55 46.47 31.78 14.9 86.74 26.31 75.97 7.44 4.39 42.43 22.97 32.97 38.17 3.86 15.27 46.59 55.28 4.12 40.99 53.27 75.52 33.9 58.08 3.86 17.0 36.61 12.68 32.41 30.35 19.51 49.85 54.93 5.51 15.36 12.86 19.22
3.77 3.86 3.86 4.12 4.39 5.51 6.77 7.19 7.44 7.55 12.68 12.86 13.44 14.9 15.27 15.36 15.6 17.0 17.16 17.98 19.22 19.51 20.73 21.51 21.87 22.97 26.31 29.2 30.35 31.73 31.78 32.1 32.41 32.97 33.9 36.51 36.55 36.61 38.17 38.58 39.43 40.99 42.43 43.94 46.47 46.59 48.53 49.35 49.85 53.01 53.27 54.93 55.19 55.28 55.29 55.51 55.65 57.41 58.08 58.13 58.46 59.72 61.75 61.77 62.4 64.7 65.28 65.33 68.73 68.78 69.37 70.75 72.38 75.52 75.97 76.06 76.1 77.09 78.24 78.49 82.2 84.46 84.68 84.8 86.74 87.25 89.27 90.31 90.42 91.24 91.3 92.32 92.45 92.51 96.35 96.78 97.05 97.75 98.36 98.7
True
'''

163
Unit 1/Umaretiya_r_U1_L3.py Normal file
View File

@ -0,0 +1,163 @@
# Name: Rushil Umaretiya
# Date: 10/01/2020
import random
class HeapPriorityQueue():
def __init__(self):
self.queue = ["dummy"] # we do not use index 0 for easy index calulation
self.current = 1 # to make this object iterable
def next(self): # define what __next__ does
if self.current >=len(self.queue):
self.current = 1 # to restart iteration later
raise StopIteration
out = self.queue[self.current]
self.current += 1
return out
def __iter__(self):
return self
__next__ = next
def isEmpty(self):
return len(self.queue) <= 1 # b/c index 0 is dummy
def swap(self, a, b):
self.queue[a], self.queue[b] = self.queue[b], self.queue[a]
# Add a value to the heap_pq
def push(self, value):
self.queue.append(value)
# write more code here to keep the min-heap property
self.heapUp(len(self.queue)-1)
# helper method for push
def heapUp(self, k):
if k <= 1:
return
if len(self.queue) % 2 == 1 and k == len(self.queue) - 1: # no sibling
if self.queue[k//2] > self.queue[k]:
self.swap(k, k//2)
self.heapUp(k//2)
return
if k % 2 == 0:
parent, sibling = k//2, k+1
else:
parent, sibling = k//2, k-1
if self.queue[k] > self.queue[sibling]:
child = sibling
else:
child = k
if self.queue[parent] > self.queue[child]:
self.swap(child, parent)
self.heapUp(parent)
# helper method for reheap and pop
def heapDown(self, k, size):
left, right = 2*k, 2*k+1
if left == size and self.queue[k] > self.queue[size]: # One child
self.swap(k, left)
elif right <= size:
child = (left if self.queue[left] < self.queue[right] else right)
if self.queue[k] > self.queue[child]:
self.swap(k, child)
self.heapDown(child, size)
# make the queue as a min-heap
def reheap(self):
if self.isEmpty():
return -1
for k in range((len(self.queue)-1)//2, 0, -1):
self.heapUp(k)
# remove the min value (root of the heap)
# return the removed value
def pop(self):
if self.isEmpty():
return -1
self.swap (1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(1, len(self.queue) - 1)
return val
# remove a value at the given index (assume index 0 is the root)
# return the removed value
def remove(self, index):
if self.isEmpty():
return -1
if len (self.queue) == 2:
val = self.queue.pop()
self.queue = []
return val
self.swap (index + 1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(index + 1, len(self.queue) - 1)
return val
# This method is for testing. Do not change it.
def isHeap(heap, k):
left, right = 2*k, 2*k+1
if left == len(heap): return True
elif len(heap) == right and heap[k] > heap[left]: return False
elif right < len(heap):
if (heap[k] > heap[left] or heap[k] > heap[right]): return False
else: return isHeap(heap, left) and isHeap(heap, right)
return True
# This method is for testing. Do not change it.
def main():
pq = HeapPriorityQueue() # create a HeapPriorityQueue object
print ("Check if dummy 0 is still dummy:", pq.queue[0])
# assign random integers into the pq
for i in range(20):
t = random.randint(10, 99)
print (t, end=" ")
pq.push(t)
print ()
# print the pq which is a min-heap
for x in pq:
print (x, end=" ")
print()
# remove test
print ("Index 4 is removed:", pq.remove(4))
# check if pq is a min-heap
for x in pq:
print (x, end=" ")
print("\nIs a min-heap?", isHeap(pq.queue, 1))
temp = []
while not pq.isEmpty():
temp.append(pq.pop())
print (temp[-1], end=" ")
print ("\nIn ascending order?", temp == sorted(temp))
if __name__ == '__main__':
main()

303
Unit 1/Umaretiya_r_U1_L4.py Normal file
View File

@ -0,0 +1,303 @@
# Name: Rushil Umaretiya
# Date: 10/11/2020
import random, time, math
class HeapPriorityQueue():
def __init__(self):
self.queue = ["dummy"] # we do not use index 0 for easy index calulation
self.current = 1 # to make this object iterable
def next(self): # define what __next__ does
if self.current >=len(self.queue):
self.current = 1 # to restart iteration later
raise StopIteration
out = self.queue[self.current]
self.current += 1
return out
def __iter__(self):
return self
__next__ = next
def isEmpty(self):
return len(self.queue) <= 1 # b/c index 0 is dummy
def swap(self, a, b):
self.queue[a], self.queue[b] = self.queue[b], self.queue[a]
# Add a value to the heap_pq
def push(self, value):
self.queue.append(value)
# write more code here to keep the min-heap property
self.heapUp(len(self.queue)-1)
# helper method for push
def heapUp(self, k):
if k <= 1:
return
if len(self.queue) % 2 == 1 and k == len(self.queue) - 1: # no sibling
if self.queue[k//2][1] > self.queue[k][1]:
self.swap(k, k//2)
self.heapUp(k//2)
return
if k % 2 == 0:
parent, sibling = k//2, k+1
else:
parent, sibling = k//2, k-1
if self.queue[k][1] > self.queue[sibling][1]:
child = sibling
else:
child = k
if self.queue[parent][1] > self.queue[child][1]:
self.swap(child, parent)
self.heapUp(parent)
# helper method for reheap and pop
def heapDown(self, k, size):
left, right = 2*k, 2*k+1
if left == size and self.queue[k][1] > self.queue[size][1]: # One child
self.swap(k, left)
elif right <= size:
child = (left if self.queue[left][1] < self.queue[right][1] else right)
if self.queue[k][1] > self.queue[child][1]:
self.swap(k, child)
self.heapDown(child, size)
# make the queue as a min-heap
def reheap(self):
if self.isEmpty():
return -1
for k in range((len(self.queue)-1)//2, 0, -1):
self.heapUp(k)
# remove the min value (root of the heap)
# return the removed value
def pop(self):
if self.isEmpty():
return -1
self.swap (1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(1, len(self.queue) - 1)
return val
# remove a value at the given index (assume index 0 is the root)
# return the removed value
def remove(self, index):
# Your code goes here
if self.isEmpty():
return -1
if len (self.queue) == 2:
val = self.queue.pop()
self.queue = []
return val
self.swap (index + 1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(index + 1, len(self.queue) - 1)
return val
def inversion_count(new_state, width = 4, N = 4):
'''
Depends on the size(width, N) of the puzzle,
we can decide if the puzzle is solvable or not by counting inversions.
If N is odd, then puzzle instance is solvable if number of inversions is even in the input state.
If N is even, puzzle instance is solvable if
the blank is on an even row counting from the bottom (second-last, fourth-last, etc.) and number of inversions is even.
the blank is on an odd row counting from the bottom (last, third-last, fifth-last, etc.) and number of inversions is odd.
'''
# Your code goes here
inversion_count = 0
for i in range(len(new_state)):
for j in range(i, len(new_state)):
if new_state[i] != '_':
if new_state[i] > new_state[j]:
inversion_count += 1
if N % 2 == 0:
blank = new_state.find('_')
if (blank // width) % 2 == 0:
return inversion_count % 2 == 0
else:
return inversion_count % 2 != 0
else:
return inversion_count % 2 == 0
def check_inversion():
t1 = inversion_count("_42135678", 3, 3) # N=3
f1 = inversion_count("21345678_", 3, 3)
t2 = inversion_count("4123C98BDA765_EF", 4) # N is default, N=4
f2 = inversion_count("4123C98BDA765_FE", 4)
return t1 and t2 and not (f1 or f2)
def getInitialState(sample, size):
sample_list = list(sample)
random.shuffle(sample_list)
new_state = ''.join(sample_list)
while not inversion_count(new_state, size, size):
random.shuffle(sample_list)
new_state = ''.join(sample_list)
return new_state
'''precondition: i<j
swap characters at position i and j and return the new state'''
def swap(state, i, j):
state = list(state)
state[i], state[j] = state[j], state[i]
return "".join(state)
'''Generate a list which hold all children of the current state
and return the list'''
def generate_children(state, size=4):
empty = state.find("_")
children = []
left, right = empty - 1, empty + 1
up, down = empty - size, empty + size
if right % size != 0:
children.append(swap(state, empty, right))
if left % size != size - 1:
children.append(swap(state, empty, left))
if up > -1:
children.append(swap(state, empty, up))
if down < len(state):
children.append(swap(state, empty, down))
return children
def display_path(path_list, size):
for n in range(size):
for path in path_list:
print (path[n*size:(n+1)*size], end = " "*size)
print ()
print ("\nThe shortest path length is :", len(path_list))
return ""
''' You can make multiple heuristic functions '''
def dist_heuristic(state, goal = "_123456789ABCDEF", size=4):
# Your code goes here
md = 0
for i in range(len(state)):
if state[i] != '_':
md += abs(goal.find(state[i]) % size - i % size) + abs(goal.find(state[i]) // size - i // size)
return md
def check_heuristic():
a = dist_heuristic("152349678_ABCDEF", "_123456789ABCDEF", 4)
b = dist_heuristic("8936C_24A71FDB5E", "_123456789ABCDEF", 4)
return (a < b)
def a_star(start, goal="_123456789ABCDEF", heuristic=dist_heuristic, size = 4):
frontier = HeapPriorityQueue()
explored = {}
if start == goal: return []
# We are pushing tuples of the (current_node, path_cost+heuristic, path)
frontier.push((start, heuristic(start, goal, size), [start]))
explored[start] = heuristic(start, goal, size)
while not frontier.isEmpty():
# Pop off the heapq
state = frontier.pop()
# Goal Test
if state[0] == goal:
return state[2]
# Push children onto priority queue
for i in generate_children(state[0], size):
cost = heuristic(i, goal, size) + len(state[2]) + 1
print(cost)
if i not in explored.keys() or explored[i] > cost:
explored[i] = cost
frontier.push((i, cost, state[2] + [i]))
return None
def main():
# A star
print ("Inversion works?:", check_inversion())
print ("Heuristic works?:", check_heuristic())
#initial_state = getInitialState("_123456789ABCDEF", 4)
initial_state = input("Type initial state: ")
if inversion_count(initial_state):
cur_time = time.time()
path = (a_star(initial_state))
if path != None: display_path(path, 4)
else: print ("No Path Found.")
print ("Duration: ", (time.time() - cur_time))
else: print ("{} did not pass inversion test.".format(initial_state))
if __name__ == '__main__':
main()
''' Sample output 1
Inversion works?: True
Heuristic works?: True
Type initial state: 152349678_ABCDEF
1523 1523 1_23 _123
4967 4_67 4567 4567
8_AB 89AB 89AB 89AB
CDEF CDEF CDEF CDEF
The shortest path length is : 4
Duration: 0.0
Sample output 2
Inversion works?: True
Heuristic works?: True
Type initial state: 2_63514B897ACDEF
2_63 _263 5263 5263 5263 5263 5263 5263 5263 52_3 5_23 _523 1523 1523 1_23 _123
514B 514B _14B 1_4B 14_B 147B 147B 147_ 14_7 1467 1467 1467 _467 4_67 4567 4567
897A 897A 897A 897A 897A 89_A 89A_ 89AB 89AB 89AB 89AB 89AB 89AB 89AB 89AB 89AB
CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF
The shortest path length is : 16
Duration: 0.005014657974243164
Sample output 3
Inversion works?: True
Heuristic works?: True
Type initial state: 8936C_24A71FDB5E
8936 8936 8936 893_ 89_3 8943 8943 8_43 84_3 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 _423 4_23 4123 4123 4123 4123 _123
C_24 C2_4 C24_ C246 C246 C2_6 C_26 C926 C926 C9_6 C916 C916 C916 C916 C916 C916 C916 C916 C916 _916 9_16 91_6 916_ 9167 9167 9167 9167 9167 9167 _167 8167 8167 8_67 8567 8567 _567 4567
A71F A71F A71F A71F A71F A71F A71F A71F A71F A71F A7_F A_7F AB7F AB7F AB7F AB7_ AB_7 A_B7 _AB7 CAB7 CAB7 CAB7 CAB7 CAB_ CA_B C_AB C5AB C5AB _5AB 95AB 95AB 95AB 95AB 9_AB _9AB 89AB 89AB
DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E D_5E D5_E D5E_ D5EF D5EF D5EF D5EF D5EF D5EF D5EF D5EF D5EF D5EF D5EF D_EF _DEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF
The shortest path length is : 37
Duration: 0.27825474739074707
Sample output 4
Inversion works?: True
Heuristic works?: True
Type initial state: 8293AC4671FEDB5_
8293 8293 8293 8293 8293 8293 8293 8293 82_3 8_23 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 8423 _423 4_23 4123 4123 4123 4123 _123
AC46 AC46 AC46 AC46 AC46 _C46 C_46 C4_6 C496 C496 C_96 C9_6 C916 C916 C916 C916 C916 C916 C916 C916 C916 _916 9_16 91_6 916_ 9167 9167 9167 9167 9167 9167 _167 8167 8167 8_67 8567 8567 _567 4567
71FE 71F_ 71_F 7_1F _71F A71F A71F A71F A71F A71F A71F A71F A7_F A_7F AB7F AB7F AB7F AB7_ AB_7 A_B7 _AB7 CAB7 CAB7 CAB7 CAB7 CAB_ CA_B C_AB C5AB C5AB _5AB 95AB 95AB 95AB 95AB 9_AB _9AB 89AB 89AB
DB5_ DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E DB5E D_5E D5_E D5E_ D5EF D5EF D5EF D5EF D5EF D5EF D5EF D5EF D5EF D5EF D5EF D_EF _DEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF CDEF
The shortest path length is : 39
Duration: 0.7709157466888428
'''

141
Unit 1/Umaretiya_r_U1_L5.py Normal file
View File

@ -0,0 +1,141 @@
# Name: Rushil Umaretiya Date: 10/14/2020
import time, string
def generate_adjacents(current, words_set):
''' words_set is a set which has all words.
By comparing current and words in the words_set,
generate adjacents set of current and return it'''
adj_set = set()
for i in range(len(current)):
for letter in string.ascii_lowercase:
perm = current[:i]+letter+current[i+1:]
if perm in words_set and perm != current:
adj_set.add(perm)
return adj_set
def check_adj(words_set):
# This check method is written for words_6_longer.txt
adj = generate_adjacents('listen', words_set)
target = {'listee', 'listel', 'litten', 'lister', 'listed'}
return (adj == target)
def bi_bfs(start, goal, words_set):
'''The idea of bi-directional search is to run two simultaneous searches--
one forward from the initial state and the other backward from the goal--
hoping that the two searches meet in the middle.
'''
if start == goal: return []
Q = [[start],[goal]]
visited = [{start:"s"},{goal:"s"}]
flag = 0
while Q[0] or Q[1]:
flag = 1 - flag
for i in range(len(Q[flag])):
state = Q[flag].pop(0)
adj_list = generate_adjacents(state, words_set)
for adj in adj_list:
if adj in visited[1 - flag]:
visited[flag][adj] = state
return build_path(visited, adj, start, goal)
for neighbor in adj_list:
if neighbor not in visited[flag]:
Q[flag].append(neighbor)
visited[flag][neighbor] = state
return None
def build_path (visited, n, start, goal):
start_path, goal_path, intersect = [], [], n
while n != "s":
goal_path.append(n)
n = visited[1][n]
n = intersect
while n != "s":
start_path.append(n)
n = visited[0][n]
return start_path[::-1] + goal_path[1:]
'''
Q = [initial_state]
explored = {}
explored[initial_state] = 's' # Put init state in queue
while Q:
state = Q.pop(0) # Pop off current state
if goal_test(state): # Check if we hit the goal
return display_path(state, explored) # Show the path
for neighbor in generate_children(state): # Add all the children to the queue
if neighbor not in explored:
Q.append(neighbor)
explored[neighbor] = state # And make sure the children are explored
'''
def main():
filename = input("Type the word file: ")
words_set = set()
file = open(filename, "r")
for word in file.readlines():
words_set.add(word.rstrip('\n'))
#print ("Check generate_adjacents():", check_adj(words_set))
initial = input("Type the starting word: ")
goal = input("Type the goal word: ")
cur_time = time.time()
path = (bi_bfs(initial, goal, words_set))
if path != None:
print (path)
print ("The number of steps: ", len(path))
print ("Duration: ", time.time() - cur_time)
else:
print ("There's no path")
if __name__ == '__main__':
main()
'''
Sample output 1
Type the word file: words.txt
Type the starting word: listen
Type the goal word: beaker
['listen', 'listed', 'fisted', 'fitted', 'fitter', 'bitter', 'better', 'beater', 'beaker']
The number of steps: 9
Duration: 0.0
Sample output 2
Type the word file: words_6_longer.txt
Type the starting word: listen
Type the goal word: beaker
['listen', 'lister', 'bister', 'bitter', 'better', 'beater', 'beaker']
The number of steps: 7
Duration: 0.000997304916381836
Sample output 3
Type the word file: words_6_longer.txt
Type the starting word: vaguer
Type the goal word: drifts
['vaguer', 'vagues', 'values', 'valves', 'calves', 'cauves', 'cruves', 'cruses', 'crusts', 'crufts', 'crafts', 'drafts', 'drifts']
The number of steps: 13
Duration: 0.0408782958984375
Sample output 4
Type the word file: words_6_longer.txt
Type the starting word: klatch
Type the goal word: giggle
['klatch', 'clatch', 'clutch', 'clunch', 'glunch', 'gaunch', 'paunch', 'paunce', 'pawnce', 'pawnee', 'pawned', 'panned', 'panged', 'ranged', 'ragged', 'raggee', 'raggle', 'gaggle', 'giggle']
The number of steps: 19
Duration: 0.0867915153503418
'''

View File

@ -0,0 +1,521 @@
# Name: Rushil Umaretiya
# Data: 10/22/2020
import random, pickle, math, time
from math import pi, acos, sin, cos
from tkinter import *
class HeapPriorityQueue():
def __init__(self):
self.queue = ["dummy"] # we do not use index 0 for easy index calulation
self.current = 1 # to make this object iterable
def next(self): # define what __next__ does
if self.current >=len(self.queue):
self.current = 1 # to restart iteration later
raise StopIteration
out = self.queue[self.current]
self.current += 1
return out
def __iter__(self):
return self
__next__ = next
def isEmpty(self):
return len(self.queue) <= 1 # b/c index 0 is dummy
def swap(self, a, b):
self.queue[a], self.queue[b] = self.queue[b], self.queue[a]
# Add a value to the heap_pq
def push(self, value):
self.queue.append(value)
# write more code here to keep the min-heap property
self.heapUp(len(self.queue)-1)
# helper method for push
def heapUp(self, k):
if k <= 1:
return
if len(self.queue) % 2 == 1 and k == len(self.queue) - 1: # no sibling
if sum(self.queue[k//2][1:3]) > sum(self.queue[k][1:3]):
self.swap(k, k//2)
self.heapUp(k//2)
return
if k % 2 == 0:
parent, sibling = k//2, k+1
else:
parent, sibling = k//2, k-1
if sum(self.queue[k][1:3]) > sum(self.queue[sibling][1:3]):
child = sibling
else:
child = k
if sum(self.queue[parent][1:3]) > sum(self.queue[child][1:3]):
self.swap(child, parent)
self.heapUp(parent)
# helper method for reheap and pop
def heapDown(self, k, size):
left, right = 2*k, 2*k+1
if left == size and sum(self.queue[k][1:3]) > sum(self.queue[size][1:3]): # One child
self.swap(k, left)
elif right <= size:
child = (left if sum(self.queue[left][1:3]) < sum(self.queue[right][1:3]) else right)
if sum(self.queue[k][1:3]) > sum(self.queue[child][1:3]):
self.swap(k, child)
self.heapDown(child, size)
# make the queue as a min-heap
def reheap(self):
if self.isEmpty():
return -1
for k in range((len(self.queue)-1)//2, 0, -1):
self.heapUp(k)
# remove the min value (root of the heap)
# return the removed value
def pop(self):
if self.isEmpty():
return -1
self.swap (1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(1, len(self.queue) - 1)
return val
# remove a value at the given index (assume index 0 is the root)
# return the removed value
def remove(self, index):
if self.isEmpty():
return -1
if len (self.queue) == 2:
val = self.queue.pop()
self.queue = []
return val
self.swap (index + 1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(index + 1, len(self.queue) - 1)
return val
def calc_edge_cost(y1, x1, y2, x2):
#
# y1 = lat1, x1 = long1
# y2 = lat2, x2 = long2
# all assumed to be in decimal degrees
# if (and only if) the input is strings
# use the following conversions
y1 = float(y1)
x1 = float(x1)
y2 = float(y2)
x2 = float(x2)
#
R = 3958.76 # miles = 6371 km
#
y1 *= pi/180.0
x1 *= pi/180.0
y2 *= pi/180.0
x2 *= pi/180.0
#
# approximate great circle distance with law of cosines
#
return acos( sin(y1)*sin(y2) + cos(y1)*cos(y2)*cos(x2-x1) ) * R
#
# NodeLocations, NodeToCity, CityToNode, Neighbors, EdgeCost
# Node: (lat, long) or (y, x), node: city, city: node, node: neighbors, (n1, n2): cost
def make_graph(nodes = "rrNodes.txt", node_city = "rrNodeCity.txt", edges = "rrEdges.txt"):
nodeLoc, nodeToCity, cityToNode, neighbors, edgeCost = {}, {}, {}, {}, {}
map = {} # have screen coordinate for each node location
nodes = open(nodes, "r")
node_city = open(node_city, "r")
edges = open(edges, "r")
for line in node_city.readlines():
args = line.strip().split(" ", 1)
nodeToCity[args[0]] = args[1]
cityToNode[args[1]] = args[0]
for line in nodes.readlines():
args = line.strip().split(" ")
nodeLoc[args[0]] = (float(args[1]), float(args[2]))
for line in edges.readlines():
args = line.strip().split(" ")
cost = calc_edge_cost(nodeLoc[args[0]][0], nodeLoc[args[0]][1], nodeLoc[args[1]][0], nodeLoc[args[1]][1])
edgeCost[(args[0],args[1])] = cost
edgeCost[(args[1],args[0])] = cost
if args[0] in neighbors:
neighbors[args[0]]+=[args[1]]
else:
neighbors[args[0]] = [args[1]]
if args[1] in neighbors:
neighbors[args[1]]+=[args[0]]
else:
neighbors[args[1]] = [args[0]]
for node in nodeLoc: #checks each
lat = float(nodeLoc[node][0]) #gets latitude
long = float(nodeLoc[node][1]) #gets long
modlat = (lat - 10)/60 #scales to 0-1
modlong = (long+130)/70 #scales to 0-1
map[node] = [modlat*800, modlong*1200] #scales to fit 800 1200
return [nodeLoc, nodeToCity, cityToNode, neighbors, edgeCost, map]
# Retuen the direct distance from node1 to node2
# Use calc_edge_cost function.
def dist_heuristic(n1, n2, graph):
return calc_edge_cost(graph[0][n1][0],graph[0][n1][1],graph[0][n2][0],graph[0][n2][1])
# Create a city path.
# Visit each node in the path. If the node has the city name, add the city name to the path.
# Example: ['Charlotte', 'Hermosillo', 'Mexicali', 'Los Angeles']
def display_path(path, graph):
print([graph[1][node] for node in path if node in graph[1]])
# Using the explored, make a path by climbing up to "s"
# This method may be used in your BFS and Bi-BFS algorithms.
def generate_path(state, explored, graph):
path = [state]
cost = 0
while explored[state] != "s": #"s" is initial's parent
cost += graph[4][(state,explored[state])]
state = explored[state]
path.append(state)
return path[::-1], cost
def drawLine(canvas, y1, x1, y2, x2, col):
x1, y1, x2, y2 = float(x1), float(y1), float(x2), float(y2)
canvas.create_line(x1, 800-y1, x2, 800-y2, fill=col)
# Draw the final shortest path.
# Use drawLine function.
def draw_final_path(ROOT, canvas, path, graph, col='red'):
for i in range(len(path[1:])):
drawLine(canvas, *graph[5][path[i]], *graph[5][path[i+1]], col)
ROOT.update()
pass
def draw_all_edges(ROOT, canvas, graph):
ROOT.geometry("1200x800") #sets geometry
canvas.pack(fill=BOTH, expand=1) #sets fill expand
for n1, n2 in graph[4]: #graph[4] keys are edge set
drawLine(canvas, *graph[5][n1], *graph[5][n2], 'white') #graph[5] is map dict
ROOT.update()
def bfs(start, goal, graph, col):
ROOT = Tk() #creates new tkinter
ROOT.title("BFS")
canvas = Canvas(ROOT, background='black') #sets background
draw_all_edges(ROOT, canvas, graph)
counter = 0
frontier, explored = [], {start: "s"}
frontier.append(start)
while frontier:
s = frontier.pop(0)
if s == goal:
path, cost = generate_path(s, explored, graph)
print(f'The number of explored nodes of BFS: {len(explored)}')
print(f'The whole path: {path}')
print(f'The length of the whole path {len(path)}')
draw_final_path(ROOT, canvas, path, graph)
return path, cost
for a in graph[3][s]: #graph[3] is neighbors
if a not in explored:
explored[a] = s
frontier.append(a)
drawLine(canvas, *graph[5][s], *graph[5][a], col)
counter += 1
if counter % 1000 == 0: ROOT.update()
return None
def bi_bfs(start, goal, graph, col):
ROOT = Tk() #creates new tkinter
ROOT.title("Bi A Star")
canvas = Canvas(ROOT, background='black') #sets background
draw_all_edges(ROOT, canvas, graph)
Q = [[start],[goal]]
explored = [{start:"s"},{goal:"s"}]
flag = 0
counter = 0
while Q[0] or Q[1]:
flag = 1 - flag
for i in range(len(Q[flag])):
state = Q[flag].pop(0)
adj_list = graph[3][state]
for adj in adj_list:
if adj in explored[1 - flag]:
explored[flag][adj] = state
start_path, start_cost = generate_path(adj, explored[0], graph)
goal_path, goal_cost = generate_path(adj, explored[1], graph)
path = start_path[:-1] + goal_path[::-1]
draw_final_path(ROOT, canvas, path, graph)
print(f'The number of explored nodes of Bi-BFS: {len(explored[0]) + len(explored[1])}')
print(f'The whole path: {path}')
print(f'The length of the whole path {len(path)}')
return path, start_cost + goal_cost
for neighbor in adj_list:
if neighbor not in explored[flag]:
explored[flag][neighbor] = state
Q[flag].append(neighbor)
drawLine(canvas, *graph[5][state], *graph[5][neighbor], col)
counter += 1
if counter % 1000 == 0: ROOT.update()
return None
def a_star(start, goal, graph, col, heuristic=dist_heuristic):
ROOT = Tk() #creates new tkinter
ROOT.title("A*")
canvas = Canvas(ROOT, background='black') #sets background
draw_all_edges(ROOT, canvas, graph)
frontier = HeapPriorityQueue()
explored = {}
if start == goal: return []
# We are pushing tuples of the (current_node, heuristic, path_cost, path))
frontier.push((start, heuristic(start, goal, graph), 0, [start]))
explored[start] = heuristic(start, goal, graph)
counter = 0
while not frontier.isEmpty():
state = frontier.pop()
# Goal test
if state[0] == goal:
path = state[3]
print(f'The number of explored nodes of A star: {len(explored)}')
print(f'The whole path: {path}')
print(f'The length of the whole path {len(path)}')
draw_final_path(ROOT, canvas, state[3], graph)
return path, state[2]
# Push children on heapq
#print(state[1] + state[2])
for neighbor in graph[3][state[0]]:
h = heuristic(neighbor, goal, graph)
path_cost = graph[4][(neighbor, state[0])] + state[2]
cost = h + path_cost
if neighbor not in explored or explored[neighbor] > cost:
explored[neighbor] = cost
frontier.push((neighbor, h, path_cost, state[3] + [neighbor]))
drawLine(canvas, *graph[5][state[0]], *graph[5][neighbor], col)
counter += 1
if counter % 1000 == 0: ROOT.update()
return None
def bi_a_star(start, goal, graph, col, ROOT, canvas, heuristic=dist_heuristic):
counter = 0
frontier = [HeapPriorityQueue(),HeapPriorityQueue()]
explored = [{start: (heuristic(start, goal, graph), [start])},{goal: (heuristic(goal, start, graph), [goal])}]
flag = 1
# We are pushing tuples of the (current_node, heuristic, path_cost, path))
frontier[0].push((start, heuristic(start, goal, graph), 0, [start]))
frontier[1].push((goal, heuristic(goal, start, graph), 0, [goal]))
while frontier[0] or frontier[1]:
flag = 1 - flag
state = frontier[flag].pop()
if state[0] in explored[1 - flag]:
if flag == 0:
path = state[3][:-1] + list(reversed(explored[1][state[0]][1]))
else:
path = explored[1][state[0]][1] + list(reversed(state[3][:-1]))
print(f'The number of explored nodes of A star: {len(explored[0]) + len(explored[1])}')
print(f'The whole path: {path}')
print(f'The length of the whole path {len(path)}')
cost = sum([graph[4][(path[i], path[i+1])] for i in range(len(path) - 1)])
return path, cost
# Push children on heapq
#print(state[1] + state[2])
for neighbor in graph[3][state[0]]:
h = heuristic(neighbor, goal, graph)
path_cost = graph[4][(neighbor, state[0])] + state[2]
cost = h + path_cost
if neighbor not in explored[flag] or explored[flag][neighbor][0] > cost:
explored[flag][neighbor] = (cost, state[3] + [neighbor])
frontier[flag].push((neighbor, h, path_cost, state[3] + [neighbor]))
drawLine(canvas, *graph[5][state[0]], *graph[5][neighbor], col)
counter += 1
if counter % 1000 == 0: ROOT.update()
return None
def tri_directional(city1, city2, city3, graph, col, ROOT, canvas, heuristic=dist_heuristic):
path_1_2, cost_1_2 = bi_a_star(city1, city2, graph, col, ROOT, canvas, heuristic)
path_1_3, cost_1_3 = bi_a_star(city3, city1, graph, col, ROOT, canvas, heuristic)
path_2_3, cost_2_3 = bi_a_star(city2, city3, graph, col, ROOT, canvas, heuristic)
cost, path = min([(cost_1_2+cost_2_3, path_1_2[:-1]+path_2_3), (cost_2_3+cost_1_3, path_2_3[:-1]+path_1_3), (cost_1_3+cost_1_2, path_1_3[:-1]+path_1_2)])
draw_final_path(ROOT, canvas, path, graph)
print()
print(f'Tri-A The whole path: {path}')
print(f'Tri-A The length of the whole path {len(path)}')
return path, cost
def main():
start, goal = input("Start city: "), input("Goal city: ")
third = input("Third city for tri-directional: ")
graph = make_graph("rrNodes.txt", "rrNodeCity.txt", "rrEdges.txt") # Task 1
"""
cur_time = time.time()
path, cost = bfs(graph[2][start], graph[2][goal], graph, 'yellow') #graph[2] is city to node
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('BFS Path Cost:', cost)
print ('BFS duration:', (time.time() - cur_time))
print ()
"""
"""
cur_time = time.time()
path, cost = bi_bfs(graph[2][start], graph[2][goal], graph, 'green')
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('Bi-BFS Path Cost:', cost)
print ('Bi-BFS duration:', (time.time() - cur_time))
print ()
"""
"""
cur_time = time.time()
path, cost = a_star(graph[2][start], graph[2][goal], graph, 'blue')
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('A star Path Cost:', cost)
print ('A star duration:', (time.time() - cur_time))
print ()
"""
ROOT = Tk() #creates new tkinter
ROOT.title("Bi A Star")
canvas = Canvas(ROOT, background='black') #sets background
draw_all_edges(ROOT, canvas, graph)
cur_time = time.time()
path, cost = bi_a_star(graph[2][start], graph[2][goal], graph, 'orange', ROOT, canvas)
if path != None:
display_path(path, graph)
draw_final_path(ROOT, canvas, path, graph)
else: print ("No Path Found.")
print ('Bi-A star Path Cost:', cost)
print ("Bi-A star duration: ", (time.time() - cur_time))
print ()
ROOT = Tk() #creates new tkinter
ROOT.title("Tri A Star")
canvas = Canvas(ROOT, background='black') #sets background
draw_all_edges(ROOT, canvas, graph)
print ("Tri-Search of ({}, {}, {})".format(start, goal, third))
cur_time = time.time()
path, cost = tri_directional(graph[2][start], graph[2][goal], graph[2][third], graph, 'pink', ROOT, canvas)
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('Tri-A star Path Cost:', cost)
print ("Tri-directional search duration:", (time.time() - cur_time))
mainloop() # Let TK windows stay still
if __name__ == '__main__':
main()
''' Sample output
----jGRASP exec: python Lab10_railroad_Kim_2019_2020.py
Start city: Charlotte
Goal city: Los Angeles
Third city for tri-directional: Chicago
The number of explored nodes of BFS: 19735
The whole path: ['3700421', '3700258', '3700256', '3700004', '3700076', '3700075', '0000530', '4500272', '4500042', '4500270', '4500231', '4500069', '4500023', '4500233', '4500094', '4500095', '4500096', '4500097', '4500234', '4500225', '4500104', '4500082', '4500164', '4500015', '4500181', '4500167', '0000533', '1300133', '1300197', '1300132', '1300146', '1300198', '1300204', '1300208', '1300087', '1300279', '1300088', '1300369', '1300459', '1300458', '1300090', '1300460', '1300107', '1300210', '1300398', '1300099', '0000031', '0100343', '0100342', '0100341', '0100084', '0100506', '0100012', '0100325', '0100345', '0100331', '0100520', '0100354', '0100355', '0100042', '0100566', '0100356', '0100357', '0100456', '0100103', '0100515', '0100264', '0100032', '0100263', '0100102', '0100033', '0100062', '0100129', '0100513', '0100061', '0000461', '2800154', '2800153', '2800032', '2800150', '2800031', '2800108', '2800247', '2800191', '2800156', '2800169', '2800001', '2800162', '2800163', '2800164', '2800125', '2800030', '2800028', '0000419', '2200078', '2200143', '2200039', '2200274', '2200379', '2200080', '2200273', '2200205', '2200112', '2200037', '2200076', '2200311', '0000411', '0500250', '0500019', '0500248', '0500005', '0500020', '0500134', '0000573', '4800439', '4800085', '4800410', '4801165', '4800956', '4801086', '4800081', '4800584', '4800082', '4800084', '4800309', '4800898', '4801101', '4800271', '4800578', '4800274', '4800881', '4800882', '4800167', '4800483', '4800464', '4800168', '4801228', '4800170', '4801230', '4800172', '4800462', '4800461', '4800230', '4800199', '4800832', '4800831', '4800198', '4801190', '4800830', '4800197', '4800200', '4800302', '4800648', '4800763', '4800286', '4800759', '4800758', '4800649', '4800675', '4801214', '4800285', '4800674', '4800757', '4800673', '4800672', '4800535', '4800280', '4800279', '4801134', '4800896', '4800357', '0009483', '9100020', '9100502', '9100501', '9100505', '9100507', '9100504', '9100503', '9100515', '9100153', '9100122', '9100478', '9100448', '9100442', '9100477', '9100476', '9100479', '9100436', '9100124', '9100150', '9100427', '9100012', '9100485', '9100484', '9100081', '9100486', '9100007', '9100117', '9100006', '9100116', '9100080', '9100438', '9100001', '0009063', '0600129', '0600577', '0600041', '0600579', '0600117', '0600039', '0600646', '0600797', '0600747', '0600516', '0600750', '0600584', '0600746', '0600585', '0600586', '0600042', '0600770', '0600434', '0600689', '0600464', '0600688', '0600384', '0600588', '0600460', '0600408', '0600799', '0600402', '0600766', '0600686', '0600079', '0600080', '0600086', '0600684', '0600425', '0600088', '0600759', '0600427', '0600316']
The length of the whole path: 243
['Charlotte', 'Hermosillo', 'Mexicali', 'Los Angeles']
BFS Path Cost: 2965.7640233572088
BFS duration: 288.9429421424866
The number of explored nodes of Bi-BFS: 12714
The whole path: ['3700421', '3700258', '3700256', '3700004', '3700076', '3700075', '0000530', '4500272', '4500042', '4500270', '4500231', '4500069', '4500023', '4500233', '4500094', '4500095', '4500096', '4500097', '4500234', '4500225', '4500104', '4500082', '4500164', '4500015', '4500181', '4500167', '0000533', '1300133', '1300197', '1300132', '1300146', '1300198', '1300204', '1300208', '1300087', '1300279', '1300088', '1300369', '1300459', '1300458', '1300090', '1300460', '1300107', '1300210', '1300398', '1300099', '0000031', '0100343', '0100342', '0100341', '0100084', '0100506', '0100012', '0100325', '0100345', '0100331', '0100520', '0100354', '0100355', '0100042', '0100566', '0100356', '0100357', '0100456', '0100103', '0100515', '0100264', '0100032', '0100263', '0100102', '0100033', '0100062', '0100129', '0100513', '0100061', '0000461', '2800154', '2800153', '2800032', '2800150', '2800031', '2800108', '2800247', '2800191', '2800156', '2800169', '2800001', '2800162', '2800163', '2800164', '2800125', '2800030', '2800028', '0000419', '2200078', '2200143', '2200039', '2200274', '2200379', '2200080', '2200273', '2200205', '2200112', '2200037', '2200076', '2200311', '0000411', '0500250', '0500019', '0500248', '0500005', '0500020', '0500134', '0000573', '4800439', '4800085', '4800410', '4801165', '4800956', '4801086', '4800081', '4800584', '4800082', '4800084', '4800309', '4800898', '4801101', '4800271', '4800578', '4800274', '4800881', '4800882', '4800167', '4800483', '4800464', '4800168', '4801228', '4800170', '4801230', '4800172', '4800462', '4800461', '4800230', '4800199', '4800832', '4800831', '4800198', '4801190', '4800830', '4800197', '4800200', '4800302', '4800648', '4800763', '4800286', '4800759', '4800758', '4800649', '4800675', '4801214', '4800285', '4800674', '4800757', '4800673', '4800672', '4800535', '4800280', '4800279', '4801134', '4800896', '4800357', '0009483', '9100020', '9100502', '9100501', '9100505', '9100018', '9100508', '9100503', '9100515', '9100153', '9100122', '9100478', '9100448', '9100442', '9100477', '9100476', '9100479', '9100436', '9100124', '9100150', '9100427', '9100012', '9100485', '9100484', '9100081', '9100486', '9100007', '9100117', '9100006', '9100116', '9100080', '9100438', '9100001', '0009063', '0600129', '0600577', '0600041', '0600579', '0600117', '0600039', '0600646', '0600797', '0600747', '0600516', '0600750', '0600584', '0600746', '0600585', '0600586', '0600042', '0600770', '0600434', '0600690', '0600875', '0600691', '0600692', '0600082', '0600313', '0600383', '0600312', '0600404', '0600405', '0600403', '0600079', '0600080', '0600086', '0600684', '0600425', '0600088', '0600759', '0600427', '0600316']
The length of the whole path 243
['Charlotte', 'Hermosillo', 'Mexicali', 'Los Angeles']
Bi-BFS Path Cost: 2965.4128704488785
Bi-BFS duration: 115.2277946472168
The number of explored nodes of A star: 7692
The whole path: ['3700421', '3700258', '3700257', '3700142', '3700422', '3700001', '3700235', '3700234', '3700330', '3700329', '3700002', '3700356', '3700355', '3700357', '3700197', '3700198', '0000529', '4500042', '4500270', '4500231', '4500069', '4500023', '4500233', '4500094', '4500095', '4500096', '4500097', '4500234', '4500225', '4500104', '4500082', '4500164', '4500015', '4500181', '4500167', '0000533', '1300133', '1300197', '1300132', '1300146', '1300198', '1300204', '1300208', '1300087', '1300279', '1300088', '1300369', '1300459', '1300458', '1300090', '1300460', '1300107', '1300210', '1300398', '1300099', '0000031', '0100343', '0100342', '0100341', '0100084', '0100340', '0100276', '0100339', '0100338', '0100324', '0100344', '0100508', '0100273', '0100329', '0100272', '0100303', '0100090', '0100430', '0100429', '0100435', '0100240', '0100239', '0100018', '0100138', '0100139', '0100088', '0100289', '0100569', '0100222', '0100224', '0100227', '0100188', '0100256', '0100101', '0100134', '0100038', '0100317', '0100319', '0100157', '0100253', '0100316', '0100198', '0100030', '0100465', '0100472', '0100028', '0100200', '0100293', '0100104', '0000462', '2800033', '2800152', '2800032', '2800150', '2800031', '2800108', '2800247', '2800191', '2800156', '2800169', '2800001', '2800162', '2800163', '2800164', '2800125', '2800030', '2800028', '0000419', '2200078', '2200143', '2200039', '2200274', '2200379', '2200080', '2200273', '2200205', '2200112', '2200037', '2200076', '2200277', '2200074', '2200322', '2200320', '2200035', '2200212', '2200218', '2200248', '2200036', '2200211', '2200209', '2200208', '2200265', '2200073', '2200312', '2200314', '0000143', '4801029', '4801030', '4800307', '4801033', '4801031', '4801171', '4800227', '4800306', '4800901', '4801289', '4800309', '4800416', '4800531', '4801183', '4800786', '4801181', '4800365', '4801180', '4800530', '4801168', '4800785', '4800096', '4800478', '4800097', '4800107', '4800106', '4800100', '4800586', '4800099', '4801026', '4800058', '4800842', '4800843', '4800467', '4800646', '4800056', '4800645', '4800456', '4800048', '4800455', '4801124', '4800778', '4800046', '4800853', '4800852', '4800045', '4801244', '4800681', '4800738', '4800291', '4800362', '4800363', '4800539', '4800295', '4800288', '4800540', '4800634', '4800554', '4801293', '4801292', '4800549', '4801294', '4800292', '4801290', '4800283', '4800702', '4800754', '4800281', '4800755', '4800756', '4800294', '4800550', '4800552', '4800553', '4800624', '4800823', '4801012', '4800536', '4800751', '4801307', '4801295', '4800743', '4800300', '4800746', '4800749', '4800516', '4801299', '0000588', '3500100', '3500044', '3500086', '3500106', '3500137', '3500015', '3500143', '3500041', '3500024', '0000310', '0400107', '0400029', '0400098', '0400105', '0400097', '0400030', '0400031', '0400033', '0400034', '0400036', '0400111', '0400110', '0400118', '0400037', '0400108', '0400120', '0400119', '0400103', '0400026', '0400079', '0400134', '0400072', '0400099', '0400044', '0400045', '0400135', '0400080', '0400048', '0400112', '0400092', '0400053', '0400060', '0000146', '0600798', '0600648', '0600758', '0600796', '0600039', '0600646', '0600797', '0600747', '0600516', '0600750', '0600584', '0600746', '0600585', '0600586', '0600042', '0600770', '0600434', '0600689', '0600464', '0600688', '0600384', '0600588', '0600460', '0600408', '0600799', '0600402', '0600766', '0600686', '0600079', '0600080', '0600085', '0600685', '0600084', '0600751', '0600322', '0600427', '0600316']
The length of the whole path 319
['Charlotte', 'Dallas', 'Tucson', 'Los Angeles']
A star Path Cost: 2419.9700735372285
A star duration: 6.368658781051636
The number of explored nodes of Bi-A star: 7692
The whole path: ['3700421', '3700258', '3700257', '3700142', '3700422', '3700001', '3700235', '3700234', '3700330', '3700329', '3700002', '3700356', '3700355', '3700357', '3700197', '3700198', '0000529', '4500042', '4500270', '4500231', '4500069', '4500023', '4500233', '4500094', '4500095', '4500096', '4500097', '4500234', '4500225', '4500104', '4500082', '4500164', '4500015', '4500181', '4500167', '0000533', '1300133', '1300197', '1300132', '1300146', '1300198', '1300204', '1300208', '1300087', '1300279', '1300088', '1300369', '1300459', '1300458', '1300090', '1300460', '1300107', '1300210', '1300398', '1300099', '0000031', '0100343', '0100342', '0100341', '0100084', '0100340', '0100276', '0100339', '0100338', '0100324', '0100344', '0100508', '0100273', '0100329', '0100272', '0100303', '0100090', '0100430', '0100429', '0100435', '0100240', '0100367', '0100368', '0100282', '0100093', '0100152', '0100375', '0100304', '0100180', '0100278', '0100268', '0100387', '0100544', '0100137', '0100525', '0100312', '0100166', '0100167', '0100026', '0100109', '0100361', '0000466', '2800215', '2800039', '2800143', '2800214', '2800213', '2800058', '2800221', '2800059', '2800057', '2800209', '0000410', '4700333', '4700249', '4700217', '4700216', '4700355', '4700352', '4700005', '4700219', '4700220', '0000407', '0500006', '0500054', '0500281', '0500055', '0500074', '0500292', '0500228', '0500073', '0500216', '0500204', '0500071', '0500040', '0500309', '0500144', '0500143', '0500315', '0500314', '0500313', '0500311', '0500312', '0500316', '0500017', '0500117', '0500104', '0500320', '0500018', '0500240', '0500251', '0500019', '0500248', '0500005', '0500020', '0500134', '0000573', '4800439', '4800085', '4800410', '4801165', '4800956', '4801086', '4800081', '4800583', '4800437', '4801087', '4800585', '4800080', '4800079', '4800076', '4800077', '4800075', '4800687', '4800088', '4800440', '4801172', '4800089', '4800112', '4801175', '4800482', '4800481', '4800784', '4800057', '4800054', '4800469', '4800470', '4800471', '4800644', '4800642', '4800641', '4800643', '4800645', '4800456', '4800048', '4800455', '4801124', '4800778', '4800046', '4800853', '4800852', '4800045', '4801244', '4800681', '4800738', '4800291', '4800362', '4800363', '4800539', '4800295', '4800288', '4800540', '4800634', '4800554', '4801293', '4801292', '4800549', '4801294', '4800292', '4801290', '4800283', '4800702', '4800754', '4800281', '4800755', '4800756', '4800294', '4800550', '4800552', '4800553', '4800624', '4800823', '4801012', '4800536', '4800751', '4801307', '4801295', '4800743', '4800300', '4800746', '4800749', '4800516', '4801299', '0000588', '3500100', '3500044', '3500086', '3500106', '3500137', '3500015', '3500143', '3500041', '3500024', '0000310', '0400107', '0400029', '0400098', '0400105', '0400097', '0400030', '0400031', '0400033', '0400034', '0400036', '0400111', '0400110', '0400118', '0400037', '0400108', '0400120', '0400119', '0400103', '0400026', '0400079', '0400134', '0400072', '0400099', '0400044', '0400045', '0400135', '0400080', '0400048', '0400112', '0400092', '0400053', '0400060', '0000146', '0600798', '0600648', '0600758', '0600796', '0600039', '0600646', '0600797', '0600747', '0600516', '0600750', '0600584', '0600746', '0600585', '0600586', '0600042', '0600770', '0600434', '0600689', '0600464', '0600688', '0600384', '0600588', '0600460', '0600408', '0600799', '0600402', '0600766', '0600686', '0600079', '0600080', '0600085', '0600685', '0600084', '0600751', '0600322', '0600427', '0600316']
The length of the whole path 319
['Charlotte', 'Dallas', 'Tucson', 'Los Angeles']
Bi-A star Path Cost: 2419.9700735372285
Bi-A star duration: 61.220252990722656
Tri-Search of (Charlotte, Los Angeles, Chicago)
The whole path: ['0600316', '0600427', '0600322', '0600751', '0600084', '0600685', '0600085', '0600080', '0600079', '0600686', '0600766', '0600402', '0600799', '0600408', '0600460', '0600588', '0600384', '0600688', '0600463', '0600435', '0600107', '0600775', '0600769', '0600436', '0600032', '0600414', '0600867', '0600866', '0600031', '0600033', '0600795', '0600602', '0600603', '0600036', '0600604', '0600871', '0600870', '0600872', '0600495', '0000144', '0400113', '0400114', '0400009', '0400010', '0400116', '0400117', '0400148', '0400074', '0400146', '0400147', '0400064', '0400005', '0400006', '0400063', '0400100', '0400075', '0400071', '0400070', '0400002', '0400050', '0000312', '3500036', '3500062', '3500063', '3500068', '3500069', '3500101', '3500111', '3500061', '3500109', '3500084', '3500089', '3500102', '3500065', '3500066', '3500032', '3500027', '3500119', '3500071', '3500070', '3500090', '3500107', '3500072', '3500013', '3500047', '3500039', '3500141', '3500025', '3500099', '0000257', '4801203', '4800003', '4801200', '4800002', '0000248', '4000264', '4000138', '4000231', '0000246', '2000206', '2000503', '2000360', '2000427', '2000500', '2000452', '2000207', '2000419', '2000501', '2000502', '2000073', '2000074', '2000075', '2000473', '2000519', '2000506', '2000294', '2000295', '2000296', '2000514', '2000523', '2000077', '2000292', '2000504', '2000293', '2000092', '2000311', '2000472', '2000470', '2000094', '2000095', '2000404', '2000097', '2000277', '2000102', '2000414', '2000103', '2000104', '2000106', '2000356', '2000114', '2000372', '2000117', '2000465', '2000466', '2000467', '2000270', '2000258', '2000257', '2000256', '2000260', '0000232', '2900371', '2900374', '2900378', '2900238', '2900184', '2900358', '2900288', '2900289', '2900098', '2900366', '2900341', '2900367', '2900108', '2900287', '2900241', '2900103', '2900482', '2900102', '2900545', '2900556', '2900111', '2900120', '2900122', '2900494', '2900355', '2900121', '2900162', '2900165', '2900566', '2900468', '2900164', '0000395', '1900057', '1900382', '1900070', '0000393', '1701225', '1700286', '1701010', '1701170', '1700285', '1701321', '1701325', '1701326', '1701323', '1700750', '1701328', '1701327', '1700292', '1700281', '1700280', '1701120', '1700301', '1700922', '1701121', '1700487', '1700480', '1700479', '1700478', '1700477', '1700430', '1700431', '1701157', '1700449', '1700419', '1700465', '1700418', '1701034', '1701194', '1700417', '1700629', '1701394', '1700653', '1700631', '1700415', '1701267', '1701265', '1701291', '1700899', '1700919', '1701607', '1700411', '1700792', '1700624', '1700635', '1700434', '1701056', '1701063', '1701062', '1700651', '1700803', '0000580', '1800373', '1800287', '1800698', '1800697', '1800699', '1800700', '1800377', '1800404', '1800710', '1800709', '1800708', '1800705', '1800706', '1800396', '1800237', '1800228', '1800227', '1800226', '1800474', '1800475', '1800280', '1800416', '1800185', '1800195', '1800200', '1800317', '1800201', '1800145', '1800144', '1800146', '1800167', '1800461', '1800162', '1800460', '1800653', '1800651', '1800652', '1800513', '1800512', '1800511', '1800328', '1800100', '1800577', '1800095', '1800560', '1800096', '1800492', '1800746', '1800744', '1800070', '1800743', '1800069', '0000013', '3901034', '3900294', '3900813', '3900814', '3900526', '3900527', '3900290', '3900293', '3900896', '3900528', '0000183', '2100102', '2100259', '2100101', '2100296', '2100328', '2100321', '2100094', '2100093', '2100092', '2100088', '2100291', '2100398', '2100162', '2100322', '2100246', '2100184', '2100051', '2100186', '2100385', '2100384', '2100383', '2100381', '2100382', '2100053', '2100055', '2100160', '2100059', '2100216', '2100060', '2100158', '2100065', '2100064', '2100152', '2100156', '0000025', '5100179', '5100126', '5100128', '5100122', '5100121', '5100269', '5100384', '5100061', '5100385', '5100062', '5100436', '0000568', '4700230', '4700231', '4700101', '4700302', '4700143', '4700410', '4700141', '4700144', '0000200', '3700359', '3700082', '3700375', '3700126', '3700376', '3700127', '3700224', '3700091', '3700225', '3700125', '3700144', '3700077', '3700075', '3700076', '3700004', '3700256', '3700258', '3700421']
The length of the whole path 381
['Los Angeles', 'Chicago', 'Charlotte']
Tri-A star Path Cost: 2760.516003492685
Tri-directional search duration: 22.166738271713257
----jGRASP: operation complete.
'''

461
Unit 1/Umaretiya_r_U1_L6.py Normal file
View File

@ -0,0 +1,461 @@
# Name: Rushil Umaretiya
# Data: 10/22/2020
import random, pickle, math, time
from math import pi, acos, sin, cos
from tkinter import *
class HeapPriorityQueue():
def __init__(self):
self.queue = ["dummy"] # we do not use index 0 for easy index calulation
self.current = 1 # to make this object iterable
def next(self): # define what __next__ does
if self.current >=len(self.queue):
self.current = 1 # to restart iteration later
raise StopIteration
out = self.queue[self.current]
self.current += 1
return out
def __iter__(self):
return self
__next__ = next
def isEmpty(self):
return len(self.queue) <= 1 # b/c index 0 is dummy
def swap(self, a, b):
self.queue[a], self.queue[b] = self.queue[b], self.queue[a]
# Add a value to the heap_pq
def push(self, value):
self.queue.append(value)
# write more code here to keep the min-heap property
self.heapUp(len(self.queue)-1)
# helper method for push
def heapUp(self, k):
if k <= 1:
return
if len(self.queue) % 2 == 1 and k == len(self.queue) - 1: # no sibling
if sum(self.queue[k//2][1:3]) > sum(self.queue[k][1:3]):
self.swap(k, k//2)
self.heapUp(k//2)
return
if k % 2 == 0:
parent, sibling = k//2, k+1
else:
parent, sibling = k//2, k-1
if sum(self.queue[k][1:3]) > sum(self.queue[sibling][1:3]):
child = sibling
else:
child = k
if sum(self.queue[parent][1:3]) > sum(self.queue[child][1:3]):
self.swap(child, parent)
self.heapUp(parent)
# helper method for reheap and pop
def heapDown(self, k, size):
left, right = 2*k, 2*k+1
if left == size and sum(self.queue[k][1:3]) > sum(self.queue[size][1:3]): # One child
self.swap(k, left)
elif right <= size:
child = (left if sum(self.queue[left][1:3]) < sum(self.queue[right][1:3]) else right)
if sum(self.queue[k][1:3]) > sum(self.queue[child][1:3]):
self.swap(k, child)
self.heapDown(child, size)
# make the queue as a min-heap
def reheap(self):
if self.isEmpty():
return -1
for k in range((len(self.queue)-1)//2, 0, -1):
self.heapUp(k)
# remove the min value (root of the heap)
# return the removed value
def pop(self):
if self.isEmpty():
return -1
self.swap (1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(1, len(self.queue) - 1)
return val
# remove a value at the given index (assume index 0 is the root)
# return the removed value
def remove(self, index):
if self.isEmpty():
return -1
if len (self.queue) == 2:
val = self.queue.pop()
self.queue = []
return val
self.swap (index + 1, len(self.queue) - 1)
val = self.queue.pop()
self.heapDown(index + 1, len(self.queue) - 1)
return val
def calc_edge_cost(y1, x1, y2, x2):
#
# y1 = lat1, x1 = long1
# y2 = lat2, x2 = long2
# all assumed to be in decimal degrees
# if (and only if) the input is strings
# use the following conversions
y1 = float(y1)
x1 = float(x1)
y2 = float(y2)
x2 = float(x2)
#
R = 3958.76 # miles = 6371 km
#
y1 *= pi/180.0
x1 *= pi/180.0
y2 *= pi/180.0
x2 *= pi/180.0
#
# approximate great circle distance with law of cosines
#
return acos( sin(y1)*sin(y2) + cos(y1)*cos(y2)*cos(x2-x1) ) * R
#
# NodeLocations, NodeToCity, CityToNode, Neighbors, EdgeCost
# Node: (lat, long) or (y, x), node: city, city: node, node: neighbors, (n1, n2): cost
def make_graph(nodes = "rrNodes.txt", node_city = "rrNodeCity.txt", edges = "rrEdges.txt"):
nodeLoc, nodeToCity, cityToNode, neighbors, edgeCost = {}, {}, {}, {}, {}
map = {} # have screen coordinate for each node location
nodes = open(nodes, "r")
node_city = open(node_city, "r")
edges = open(edges, "r")
for line in node_city.readlines():
args = line.strip().split(" ", 1)
nodeToCity[args[0]] = args[1]
cityToNode[args[1]] = args[0]
for line in nodes.readlines():
args = line.strip().split(" ")
nodeLoc[args[0]] = (float(args[1]), float(args[2]))
for line in edges.readlines():
args = line.strip().split(" ")
cost = calc_edge_cost(nodeLoc[args[0]][0], nodeLoc[args[0]][1], nodeLoc[args[1]][0], nodeLoc[args[1]][1])
edgeCost[(args[0],args[1])] = cost
edgeCost[(args[1],args[0])] = cost
if args[0] in neighbors:
neighbors[args[0]]+=[args[1]]
else:
neighbors[args[0]] = [args[1]]
if args[1] in neighbors:
neighbors[args[1]]+=[args[0]]
else:
neighbors[args[1]] = [args[0]]
for node in nodeLoc: #checks each
lat = float(nodeLoc[node][0]) #gets latitude
long = float(nodeLoc[node][1]) #gets long
modlat = (lat - 10)/60 #scales to 0-1
modlong = (long+130)/70 #scales to 0-1
map[node] = [modlat*800, modlong*1200] #scales to fit 800 1200
return [nodeLoc, nodeToCity, cityToNode, neighbors, edgeCost, map]
# Retuen the direct distance from node1 to node2
# Use calc_edge_cost function.
def dist_heuristic(n1, n2, graph):
return calc_edge_cost(graph[0][n1][0],graph[0][n1][1],graph[0][n2][0],graph[0][n2][1])
# Create a city path.
# Visit each node in the path. If the node has the city name, add the city name to the path.
# Example: ['Charlotte', 'Hermosillo', 'Mexicali', 'Los Angeles']
def display_path(path, graph):
print([graph[1][node] for node in path if node in graph[1]])
# Using the explored, make a path by climbing up to "s"
# This method may be used in your BFS and Bi-BFS algorithms.
def generate_path(state, explored, graph):
path = [state]
cost = 0
while explored[state] != "s": #"s" is initial's parent
cost += graph[4][(state,explored[state])]
state = explored[state]
path.append(state)
return path[::-1], cost
def drawLine(canvas, y1, x1, y2, x2, col):
x1, y1, x2, y2 = float(x1), float(y1), float(x2), float(y2)
canvas.create_line(x1, 800-y1, x2, 800-y2, fill=col)
# Draw the final shortest path.
# Use drawLine function.
def draw_final_path(ROOT, canvas, path, graph, col='red'):
for i in range(len(path[1:])):
drawLine(canvas, *graph[5][path[i]], *graph[5][path[i+1]], col)
ROOT.update()
pass
def draw_all_edges(ROOT, canvas, graph):
ROOT.geometry("1200x800") #sets geometry
canvas.pack(fill=BOTH, expand=1) #sets fill expand
for n1, n2 in graph[4]: #graph[4] keys are edge set
drawLine(canvas, *graph[5][n1], *graph[5][n2], 'white') #graph[5] is map dict
ROOT.update()
def bfs(start, goal, graph, col):
ROOT = Tk() #creates new tkinter
ROOT.title("BFS")
canvas = Canvas(ROOT, background='black') #sets background
draw_all_edges(ROOT, canvas, graph)
counter = 0
frontier, explored = [], {start: "s"}
frontier.append(start)
while frontier:
s = frontier.pop(0)
if s == goal:
path, cost = generate_path(s, explored, graph)
print(f'The number of explored nodes of BFS: {len(explored)}')
print(f'The whole path: {path}')
print(f'The length of the whole path {len(path)}')
draw_final_path(ROOT, canvas, path, graph)
return path, cost
for a in graph[3][s]: #graph[3] is neighbors
if a not in explored:
explored[a] = s
frontier.append(a)
drawLine(canvas, *graph[5][s], *graph[5][a], col)
counter += 1
if counter % 1000 == 0: ROOT.update()
return None
def bi_bfs(start, goal, graph, col):
ROOT = Tk() #creates new tkinter
ROOT.title("Bi-BFS")
canvas = Canvas(ROOT, background='black') #sets background
draw_all_edges(ROOT, canvas, graph)
Q = [[start],[goal]]
explored = [{start:"s"},{goal:"s"}]
flag = 0
counter = 0
while Q[0] or Q[1]:
flag = 1 - flag
for i in range(len(Q[flag])):
state = Q[flag].pop(0)
adj_list = graph[3][state]
for adj in adj_list:
if adj in explored[1 - flag]:
explored[flag][adj] = state
start_path, start_cost = generate_path(adj, explored[0], graph)
goal_path, goal_cost = generate_path(adj, explored[1], graph)
path = start_path[:-1] + goal_path[::-1]
draw_final_path(ROOT, canvas, path, graph)
print(f'The number of explored nodes of Bi-BFS: {len(explored[0]) + len(explored[1])}')
print(f'The whole path: {path}')
print(f'The length of the whole path {len(path)}')
return path, start_cost + goal_cost
for neighbor in adj_list:
if neighbor not in explored[flag]:
explored[flag][neighbor] = state
Q[flag].append(neighbor)
drawLine(canvas, *graph[5][state], *graph[5][neighbor], col)
counter += 1
if counter % 1000 == 0: ROOT.update()
return None
def a_star(start, goal, graph, col, heuristic=dist_heuristic):
ROOT = Tk() #creates new tkinter
ROOT.title("A*")
canvas = Canvas(ROOT, background='black') #sets background
draw_all_edges(ROOT, canvas, graph)
frontier = HeapPriorityQueue()
explored = {}
if start == goal: return []
# We are pushing tuples of the (current_node, heuristic, path_cost, path))
frontier.push((start, heuristic(start, goal, graph), 0, [start]))
explored[start] = heuristic(start, goal, graph)
counter = 0
while not frontier.isEmpty():
state = frontier.pop()
# Goal test
if state[0] == goal:
path = state[3]
print(f'The number of explored nodes of A star: {len(explored)}')
print(f'The whole path: {path}')
print(f'The length of the whole path {len(path)}')
draw_final_path(ROOT, canvas, state[3], graph)
return path, state[2]
# Push children on heapq
#print(state[1] + state[2])
for neighbor in graph[3][state[0]]:
h = heuristic(neighbor, goal, graph)
path_cost = graph[4][(neighbor, state[0])] + state[2]
cost = h + path_cost
if neighbor not in explored or explored[neighbor] > cost:
explored[neighbor] = cost
frontier.push((neighbor, h, path_cost, state[3] + [neighbor]))
drawLine(canvas, *graph[5][state[0]], *graph[5][neighbor], col)
counter += 1
if counter % 1000 == 0: ROOT.update()
return None
def bi_a_star(start, goal, graph, col, heuristic=dist_heuristic):
# Your code goes here
return None
def tri_directional(city1, city2, city3, graph, col, heuristic=dist_heuristic):
# Your code goes here
return None
def main():
start, goal = input("Start city: "), input("Goal city: ")
#third = input("Third city for tri-directional: ")
graph = make_graph("rrNodes.txt", "rrNodeCity.txt", "rrEdges.txt") # Task 1
cur_time = time.time()
path, cost = bfs(graph[2][start], graph[2][goal], graph, 'yellow') #graph[2] is city to node
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('BFS Path Cost:', cost)
print ('BFS duration:', (time.time() - cur_time))
print ()
cur_time = time.time()
path, cost = bi_bfs(graph[2][start], graph[2][goal], graph, 'green')
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('Bi-BFS Path Cost:', cost)
print ('Bi-BFS duration:', (time.time() - cur_time))
print ()
cur_time = time.time()
path, cost = a_star(graph[2][start], graph[2][goal], graph, 'blue')
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('A star Path Cost:', cost)
print ('A star duration:', (time.time() - cur_time))
print ()
"""
cur_time = time.time()
path, cost = bi_a_star(graph[2][start], graph[2][goal], graph, 'orange', ROOT, canvas)
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('Bi-A star Path Cost:', cost)
print ("Bi-A star duration: ", (time.time() - cur_time))
print ()
print ("Tri-Search of ({}, {}, {})".format(start, goal, third))
cur_time = time.time()
path, cost = tri_directional(graph[2][start], graph[2][goal], graph[2][third], graph, 'pink', ROOT, canvas)
if path != None: display_path(path, graph)
else: print ("No Path Found.")
print ('Tri-A star Path Cost:', cost)
print ("Tri-directional search duration:", (time.time() - cur_time))
"""
mainloop() # Let TK windows stay still
if __name__ == '__main__':
main()
''' Sample output
----jGRASP exec: python Lab10_railroad_Kim_2019_2020.py
Start city: Charlotte
Goal city: Los Angeles
Third city for tri-directional: Chicago
The number of explored nodes of BFS: 19735
The whole path: ['3700421', '3700258', '3700256', '3700004', '3700076', '3700075', '0000530', '4500272', '4500042', '4500270', '4500231', '4500069', '4500023', '4500233', '4500094', '4500095', '4500096', '4500097', '4500234', '4500225', '4500104', '4500082', '4500164', '4500015', '4500181', '4500167', '0000533', '1300133', '1300197', '1300132', '1300146', '1300198', '1300204', '1300208', '1300087', '1300279', '1300088', '1300369', '1300459', '1300458', '1300090', '1300460', '1300107', '1300210', '1300398', '1300099', '0000031', '0100343', '0100342', '0100341', '0100084', '0100506', '0100012', '0100325', '0100345', '0100331', '0100520', '0100354', '0100355', '0100042', '0100566', '0100356', '0100357', '0100456', '0100103', '0100515', '0100264', '0100032', '0100263', '0100102', '0100033', '0100062', '0100129', '0100513', '0100061', '0000461', '2800154', '2800153', '2800032', '2800150', '2800031', '2800108', '2800247', '2800191', '2800156', '2800169', '2800001', '2800162', '2800163', '2800164', '2800125', '2800030', '2800028', '0000419', '2200078', '2200143', '2200039', '2200274', '2200379', '2200080', '2200273', '2200205', '2200112', '2200037', '2200076', '2200311', '0000411', '0500250', '0500019', '0500248', '0500005', '0500020', '0500134', '0000573', '4800439', '4800085', '4800410', '4801165', '4800956', '4801086', '4800081', '4800584', '4800082', '4800084', '4800309', '4800898', '4801101', '4800271', '4800578', '4800274', '4800881', '4800882', '4800167', '4800483', '4800464', '4800168', '4801228', '4800170', '4801230', '4800172', '4800462', '4800461', '4800230', '4800199', '4800832', '4800831', '4800198', '4801190', '4800830', '4800197', '4800200', '4800302', '4800648', '4800763', '4800286', '4800759', '4800758', '4800649', '4800675', '4801214', '4800285', '4800674', '4800757', '4800673', '4800672', '4800535', '4800280', '4800279', '4801134', '4800896', '4800357', '0009483', '9100020', '9100502', '9100501', '9100505', '9100507', '9100504', '9100503', '9100515', '9100153', '9100122', '9100478', '9100448', '9100442', '9100477', '9100476', '9100479', '9100436', '9100124', '9100150', '9100427', '9100012', '9100485', '9100484', '9100081', '9100486', '9100007', '9100117', '9100006', '9100116', '9100080', '9100438', '9100001', '0009063', '0600129', '0600577', '0600041', '0600579', '0600117', '0600039', '0600646', '0600797', '0600747', '0600516', '0600750', '0600584', '0600746', '0600585', '0600586', '0600042', '0600770', '0600434', '0600689', '0600464', '0600688', '0600384', '0600588', '0600460', '0600408', '0600799', '0600402', '0600766', '0600686', '0600079', '0600080', '0600086', '0600684', '0600425', '0600088', '0600759', '0600427', '0600316']
The length of the whole path: 243
['Charlotte', 'Hermosillo', 'Mexicali', 'Los Angeles']
BFS Path Cost: 2965.7640233572088
BFS duration: 288.9429421424866
The number of explored nodes of Bi-BFS: 12714
The whole path: ['3700421', '3700258', '3700256', '3700004', '3700076', '3700075', '0000530', '4500272', '4500042', '4500270', '4500231', '4500069', '4500023', '4500233', '4500094', '4500095', '4500096', '4500097', '4500234', '4500225', '4500104', '4500082', '4500164', '4500015', '4500181', '4500167', '0000533', '1300133', '1300197', '1300132', '1300146', '1300198', '1300204', '1300208', '1300087', '1300279', '1300088', '1300369', '1300459', '1300458', '1300090', '1300460', '1300107', '1300210', '1300398', '1300099', '0000031', '0100343', '0100342', '0100341', '0100084', '0100506', '0100012', '0100325', '0100345', '0100331', '0100520', '0100354', '0100355', '0100042', '0100566', '0100356', '0100357', '0100456', '0100103', '0100515', '0100264', '0100032', '0100263', '0100102', '0100033', '0100062', '0100129', '0100513', '0100061', '0000461', '2800154', '2800153', '2800032', '2800150', '2800031', '2800108', '2800247', '2800191', '2800156', '2800169', '2800001', '2800162', '2800163', '2800164', '2800125', '2800030', '2800028', '0000419', '2200078', '2200143', '2200039', '2200274', '2200379', '2200080', '2200273', '2200205', '2200112', '2200037', '2200076', '2200311', '0000411', '0500250', '0500019', '0500248', '0500005', '0500020', '0500134', '0000573', '4800439', '4800085', '4800410', '4801165', '4800956', '4801086', '4800081', '4800584', '4800082', '4800084', '4800309', '4800898', '4801101', '4800271', '4800578', '4800274', '4800881', '4800882', '4800167', '4800483', '4800464', '4800168', '4801228', '4800170', '4801230', '4800172', '4800462', '4800461', '4800230', '4800199', '4800832', '4800831', '4800198', '4801190', '4800830', '4800197', '4800200', '4800302', '4800648', '4800763', '4800286', '4800759', '4800758', '4800649', '4800675', '4801214', '4800285', '4800674', '4800757', '4800673', '4800672', '4800535', '4800280', '4800279', '4801134', '4800896', '4800357', '0009483', '9100020', '9100502', '9100501', '9100505', '9100018', '9100508', '9100503', '9100515', '9100153', '9100122', '9100478', '9100448', '9100442', '9100477', '9100476', '9100479', '9100436', '9100124', '9100150', '9100427', '9100012', '9100485', '9100484', '9100081', '9100486', '9100007', '9100117', '9100006', '9100116', '9100080', '9100438', '9100001', '0009063', '0600129', '0600577', '0600041', '0600579', '0600117', '0600039', '0600646', '0600797', '0600747', '0600516', '0600750', '0600584', '0600746', '0600585', '0600586', '0600042', '0600770', '0600434', '0600690', '0600875', '0600691', '0600692', '0600082', '0600313', '0600383', '0600312', '0600404', '0600405', '0600403', '0600079', '0600080', '0600086', '0600684', '0600425', '0600088', '0600759', '0600427', '0600316']
The length of the whole path 243
['Charlotte', 'Hermosillo', 'Mexicali', 'Los Angeles']
Bi-BFS Path Cost: 2965.4128704488785
Bi-BFS duration: 115.2277946472168
The number of explored nodes of A star: 7692
The whole path: ['3700421', '3700258', '3700257', '3700142', '3700422', '3700001', '3700235', '3700234', '3700330', '3700329', '3700002', '3700356', '3700355', '3700357', '3700197', '3700198', '0000529', '4500042', '4500270', '4500231', '4500069', '4500023', '4500233', '4500094', '4500095', '4500096', '4500097', '4500234', '4500225', '4500104', '4500082', '4500164', '4500015', '4500181', '4500167', '0000533', '1300133', '1300197', '1300132', '1300146', '1300198', '1300204', '1300208', '1300087', '1300279', '1300088', '1300369', '1300459', '1300458', '1300090', '1300460', '1300107', '1300210', '1300398', '1300099', '0000031', '0100343', '0100342', '0100341', '0100084', '0100340', '0100276', '0100339', '0100338', '0100324', '0100344', '0100508', '0100273', '0100329', '0100272', '0100303', '0100090', '0100430', '0100429', '0100435', '0100240', '0100239', '0100018', '0100138', '0100139', '0100088', '0100289', '0100569', '0100222', '0100224', '0100227', '0100188', '0100256', '0100101', '0100134', '0100038', '0100317', '0100319', '0100157', '0100253', '0100316', '0100198', '0100030', '0100465', '0100472', '0100028', '0100200', '0100293', '0100104', '0000462', '2800033', '2800152', '2800032', '2800150', '2800031', '2800108', '2800247', '2800191', '2800156', '2800169', '2800001', '2800162', '2800163', '2800164', '2800125', '2800030', '2800028', '0000419', '2200078', '2200143', '2200039', '2200274', '2200379', '2200080', '2200273', '2200205', '2200112', '2200037', '2200076', '2200277', '2200074', '2200322', '2200320', '2200035', '2200212', '2200218', '2200248', '2200036', '2200211', '2200209', '2200208', '2200265', '2200073', '2200312', '2200314', '0000143', '4801029', '4801030', '4800307', '4801033', '4801031', '4801171', '4800227', '4800306', '4800901', '4801289', '4800309', '4800416', '4800531', '4801183', '4800786', '4801181', '4800365', '4801180', '4800530', '4801168', '4800785', '4800096', '4800478', '4800097', '4800107', '4800106', '4800100', '4800586', '4800099', '4801026', '4800058', '4800842', '4800843', '4800467', '4800646', '4800056', '4800645', '4800456', '4800048', '4800455', '4801124', '4800778', '4800046', '4800853', '4800852', '4800045', '4801244', '4800681', '4800738', '4800291', '4800362', '4800363', '4800539', '4800295', '4800288', '4800540', '4800634', '4800554', '4801293', '4801292', '4800549', '4801294', '4800292', '4801290', '4800283', '4800702', '4800754', '4800281', '4800755', '4800756', '4800294', '4800550', '4800552', '4800553', '4800624', '4800823', '4801012', '4800536', '4800751', '4801307', '4801295', '4800743', '4800300', '4800746', '4800749', '4800516', '4801299', '0000588', '3500100', '3500044', '3500086', '3500106', '3500137', '3500015', '3500143', '3500041', '3500024', '0000310', '0400107', '0400029', '0400098', '0400105', '0400097', '0400030', '0400031', '0400033', '0400034', '0400036', '0400111', '0400110', '0400118', '0400037', '0400108', '0400120', '0400119', '0400103', '0400026', '0400079', '0400134', '0400072', '0400099', '0400044', '0400045', '0400135', '0400080', '0400048', '0400112', '0400092', '0400053', '0400060', '0000146', '0600798', '0600648', '0600758', '0600796', '0600039', '0600646', '0600797', '0600747', '0600516', '0600750', '0600584', '0600746', '0600585', '0600586', '0600042', '0600770', '0600434', '0600689', '0600464', '0600688', '0600384', '0600588', '0600460', '0600408', '0600799', '0600402', '0600766', '0600686', '0600079', '0600080', '0600085', '0600685', '0600084', '0600751', '0600322', '0600427', '0600316']
The length of the whole path 319
['Charlotte', 'Dallas', 'Tucson', 'Los Angeles']
A star Path Cost: 2419.9700735372285
A star duration: 6.368658781051636
The number of explored nodes of Bi-A star: 7692
The whole path: ['3700421', '3700258', '3700257', '3700142', '3700422', '3700001', '3700235', '3700234', '3700330', '3700329', '3700002', '3700356', '3700355', '3700357', '3700197', '3700198', '0000529', '4500042', '4500270', '4500231', '4500069', '4500023', '4500233', '4500094', '4500095', '4500096', '4500097', '4500234', '4500225', '4500104', '4500082', '4500164', '4500015', '4500181', '4500167', '0000533', '1300133', '1300197', '1300132', '1300146', '1300198', '1300204', '1300208', '1300087', '1300279', '1300088', '1300369', '1300459', '1300458', '1300090', '1300460', '1300107', '1300210', '1300398', '1300099', '0000031', '0100343', '0100342', '0100341', '0100084', '0100340', '0100276', '0100339', '0100338', '0100324', '0100344', '0100508', '0100273', '0100329', '0100272', '0100303', '0100090', '0100430', '0100429', '0100435', '0100240', '0100367', '0100368', '0100282', '0100093', '0100152', '0100375', '0100304', '0100180', '0100278', '0100268', '0100387', '0100544', '0100137', '0100525', '0100312', '0100166', '0100167', '0100026', '0100109', '0100361', '0000466', '2800215', '2800039', '2800143', '2800214', '2800213', '2800058', '2800221', '2800059', '2800057', '2800209', '0000410', '4700333', '4700249', '4700217', '4700216', '4700355', '4700352', '4700005', '4700219', '4700220', '0000407', '0500006', '0500054', '0500281', '0500055', '0500074', '0500292', '0500228', '0500073', '0500216', '0500204', '0500071', '0500040', '0500309', '0500144', '0500143', '0500315', '0500314', '0500313', '0500311', '0500312', '0500316', '0500017', '0500117', '0500104', '0500320', '0500018', '0500240', '0500251', '0500019', '0500248', '0500005', '0500020', '0500134', '0000573', '4800439', '4800085', '4800410', '4801165', '4800956', '4801086', '4800081', '4800583', '4800437', '4801087', '4800585', '4800080', '4800079', '4800076', '4800077', '4800075', '4800687', '4800088', '4800440', '4801172', '4800089', '4800112', '4801175', '4800482', '4800481', '4800784', '4800057', '4800054', '4800469', '4800470', '4800471', '4800644', '4800642', '4800641', '4800643', '4800645', '4800456', '4800048', '4800455', '4801124', '4800778', '4800046', '4800853', '4800852', '4800045', '4801244', '4800681', '4800738', '4800291', '4800362', '4800363', '4800539', '4800295', '4800288', '4800540', '4800634', '4800554', '4801293', '4801292', '4800549', '4801294', '4800292', '4801290', '4800283', '4800702', '4800754', '4800281', '4800755', '4800756', '4800294', '4800550', '4800552', '4800553', '4800624', '4800823', '4801012', '4800536', '4800751', '4801307', '4801295', '4800743', '4800300', '4800746', '4800749', '4800516', '4801299', '0000588', '3500100', '3500044', '3500086', '3500106', '3500137', '3500015', '3500143', '3500041', '3500024', '0000310', '0400107', '0400029', '0400098', '0400105', '0400097', '0400030', '0400031', '0400033', '0400034', '0400036', '0400111', '0400110', '0400118', '0400037', '0400108', '0400120', '0400119', '0400103', '0400026', '0400079', '0400134', '0400072', '0400099', '0400044', '0400045', '0400135', '0400080', '0400048', '0400112', '0400092', '0400053', '0400060', '0000146', '0600798', '0600648', '0600758', '0600796', '0600039', '0600646', '0600797', '0600747', '0600516', '0600750', '0600584', '0600746', '0600585', '0600586', '0600042', '0600770', '0600434', '0600689', '0600464', '0600688', '0600384', '0600588', '0600460', '0600408', '0600799', '0600402', '0600766', '0600686', '0600079', '0600080', '0600085', '0600685', '0600084', '0600751', '0600322', '0600427', '0600316']
The length of the whole path 319
['Charlotte', 'Dallas', 'Tucson', 'Los Angeles']
Bi-A star Path Cost: 2419.9700735372285
Bi-A star duration: 61.220252990722656
Tri-Search of (Charlotte, Los Angeles, Chicago)
The whole path: ['0600316', '0600427', '0600322', '0600751', '0600084', '0600685', '0600085', '0600080', '0600079', '0600686', '0600766', '0600402', '0600799', '0600408', '0600460', '0600588', '0600384', '0600688', '0600463', '0600435', '0600107', '0600775', '0600769', '0600436', '0600032', '0600414', '0600867', '0600866', '0600031', '0600033', '0600795', '0600602', '0600603', '0600036', '0600604', '0600871', '0600870', '0600872', '0600495', '0000144', '0400113', '0400114', '0400009', '0400010', '0400116', '0400117', '0400148', '0400074', '0400146', '0400147', '0400064', '0400005', '0400006', '0400063', '0400100', '0400075', '0400071', '0400070', '0400002', '0400050', '0000312', '3500036', '3500062', '3500063', '3500068', '3500069', '3500101', '3500111', '3500061', '3500109', '3500084', '3500089', '3500102', '3500065', '3500066', '3500032', '3500027', '3500119', '3500071', '3500070', '3500090', '3500107', '3500072', '3500013', '3500047', '3500039', '3500141', '3500025', '3500099', '0000257', '4801203', '4800003', '4801200', '4800002', '0000248', '4000264', '4000138', '4000231', '0000246', '2000206', '2000503', '2000360', '2000427', '2000500', '2000452', '2000207', '2000419', '2000501', '2000502', '2000073', '2000074', '2000075', '2000473', '2000519', '2000506', '2000294', '2000295', '2000296', '2000514', '2000523', '2000077', '2000292', '2000504', '2000293', '2000092', '2000311', '2000472', '2000470', '2000094', '2000095', '2000404', '2000097', '2000277', '2000102', '2000414', '2000103', '2000104', '2000106', '2000356', '2000114', '2000372', '2000117', '2000465', '2000466', '2000467', '2000270', '2000258', '2000257', '2000256', '2000260', '0000232', '2900371', '2900374', '2900378', '2900238', '2900184', '2900358', '2900288', '2900289', '2900098', '2900366', '2900341', '2900367', '2900108', '2900287', '2900241', '2900103', '2900482', '2900102', '2900545', '2900556', '2900111', '2900120', '2900122', '2900494', '2900355', '2900121', '2900162', '2900165', '2900566', '2900468', '2900164', '0000395', '1900057', '1900382', '1900070', '0000393', '1701225', '1700286', '1701010', '1701170', '1700285', '1701321', '1701325', '1701326', '1701323', '1700750', '1701328', '1701327', '1700292', '1700281', '1700280', '1701120', '1700301', '1700922', '1701121', '1700487', '1700480', '1700479', '1700478', '1700477', '1700430', '1700431', '1701157', '1700449', '1700419', '1700465', '1700418', '1701034', '1701194', '1700417', '1700629', '1701394', '1700653', '1700631', '1700415', '1701267', '1701265', '1701291', '1700899', '1700919', '1701607', '1700411', '1700792', '1700624', '1700635', '1700434', '1701056', '1701063', '1701062', '1700651', '1700803', '0000580', '1800373', '1800287', '1800698', '1800697', '1800699', '1800700', '1800377', '1800404', '1800710', '1800709', '1800708', '1800705', '1800706', '1800396', '1800237', '1800228', '1800227', '1800226', '1800474', '1800475', '1800280', '1800416', '1800185', '1800195', '1800200', '1800317', '1800201', '1800145', '1800144', '1800146', '1800167', '1800461', '1800162', '1800460', '1800653', '1800651', '1800652', '1800513', '1800512', '1800511', '1800328', '1800100', '1800577', '1800095', '1800560', '1800096', '1800492', '1800746', '1800744', '1800070', '1800743', '1800069', '0000013', '3901034', '3900294', '3900813', '3900814', '3900526', '3900527', '3900290', '3900293', '3900896', '3900528', '0000183', '2100102', '2100259', '2100101', '2100296', '2100328', '2100321', '2100094', '2100093', '2100092', '2100088', '2100291', '2100398', '2100162', '2100322', '2100246', '2100184', '2100051', '2100186', '2100385', '2100384', '2100383', '2100381', '2100382', '2100053', '2100055', '2100160', '2100059', '2100216', '2100060', '2100158', '2100065', '2100064', '2100152', '2100156', '0000025', '5100179', '5100126', '5100128', '5100122', '5100121', '5100269', '5100384', '5100061', '5100385', '5100062', '5100436', '0000568', '4700230', '4700231', '4700101', '4700302', '4700143', '4700410', '4700141', '4700144', '0000200', '3700359', '3700082', '3700375', '3700126', '3700376', '3700127', '3700224', '3700091', '3700225', '3700125', '3700144', '3700077', '3700075', '3700076', '3700004', '3700256', '3700258', '3700421']
The length of the whole path 381
['Los Angeles', 'Chicago', 'Charlotte']
Tri-A star Path Cost: 2760.516003492685
Tri-directional search duration: 22.166738271713257
----jGRASP: operation complete.
'''

138
Unit 1/Umaretiya_r_lab_0.py Normal file
View File

@ -0,0 +1,138 @@
# Name: Rushil Umaretiya
# Date: 09/18/2020
# Each Vertex object will have attributes to store its own name and its list of its neighboring vertices.
class Vertex:
def __init__(self, name, vertices):
self.name = name
self.vertices = vertices
def __str__(self):
return f'{self.name} {self.vertices}'
def __repr__(self):
return str(self.name)
# If the file exists, read all edges and build a graph. It returns a list of Vertexes.
def build_graph(filename):
try:
file = open(filename, 'r')
except:
return []
lines = file.read().strip().splitlines()
vertices = []
# Sorry about this solution Ms. Kim, it's not very efficient, but it makes sense.
# Create all the source verticies
for line in lines:
line = line.strip().split()
for vertex in vertices:
if vertex.name == line[0]:
break
else:
vertices.append(Vertex(line[0], []))
# Create all the ending verticies
for line in lines:
line = line.strip().split()
for vertex in vertices:
if vertex.name == line[1]:
break
else:
vertices.append(Vertex(line[1], []))
# Link them!
for line in lines:
line = line.strip().split()
source, end = None, None
for vertex in vertices:
if vertex.name == line[0]:
source = vertex
if vertex.name == line[1]:
end = vertex
if source != None and end != None:
break
source.vertices.append(end)
return vertices
# prints all vertices and adjacent lists of the given graph.
def display_graph(graph):
for vertex in graph:
print (vertex)
# checks if two Vertexes are reachable or not.
def is_reachable(fromV, toV, graph):
visited = []
Q = [fromV]
while len(Q) > 0:
state = Q.pop(0)
if state not in visited:
if state == toV:
return True
visited.append(state)
neighbours = state.vertices
for neighbour in neighbours:
Q.append(neighbour)
return False
# returns the length of the path from a Vertex to the other Vertex.
# If the other Vertex is not reachable, return -1. (Ex) Path cost of A to B to C is 2.
def path_cost(fromV, toV, graph):
if fromV == toV:
return 0
if not is_reachable(fromV, toV, graph):
return -1
visited = []
Q = [fromV]
while len(Q) > 0:
state = Q.pop(0)
if state not in visited:
if state == toV:
return len(visited)
visited.append(state)
neighbours = state.vertices
for neighbour in neighbours:
Q.append(neighbour)
# Test cases
g = build_graph(input("filename: ")) # build a graph
# To check if you build the graph with object correctly
for v in g:
print (v, v.vertices)
display_graph(g) # display the graph (edge list)
fromV, toV = None, None
print ("If you want to stop checking, type -1 for vertex values")
fromV_val, toV_val = input("From vertex value: "), input("To vertex value: ") # Get vertex values from user
while fromV_val != '-1':
# Find from and to Vertexes at graph
for v in g:
if v.name == fromV_val: fromV = v
if v.name == toV_val: toV = v
if fromV is None or toV is None:
print ("One or more vertex value does not exist.")
else:
print ("From {} to {} is reachable?".format(fromV_val, toV_val), is_reachable(fromV, toV, g))
print ("Path cost from {} to {} is".format(fromV_val, toV_val), path_cost(fromV, toV, g))
# Reset to test another case
fromV_val, toV_val = input("\nFrom vertex value: "), input("To vertex value: ")
fromV, toV = None, None

BIN
Unit 1/day2notes.PDF Normal file

Binary file not shown.

6
Unit 1/graph.txt Normal file
View File

@ -0,0 +1,6 @@
A C
B A
C C
C D
D C
D A

25261
Unit 1/rrEdges.txt Normal file

File diff suppressed because it is too large Load Diff

50
Unit 1/rrNodeCity.txt Normal file
View File

@ -0,0 +1,50 @@
3500060 Albuquerque
1300287 Atlanta
4801193 Austin
3600348 Brooklyn
8801670 Calgary
3700421 Charlotte
1701291 Chicago
9100509 Chihuahua
9100015 Ciudad Juarez
3900511 Columbus
4800100 Dallas
0800292 Denver
2600346 Detroit
8800126 Edmonton
4800471 Fort Worth
9100069 Guadalajara
9100007 Hermosillo
4800445 Houston
1800091 Indianapolis
1200490 Jacksonville
2900275 Kansas City
3200014 Las Vegas
9100092 Leon
0600316 Los Angeles
9100463 Merida
9100001 Mexicali
9100327 Mexico City
1200297 Miami
5500248 Milwaukee
2700091 Minneapolis
9100351 Monterrey
8800845 Montreal
1200469 Orlando
8801197 Ottawa
4201162 Philadelphia
0400017 Phoenix
4100109 Portland
8801212 Quebec City
2900190 St Louis
4800332 San Antonio
0600580 San Diego
0600209 San Francisco
0600212 San Jose
5300198 Seattle
1200148 Tampa
8801159 Toronto
0400118 Tucson
8802522 Vancouver
1100005 Washington DC
8801752 Winnipeg

21782
Unit 1/rrNodes.txt Normal file

File diff suppressed because it is too large Load Diff

3
Unit 1/testing.py Normal file
View File

@ -0,0 +1,3 @@
file = open("rrNodeCity.txt", "r")
for word in file.readlines():
print(word.strip().split(" ", 1))

4969
Unit 1/words.txt Normal file

File diff suppressed because it is too large Load Diff

21434
Unit 1/words_6_longer.txt Normal file

File diff suppressed because it is too large Load Diff

135
Unit 2/Umaretiya_r_U2_L1.py Normal file
View File

@ -0,0 +1,135 @@
# Name: Rushil Umaretiya
# Period: 1
from tkinter import *
from graphics import *
import random
def check_complete(assignment, vars, adjs):
# check if assignment is complete or not. Goal_Test
for i in vars:
if i not in assignment: return False
for assigned in assignment:
if assigned in adjs:
for adj in adjs[assigned]:
if assignment[assigned] == assignment[adj]: return False
return True
def select_unassigned_var(assignment, vars, adjs):
# Select an unassigned variable - forward checking, MRV, or LCV
var, low = '', 999999
for i in vars:
if len(vars[i]) < low and len(vars[i]) > 0:
var = i
low = len(vars[i])
return var if var != '' else None
def isValid(value, var, assignment, vars, adjs):
# value is consistent with assignment
# check adjacents to check 'var' is working or not.
if var not in adjs: return True
for adj in adjs[var]:
if adj in assignment and value in assignment[adj]: return False
return True
def backtracking_search(variables, adjs, shapes, frame):
return recursive_backtracking({}, variables, adjs, shapes, frame)
def recursive_backtracking(assignment, vars, adjs, shapes, frame):
# Refer the pseudo code given in class.
if check_complete(assignment, vars, adjs):
draw_final_shapes(assignment, shapes, frame)
return assignment
var = select_unassigned_var(assignment, vars, adjs)
for value in vars[var]:
if isValid(value, var, assignment, vars, adjs):
assignment[var] = value
new_vars = dict(vars)
new_vars[var] = {}
if var in adjs:
for i in adjs[var]:
if value in new_vars[i]: new_vars[i].remove(value)
result = recursive_backtracking(assignment, new_vars, adjs, shapes, frame)
if result != None: return result
assignment.pop(var)
return None
def draw_final_shapes(assignment, shapes, frame):
for node in assignment:
draw_shape(shapes[node], frame, assignment[node])
# return shapes as {region:[points], ...} form
def read_shape(filename):
infile = open(filename)
region, points, shapes = "", [], {}
for line in infile.readlines():
line = line.strip()
if line.isalpha():
if region != "": shapes[region] = points
region, points = line, []
else:
x, y = line.split(" ")
points.append(Point(int(x), 300-int(y)))
shapes[region] = points
return shapes
# fill the shape
def draw_shape(points, frame, color):
shape = Polygon(points)
shape.setFill(color)
shape.setOutline("black")
shape.draw(frame)
space = [x for x in range(9999999)] # give some pause
def main():
regions, vars, adjacents = [], {}, {}
# Read mcNodes.txt and store all regions in regions list
for line in open('mcNodes.txt', 'r'): regions.append(line.strip())
# Fill variables by using regions list -- no additional code for this part
for r in regions: vars[r] = {'red', 'green', 'blue'}
# Read mcEdges.txt and fill the adjacents. Edges are bi-directional.
for line in open('mcEdges.txt', 'r'):
line = line.strip().split()
if line[0] not in adjacents: adjacents[line[0]] = [line[1]]
else: adjacents[line[0]].append(line[1])
if line[1] not in adjacents: adjacents[line[1]] = [line[0]]
else: adjacents[line[1]].append(line[0])
# Set graphics -- no additional code for this part
frame = GraphWin('Map', 300, 300)
frame.setCoords(0, 0, 299, 299)
shapes = read_shape("mcPoints.txt")
for s, points in shapes.items():
draw_shape(points, frame, 'white')
# solve the map coloring problem by using backtracking_search -- no additional code for this part
solution = backtracking_search(vars, adjacents, shapes, frame)
print (solution)
mainloop()
if __name__ == '__main__':
main()
''' Sample output:
{'WA': 'red', 'NT': 'green', 'SA': 'blue', 'Q': 'red', 'NSW': 'green', 'V': 'red', 'T': 'red'}
By using graphics functions, visualize the map.
'''

View File

@ -0,0 +1,87 @@
# Name: Rushil Umaretiya
# Date: 11/12/2020
import time
def check_complete(assignment, csp_table):
if assignment.find('.') != -1: return False
for hexa in csp_table:
if len(set([assignment[i] for i in hexa])) != 6: return False
return True
def select_unassigned_var(assignment, csp_table):
if '.' in assignment: return assignment.find('.')
else: return None
def isValid(value, var_index, assignment, csp_table):
csp_indexes = [i for i in range(len(csp_table)) if var_index in csp_table[i]]
for index in csp_indexes:
hex = csp_table[index]
for i in hex:
if i != var_index and assignment[i] == str(value): return False
return True
def backtracking_search(input, csp_table):
return recursive_backtracking(input, csp_table)
def recursive_backtracking(assignment, csp_table):
if check_complete(assignment, csp_table): return assignment
var = select_unassigned_var(assignment, csp_table)
for value in range(1, 7):
if isValid(value, var, assignment, csp_table):
assignment = assignment[:var] + str(value) + assignment[var + 1:]
result = recursive_backtracking(assignment, csp_table)
if result != None: return result
assignment = assignment[:var] + '.' + assignment[var + 1:]
return None
def display(solution):
result = ""
for i in range(len(solution)):
if i == 0: result += " "
if i == 5: result += "\n"
if i == 12: result += "\n"
if i == 19: result += "\n "
result += solution[i] + " "
return result
def main():
csp_table = [[0, 1, 2, 6, 7, 8], [2, 3, 4, 8, 9, 10], [5, 6, 7, 12, 13, 14], [7, 8, 9, 14, 15, 16], [9, 10, 11, 16, 17, 18], [13, 14, 15, 19, 20, 21], [15, 16, 17, 21, 22, 23]]
string = input("24-char(. and 1-6) input: ")
cur_time = time.time()
solution = backtracking_search(string, csp_table)
if solution != None:
print (display(solution))
print ('\n'+ solution)
print (check_complete(solution, csp_table))
print ('Duration:', (time.time() - cur_time))
else: print ("It's not solvable.")
if __name__ == '__main__':
main()
"""
Sample Output 1:
24-char(. and 1-6) input: ........................
1 2 3 1 2
1 4 5 6 4 5 1
2 6 3 1 2 3 6
2 4 5 4 6
123121456451263123624546
True
Sample Output 2:
24-char(. and 1-6) input: 6.....34...1.....2..4...
6 1 2 1 3
1 3 4 5 6 4 1
5 6 2 1 3 2 5
3 4 5 4 6
612131345641562132534546
True
"""

160
Unit 2/Umaretiya_r_U2_L3.py Normal file
View File

@ -0,0 +1,160 @@
# Name: Rushil Umaretiya
# Date: 11/17/20
import time
import copy as cp
def check_complete(assignment, csp_table):
if assignment.find('.') != -1: return False
for area in csp_table:
if len(set([assignment[i] for i in area])) != 9: return False
return True
def select_unassigned_var(assignment, variables, csp_table):
min_val, index = 9999, -1
for i in range(len(assignment)):
if assignment[i] == '.' and len(variables[i]) < min_val:
min_val = len(variables[i])
index = i
return index
def isValid(value, var_index, assignment, variables, csp_table):
csp_indexes = [i for i in range(len(csp_table)) if var_index in csp_table[i]]
for index in csp_indexes:
for i in csp_table[index]:
if i != var_index and assignment[i] == str(value):
return False
return True
def ordered_domain(assignment, variables, csp_table):
return [x for _,x in sorted(zip([assignment.count(str(i)) for i in range(1, 10)],list(range(1,10))), reverse=True)]
def update_variables(value, var_index, assignment, variables, csp_table):
updated = cp.deepcopy(variables)
csp_indexes = [i for i in range(len(csp_table)) if var_index in csp_table[i]]
for index in csp_indexes:
constraint_area = csp_table[index]
for i in constraint_area:
if i != var_index and i in updated and value in updated[i]:
updated[i].remove(value)
return updated
def backtracking_search(puzzle, variables, csp_table):
return recursive_backtracking(puzzle, variables, csp_table)
def recursive_backtracking(assignment, variables, csp_table):
if check_complete(assignment, csp_table):
return assignment
var = select_unassigned_var(assignment, variables, csp_table)
for value in ordered_domain(assignment, variables, csp_table):
if value in variables[var] and isValid(value, var, assignment, variables, csp_table):
assignment = assignment[:var] + str(value) + assignment[var + 1:]
copy = update_variables(value, var, assignment, variables, csp_table)
#copy = cp.deepcopy(variables)
result = recursive_backtracking(assignment, copy, csp_table)
if result != None: return result
assignment = assignment[:var] + '.' + assignment[var + 1:]
return None
def display(solution):
string = ""
for i in range(9):
for j in range(9):
string += solution[(i*9)+j] + " "
if j == 2 or j == 5:
string += " "
string += '\n'
if i == 2 or i == 5:
string +='\n'
return string
def sudoku_csp():
table, square, col, row = [], [0,1,2,9,10,11,18,19,20], [0,9,18,27,36,45,54,63,72], list(range(9))
for i in range(9):
table.append([index+(i*3)+((i//3)*18) for index in square])
table.append([index+i for index in col])
table.append([index+(i*9) for index in row])
return table
def initial_variables(puzzle, csp_table):
vars = {}
for i in range(len(puzzle)):
if puzzle[i] == '.':
vars[i] = list(range(1,10))
return constrain_init(vars, puzzle, csp_table)
def constrain_init (vars, puzzle, csp_table):
updated = dict(vars)
for var_index in range(len(puzzle)):
if puzzle[var_index] != '.':
updated = update_variables(int(puzzle[var_index]), var_index, puzzle, vars, csp_table)
return updated
def main():
#puzzle = input("Type a 81-char string:")
#puzzle = ".21.7...63.9...5.......1...13...8....84...9....6...34......6.87.....36..7...8..9."
#puzzle = "4.....3.....8.2......7........1...8734.......6........5...6........1.4...82......"
#puzzle = "4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......"
puzzle = "3..........5..9...2..5.4....2....7..16.....587.431.6.....89.1......67.8......5437"
while len(puzzle) != 81:
print ("Invalid puzzle")
puzzle = input("Type a 81-char string: ")
csp_table = sudoku_csp()
variables = initial_variables(puzzle, csp_table)
print ("Initial:\n" + display(puzzle))
start_time = time.time()
#import cProfile
#cProfile.runctx('g(puzzle, variables, csp_table)', {'g': backtracking_search, 'puzzle': puzzle, 'variables': variables, 'csp_table': csp_table}, {})
solution = backtracking_search(puzzle,variables,csp_table)
if solution != None: print ("solution\n + display(solution)" + display(solution))
else: print ("No solution found.\n")
print ("Duration:", (time.time() - start_time))
if __name__ == '__main__': main()
"""
..7369825632158947958724316825437169791586432346912758289643571573291684164875293
4 1 7 3 6 9 8 2 5
6 3 2 1 5 8 9 4 7
9 5 8 7 2 4 3 1 6
8 2 5 4 3 7 1 6 9
7 9 1 5 8 6 4 3 2
3 4 6 9 1 2 7 5 8
2 8 9 6 4 3 5 7 1
5 7 3 2 9 1 6 8 4
1 6 4 8 7 5 2 9 3
.3..5..4...8.1.5..46.....12.7.5.2.8....6.3....4.1.9.3.25.....98..1.2.6...8..6..2.
1 3 7 2 5 6 8 4 9
9 2 8 3 1 4 5 6 7
4 6 5 8 9 7 3 1 2
6 7 3 5 4 2 9 8 1
8 1 9 6 7 3 2 5 4
5 4 2 1 8 9 7 3 6
2 5 6 7 3 1 4 9 8
3 9 1 4 2 8 6 7 5
7 8 4 9 6 5 1 2 3
....8....27.....54.95...81...98.64...2.4.3.6...69.51...17...62.46.....38....9....
1 3 4 5 8 7 2 9 6
2 7 8 1 6 9 3 5 4
6 9 5 2 3 4 8 1 7
3 5 9 8 1 6 4 7 2
8 2 1 4 7 3 5 6 9
7 4 6 9 2 5 1 8 3
9 1 7 3 4 8 6 2 5
4 6 2 7 5 1 9 3 8
5 8 3 6 9 2 7 4 1
"""

124
Unit 2/Umaretiya_r_U2_L4.py Normal file
View File

@ -0,0 +1,124 @@
# Name: Rushil Umaretiya
# Date: 12/1/2020
import os, time, operator, copy
def solve(puzzle, neighbors):
''' suggestion:
# q_table is quantity table {'1': number of value '1' occurred, ...}
variables, puzzle, q_table = initialize_ds(puzzle, neighbors)
return recursive_backtracking(puzzle, variables, neighbors, q_table)
'''
variables, puzzle, q_table = initialize_ds(puzzle, neighbors)
return recursive_backtracking(puzzle, variables, neighbors, q_table)
def initialize_ds(puzzle, neighbors):
vars = {}
q_table = {x: 0 for x in range(1, 10)}
for i in range(len(puzzle)):
if puzzle[i] == '.':
vars[i] = list(range(1,10))
else:
q_table[int(puzzle[i])] += 1
return vars, puzzle, q_table
def recursive_backtracking(puzzle, variables, neighbors, q_table):
if check_complete(puzzle, neighbors, q_table): return puzzle
var = select_unassigned_var(puzzle, variables, neighbors)
#for value in [x for _,x in sorted(zip([puzzle.count(str(i)) for i in range(1, 10)],list(range(1,10))), reverse=True)]:
for quantity in sorted(q_table.items(), key=operator.itemgetter(1), reverse=True):
value = quantity[0]
if value in variables[var] and isValid(value, var, puzzle, neighbors):
puzzle = puzzle[:var] + str(value) + puzzle[var + 1:]
copy = update_variables(value, var, puzzle, variables, neighbors)
#copy = {k: list(variables[k]) for k in variables}
q_table[value] += 1
result = recursive_backtracking(puzzle, copy, neighbors, q_table)
if result != None: return result
puzzle = puzzle[:var] + '.' + puzzle[var + 1:]
q_table[value] -= 1
def check_complete(puzzle, neighbors, q_table):
if puzzle.find('.') != -1: return False
for index in range(len(puzzle)):
for neighbor in neighbors[index]:
if puzzle[index] == puzzle[neighbor]: return False
return True
def select_unassigned_var(assignment, variables, csp_table):
min_val, index = 9999, -1
for i in range(len(assignment)):
if assignment[i] == '.':
if len(variables[i]) < min_val:
min_val = len(variables[i])
index = i
return index
def isValid(value, var_index, puzzle, neighbors):
for i in neighbors[var_index]:
if puzzle[i] == str(value):
return False
return True
def update_variables(value, var_index, puzzle, variables, neighbors):
updated = {k: list(variables[k]) for k in variables}
for i in neighbors[var_index]:
if i in updated and value in updated[i]:
updated[i].remove(value)
return updated
def sudoku_neighbors(csp_table):
# each position p has its neighbors {p:[positions in same row/col/subblock], ...}
neighbors = {}
for i in range(81):
temp = []
for constraint in csp_table:
if i in constraint:
removed = list(constraint)
removed.remove(i)
temp += removed
neighbors[i] = set(temp)
return neighbors
def sudoku_csp(n=9):
csp_table = [[k for k in range(i*n, (i+1)*n)] for i in range(n)] # rows
csp_table += [[k for k in range(i,n*n,n)] for i in range(n)] # cols
temp = [0, 1, 2, 9, 10, 11, 18, 19, 20]
csp_table += [[i+k for k in temp] for i in [0, 3, 6, 27, 30, 33, 54, 57, 60]] # sub_blocks
return csp_table
def checksum(solution):
return sum([ord(c) for c in solution]) - 48*81 # One easy way to check a valid solution
def main():
#filename = input("file name: ")
filename = ""
if not os.path.isfile(filename):
filename = "puzzles.txt"
csp_table = sudoku_csp() # rows, cols, and sub_blocks
neighbors = sudoku_neighbors(csp_table) # each position p has its neighbors {p:[positions in same row/col/subblock], ...}
start_time = time.time()
for line, puzzle in enumerate(open(filename).readlines()):
#if line == 50: break # check point: goal is less than 0.5 sec
line, puzzle = line+1, puzzle.rstrip()
print ("Line {}: {}".format(line, puzzle))
solution = solve(puzzle, neighbors)
if solution == None:print ("No solution found."); break
print ("{}({}, {})".format(" "*(len(str(line))+1), checksum(solution), solution))
print ("Duration:", (time.time() - start_time))
if __name__ == '__main__': main()
"""
26.63564682006836
"""

View File

@ -0,0 +1,126 @@
# Name: Rushil Umaretiya
# Date: 12/1/2020
import os, time, operator, copy
def solve(puzzle, neighbors):
''' suggestion:
# q_table is quantity table {'1': number of value '1' occurred, ...}
variables, puzzle, q_table = initialize_ds(puzzle, neighbors)
return recursive_backtracking(puzzle, variables, neighbors, q_table)
'''
variables, puzzle, q_table = initialize_ds(puzzle, neighbors)
return recursive_backtracking(puzzle, variables, neighbors, q_table)
def initialize_ds(puzzle, neighbors):
vars = {}
q_table = {x: 0 for x in range(1, 10)}
for i in range(len(puzzle)):
if puzzle[i] == '.':
vars[i] = list(range(1,10))
else:
q_table[int(puzzle[i])] += 1
return vars, puzzle, q_table
def recursive_backtracking(puzzle, variables, neighbors, q_table):
if check_complete(puzzle, neighbors, variables): return puzzle
var = select_unassigned_var(puzzle, variables, neighbors)
for value in ordered_domain(var, variables, q_table):
if q_table[value] < 9 and isValid(value, var, puzzle, neighbors):
puzzle = puzzle[:var] + str(value) + puzzle[var + 1:]
q_table[value] += 1
result = recursive_backtracking(puzzle, update_variables(value, var, puzzle, variables, neighbors), neighbors, q_table)
if result != None: return result
puzzle = puzzle[:var] + '.' + puzzle[var + 1:]
q_table[value] -= 1
def ordered_domain(var, variables, q_table):
return sorted(variables[var], key=lambda k: q_table[k], reverse=True)
def check_complete(puzzle, neighbors, variables):
if len(variables) != 0: return False
for index in range(len(puzzle)):
for neighbor in neighbors[index]:
if puzzle[index] == puzzle[neighbor]: return False
return True
def select_unassigned_var(puzzle, variables, neighbors):
min, index = 9999, -1
for i in variables:
if min > len(variables[i]):
min = len(variables[i])
index = i
return index
#return min(variables, key=lambda k: len(variables[k]))
def isValid(value, var_index, puzzle, neighbors):
value_string = str(value)
for i in neighbors[var_index]:
if puzzle[i] == value_string:
return False
return True
def update_variables(value, var_index, puzzle, variables, neighbors):
updated = {k: list(variables[k]) for k in variables}
del updated[var_index]
for i in neighbors[var_index]:
if i in updated and value in updated[i]:
updated[i].remove(value)
return updated
def sudoku_neighbors(csp_table):
# each position p has its neighbors {p:[positions in same row/col/subblock], ...}
neighbors = {}
for i in range(81):
temp = []
for constraint in csp_table:
if i in constraint:
removed = list(constraint)
removed.remove(i)
temp += removed
neighbors[i] = set(temp)
return neighbors
def sudoku_csp(n=9):
csp_table = [[k for k in range(i*n, (i+1)*n)] for i in range(n)] # rows
csp_table += [[k for k in range(i,n*n,n)] for i in range(n)] # cols
temp = [0, 1, 2, 9, 10, 11, 18, 19, 20]
csp_table += [[i+k for k in temp] for i in [0, 3, 6, 27, 30, 33, 54, 57, 60]] # sub_blocks
return csp_table
def checksum(solution):
return sum([ord(c) for c in solution]) - 48*81 # One easy way to check a valid solution
def main():
#filename = input("file name: ")
filename = ""
if not os.path.isfile(filename):
filename = "puzzles.txt"
csp_table = sudoku_csp() # rows, cols, and sub_blocks
neighbors = sudoku_neighbors(csp_table) # each position p has its neighbors {p:[positions in same row/col/subblock], ...}
start_time = time.time()
puzzle = "4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......"
import cProfile
cProfile.runctx('g(puzzle, neighbors)', {'g': solve, 'puzzle': puzzle, 'neighbors': neighbors}, {})
"""
for line, puzzle in enumerate(open(filename).readlines()):
# if line == 50: break # check point: goal is less than 0.5 sec
line, puzzle = line+1, puzzle.rstrip()
print ("Line {}: {}".format(line, puzzle))
solution = solve(puzzle, neighbors)
if solution == None:print ("No solution found."); break
print ("{}({}, {})".format(" "*(len(str(line))+1), checksum(solution), solution))
"""
print ("Duration:", (time.time() - start_time))
if __name__ == '__main__': main()

1015
Unit 2/graphics.py Normal file

File diff suppressed because it is too large Load Diff

9
Unit 2/mcEdges.txt Normal file
View File

@ -0,0 +1,9 @@
WA NT
WA SA
NT SA
SA Q
SA NSW
SA V
Q NSW
Q NT
V NSW

7
Unit 2/mcNodes.txt Normal file
View File

@ -0,0 +1,7 @@
WA
NT
SA
Q
NSW
V
T

91
Unit 2/mcPoints.txt Normal file
View File

@ -0,0 +1,91 @@
WA
16 137
38 210
123 184
123 140
120 61
103 52
66 96
NT
120 61
137 37
176 37
170 56
183 72
182 140
123 140
SA
123 184
123 140
182 140
201 143
200 164
198 204
195 234
188 228
178 193
163 208
153 190
Q
183 72
182 140
201 143
200 164
250 169
258 168
265 172
273 167
281 168
280 150
268 123
256 104
242 95
237 62
230 55
226 56
219 28
205 75
191 74
183 72
NSW
200 164
250 169
258 168
265 172
273 167
281 168
269 200
249 231
239 229
237 222
221 218
218 220
210 207
206 209
203 203
198 204
V
249 231
239 229
237 222
221 218
218 220
210 207
206 209
203 203
198 204
195 234
209 240
220 232
225 243
236 237
T
215 256
219 266
220 277
226 278
230 274
232 276
236 263
234 258
225 260

128
Unit 2/puzzles.txt Normal file
View File

@ -0,0 +1,128 @@
.17369825632158947958724316825437169791586432346912758289643571573291684164875293
4.7369825632158947958724316825437169791586432346912758289643571573291684164875293
..7369825632158947958724316825437169791586432346912758289643571573291684164875293
.1736982563215894795872431682543716979158643234691275828964357157329168416487529.
81497653265912347873.854169948265317275341896163798245391682754587439621426517983
814976532659123478.3.854169948265317275341896163798245391682754587439621426517983
81497653265.123478.3.854169948265317275341896163798245391682754587439621426517983
814976532.5.123478.3.854169948265317275341896163798245391682754587439621426517983
81.976532.5.123478.3.854169948265317275341896163798245391682754587439621426517983
8..976532.5.123478.3.854169948265317275341896163798245391682754587439621426517983
...976532.5.123478.3.854169948265317275341896163798245391682754587439621426517983
..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..
2...8.3...6..7..84.3.5..2.9...1.54.8.........4.27.6...3.1..7.4.72..4..6...4.1...3
......9.7...42.18....7.5.261..9.4....5.....4....5.7..992.1.8....34.59...5.7......
.3..5..4...8.1.5..46.....12.7.5.2.8....6.3....4.1.9.3.25.....98..1.2.6...8..6..2.
.2.81.74.7....31...9...28.5..9.4..874..2.8..316..3.2..3.27...6...56....8.76.51.9.
1..92....524.1...........7..5...81.2.........4.27...9..6...........3.945....71..6
.43.8.25.6.............1.949....4.7....6.8....1.2....382.5.............5.34.9.71.
48...69.2..2..8..19..37..6.84..1.2....37.41....1.6..49.2..85..77..9..6..6.92...18
...9....2.5.1234...3....16.9.8.......7.....9.......2.5.91....5...7439.2.4....7...
..19....39..7..16..3...5..7.5......9..43.26..2......7.6..1...3..42..7..65....68..
...1254....84.....42.8......3.....95.6.9.2.1.51.....6......3.49.....72....1298...
.6234.75.1....56..57.....4.....948..4.......6..583.....3.....91..64....7.59.8326.
3..........5..9...2..5.4....2....7..16.....587.431.6.....89.1......67.8......5437
63..........5....8..5674.......2......34.1.2.......345.....7..4.8.3..9.29471...8.
....2..4...8.35.......7.6.2.31.4697.2...........5.12.3.49...73........1.8....4...
361.259...8.96..1.4......57..8...471...6.3...259...8..74......5.2..18.6...547.329
.5.8.7.2.6...1..9.7.254...6.7..2.3.15.4...9.81.3.8..7.9...762.5.6..9...3.8.1.3.4.
.8...5........3457....7.8.9.6.4..9.3..7.1.5..4.8..7.2.9.1.2....8423........1...8.
..35.29......4....1.6...3.59..251..8.7.4.8.3.8..763..13.8...1.4....2......51.48..
...........98.51...519.742.29.4.1.65.........14.5.8.93.267.958...51.36...........
.2..3..9....9.7...9..2.8..5..48.65..6.7...2.8..31.29..8..6.5..7...3.9....3..2..5.
..5.....6.7...9.2....5..1.78.415.......8.3.......928.59.7..6....3.4...1.2.....6..
.4.....5...19436....9...3..6...5...21.3...5.68...2...7..5...2....24367...3.....4.
..4..........3...239.7...8.4....9..12.98.13.76..2....8.1...8.539...4..........8..
36..2..89...361............8.3...6.24..6.3..76.7...1.8............418...97..3..14
5..4...6...9...8..64..2.........1..82.8...5.17..5.........9..84..3...6...6...3..2
..72564..4.......5.1..3..6....5.8.....8.6.2.....1.7....3..7..9.2.......4..63127..
..........79.5.18.8.......7..73.68..45.7.8.96..35.27..7.......5.16.3.42..........
.3.....8...9...5....75.92..7..1.5..8.2..9..3.9..4.2..1..42.71....2...8...7.....9.
2..17.6.3.5....1.......6.79....4.7.....8.1.....9.5....31.4.......5....6.9.6.37..2
.......8.8..7.1.4..4..2..3.374...9......3......5...321.1..6..5..5.8.2..6.8.......
.......85...21...996..8.1..5..8...16.........89...6..7..9.7..523...54...48.......
6.8.7.5.2.5.6.8.7...2...3..5...9...6.4.3.2.5.8...5...3..5...2...1.7.4.9.4.9.6.7.1
.5..1..4.1.7...6.2...9.5...2.8.3.5.1.4..7..2.9.1.8.4.6...4.1...3.4...7.9.2..6..1.
.53...79...97534..1.......2.9..8..1....9.7....8..3..7.5.......3..76412...61...94.
..6.8.3...49.7.25....4.5...6..317..4..7...8..1..826..9...7.2....75.4.19...3.9.6..
..5.8.7..7..2.4..532.....84.6.1.5.4...8...5...7.8.3.1.45.....916..5.8..7..3.1.6..
...9..8..128..64...7.8...6.8..43...75.......96...79..8.9...4.1...36..284..1..7...
....8....27.....54.95...81...98.64...2.4.3.6...69.51...17...62.46.....38....9....
...6.2...4...5...1.85.1.62..382.671...........194.735..26.4.53.9...2...7...8.9...
4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......
52...6.........7.13...........4..8..6......5...........418.........3..2...87.....
6.....8.3.4.7.................5.4.7.3..2.....1.6.......2.....5.....8.6......1....
48.3............71.2.......7.5....6....2.58.............1.76...3.....4......5....
....14....3....2...7..........9...3.6.1.............8.2.....1.4....5.6.....7.8...
......52..8.4......3...9...5.1...6..2..7.6......3.....6...13.........7.4.......3.
6.2.5.........3.4..........43...8....1....2........73.5..27...........81...6.....
.524.........7.1..............8.2...3.....6...9.5.....1.6.3...........897........
6.2.5.........4.3..........43...8....1....2........7..5..27...........81...6.....
.923.........8.1...........1.7.4...........658.........6.5.2.1.4.....7.....9.....
6..3.2....5.....1..........7.26............543.........8.15........4.2........7..
.6.5.1.9.1...9..539....7....4.8...7.......5.8.817.5.3.....5.2............76..8...
..5...987.4..5...1..7......2...48....9.1.....6..2.....3..6..2.......9.7.......5..
3.6.7...........518.........1.4.5...7.....6.....2......2.....4.....8.3.....5.....
1.....3.8.7.4..............2.3.1...........958.........5.6...7.....8.2...4.......
6..3.2....4.....1..........7.26............543.........8.15........4.2........7..
....3..9....2....1.5.9..............1.2.8.4.6.8.5...2..75......4.1..6..3.....4.6.
45.....3....8.1....9...........5..9.2..7.....8.........1..4..........7.2...6..8..
.237....68...6.59.9.....7......4.97.3.7.96..2.........5..47.........2....8.......
..84...3....3.....9....157479...8........7..514.....2...9.6...2.5....4......9..56
.98.1....2......6.............3.2.5..84.........6.........4.8.931.5...........1..
..247..58..............1.4.....2...9528.9.4....9...1.........3.3....75..685..2...
4.....8.5.3..........7......2.....6.....5.4......1.......6.3.7.5..2.....1.9......
.2.3......63.....58.......15....9.3....7........1....8.879..26......6.7...6..7..4
1.....7.9.4...72..8.........7..1..6.3.......5.6..4..2.........8..53...7.7.2....46
4.....3.....8.2......7........1...8734.......6........5...6........1.4...82......
.......71.2.8........4.3...7...6..5....2..3..9........6...7.....8....4......5....
6..3.2....4.....8..........7.263...........543.........8.15........832........7..
.47.8...1............6..7..6....357......5....1..6....28..4.....9.1...4.....2.69.
......8.17..2........5.6......7...5..1....3...8.......5......2..4..8....6...3....
38.6.......9.......2..3.51......5....3..1..6....4......17.5..8.......9.......7.32
...5...........5.697.....2...48.2...25.1...3..8..3.........4.7..13.5..9..2...31..
.2.......3.5.62..9.68...3...5..........64.8.2..47..9....3.....1.....6...17.43....
.8..4....3......1........2...5...4.69..1..8..2...9.......369....6....5.....2.....
..8.9.1...6.5...2......6....3.1.7.5.........9..4...3...5....2...7...3.8.2..7....4
4.....5.8.3..........7......2.....6.....5.8......1.......6.3.7.5..2.....1.8......
1.....3.8.6.4..............2.3.1...........958.........5.6...7.....8.2...4.......
1....6.8..64..........4...7....9.6...7.4..5..5...7.1...5....32.3....8...4........
249.6...3.3....2..8.......5.....6......2......1..4.82..9.5..7....4.....1.7...3...
...8....9.873...4.6..7.......85..97...........43..75.......3....3...145.4....2..1
...5.1....9.6..8...6.......421..........7..9........3.8.....1.5...2..4.....36....
......8.16..2........7.5......6...2..1....3...8.......2......7..3..8....5...4....
.476...5.8.3.....2.....9......8.5..6...1.....6.24......78...51...6....4..9...4..7
.....7.95.....1...86..2.....2..73..85......6...3..49..3.5...41724................
.4.5.....8...9..3..76.2.....146..........9..7.....36....1..4.5..6......3..71..2..
.834.........7..5...........471.8..........27...3.....2.6.5....5.....8........1..
..9.....3.....9...7.....5.6..65..4.....3......28......3..75.6..6...........12.3.8
.26.39......6....19.....7.......4..9.5....2....85.....3..2..9..4....762.........4
2.3.8....8..7...........1...6.5.7...4......3....1............82.5....6...1.......
6..3.2....1.....5..........7.26............843.........8.15........8.2........7..
1.....9...64..1.7..7..4.......3.....3.89..5....7....2.....6.7.9.....4.1....129.3.
.........9......84.623...5....6...453...1...6...9...7....1.....4.5..2....3.8....9
.2....5938..5..46.94..6...8..2.3.....6..8.73.7..2.........4.38..7....6..........5
9.4..5...25.6..1..31......8.7...9...4..26......147....7.......2...3..8.6.4.....9.
...52.....9...3..4......7...1.....4..8..453..6...1...87.2........8....32.4..8..1.
53..2.9...24.3..5...9..........1.827...7.........981.............64....91.2.5.43.
1....786...7..8.1.8..2....9........24...1......9..5...6.8..........5.9.......93.4
....5...11......7..6.....8......4.....9.1.3.....596.2..8..62..7..7......3.5.7.2..
.47.2....8....1....3....9.2.....5...6..81..5.....4.....7....3.4...9...1.4..27.8..
......94.....9...53....5.7..8.4..1..463...........7.8.8..7.....7......28.5.26....
.2......6....41.....78....1......7....37.....6..412....1..74..5..8.5..7......39..
1.....3.8.6.4..............2.3.1...........758.........7.5...6.....8.2...4.......
2....1.9..1..3.7..9..8...2.......85..6.4.........7...3.2.3...6....5.....1.9...2.5
..7..8.....6.2.3...3......9.1..5..6.....1.....7.9....2........4.83..4...26....51.
...36....85.......9.4..8........68.........17..9..45...1.5...6.4....9..2.....3...
34.6.......7.......2..8.57......5....7..1..2....4......36.2..1.......9.......7.82
......4.18..2........6.7......8...6..4....3...1.......6......2..5..1....7...3....
.4..5..67...1...4....2.....1..8..3........2...6...........4..5.3.....8..2........
.......4...2..4..1.7..5..9...3..7....4..6....6..1..8...2....1..85.9...6.....8...3
8..7....4.5....6............3.97...8....43..5....2.9....6......2...6...7.71..83.2
.8...4.5....7..3...3........1..85...6.....28.....4....3.26............417........
1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..
..53.....8......2..7..1.5..4....53...1..7...6..32...8..6.5....9..4....3......97..
..........1.62..9...2..931...4..6.8...87.21...3.8..5...691..4...8..73.5..........
.21.7...63.9...5.......1...13...8....84...9....6...34......6.87.....36..7...8..9.
85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.
..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9

99
Unit 2/quiz.py Normal file
View File

@ -0,0 +1,99 @@
"""
def solve(board, col):
if check_complete(board, col): return board
for row in range(len(board)):
if isValid(row,col,board):
board[row][col] = 1
result = solve(board, col+1)
if result != None: return result
board[row][col] = 0
return None
def check_complete(board, colNum):
return len(board) == sum(map(sum,board))
def isValid(row,col,board):
for x in range(col):
if board[row][x] == 1:
return False
for i, j in zip(range(row, -1,-1), range(col, -1, -1)):
if board[i][j] == 1:
return False
for i, j in zip(range(row, len(board),1), range(col, -1, -1)):
if board[i][j] == 1:
return False
return True
def main():
board = [[0 for i in range(8)] for j in range(8)]
solution = solve(board,0)
print(board)
if __name__ == "__main__":
main()
"""
def check_complete(table, variables):
total_vars = len(variables) + 2
if len([i for i, x in enumerate(table) if x != ""]) != total_vars: return False
distances, indicies = [], [i for i, x in enumerate(table) if x != ""]
for i in range(len(indicies)):
for j in range(i+1, len(indicies)):
distances.append(abs(indicies[i]-indicies[j]))
if len(set(distances)) != len(distances): return False
else: return True
def isValid(table, index, current):
distances, indicies = [], [i for i, x in enumerate(table) if x != ""]
for i in range(len(indicies)):
for j in range(i+1, len(indicies)):
distances.append(abs(indicies[i]-indicies[j]))
if len(set(distances)) != len(distances): return False
else: return True
def search(table):
table[0] = 'TA'
# return backtrack(table, ['A','B','C','D'], 0)
indicies = []
for i in range(1, len(table)):
copy = list(table)
copy[i] = 'A'
solution = backtrack(copy, ['B','C','D'], 0)
if solution != None: indicies.append([i for i, x in enumerate(solution) if x != ""])
distinct = set(tuple(x) for x in indicies)
print(distinct)
print(len(distinct), " distinct solutions")
print()
print()
return indicies
def backtrack(table, variables, current):
if check_complete(table, variables):
return table
for index in [i for i, x in enumerate(table) if x == ""]:
if isValid(table, index, current):
table[index] = variables[current]
result = backtrack(table, variables, current+1)
if result != None: return result
table[index] = ""
return None
def main():
table = ['' for i in range(13)]
solution = search(table)
if solution != None:
print(solution)
else:
print("sorry no solution and u failed the quiz")
if __name__ == "__main__":
main()

99
Unit 2/retake.py Normal file
View File

@ -0,0 +1,99 @@
"""
def solve(board, col):
if check_complete(board, col): return board
for row in range(len(board)):
if isValid(row,col,board):
board[row][col] = 1
result = solve(board, col+1)
if result != None: return result
board[row][col] = 0
return None
def check_complete(board, colNum):
return len(board) == sum(map(sum,board))
def isValid(row,col,board):
for x in range(col):
if board[row][x] == 1:
return False
for i, j in zip(range(row, -1,-1), range(col, -1, -1)):
if board[i][j] == 1:
return False
for i, j in zip(range(row, len(board),1), range(col, -1, -1)):
if board[i][j] == 1:
return False
return True
def main():
board = [[0 for i in range(8)] for j in range(8)]
solution = solve(board,0)
print(board)
if __name__ == "__main__":
main()
"""
def check_complete(table, variables):
total_vars = len(variables) + 2
if len([i for i, x in enumerate(table) if x != ""]) != total_vars: return False
distances, indicies = [], [i for i, x in enumerate(table) if x != ""]
for i in range(len(indicies)):
for j in range(i+1, len(indicies)):
distances.append(abs(indicies[i]-indicies[j]))
if len(set(distances)) != len(distances): return False
else: return True
def isValid(table, index, current):
distances, indicies = [], [i for i, x in enumerate(table) if x != ""]
for i in range(len(indicies)):
for j in range(i+1, len(indicies)):
distances.append(abs(indicies[i]-indicies[j]))
if len(set(distances)) != len(distances): return False
else: return True
def search(table):
table[0] = 'TA'
# return backtrack(table, ['A','B','C','D'], 0)
indicies = []
for i in range(1, len(table)):
copy = list(table)
copy[i] = 'A'
solution = backtrack(copy, ['B','C','D'], 0)
if solution != None: indicies.append([i for i, x in enumerate(solution) if x != ""])
distinct = set(tuple(x) for x in indicies)
print(distinct)
print(len(distinct), " distinct solutions")
print()
print()
return indicies
def backtrack(table, variables, current):
if check_complete(table, variables):
return table
for index in [i for i, x in enumerate(table) if x == ""]:
if isValid(table, index, current):
table[index] = variables[current]
result = backtrack(table, variables, current+1)
if result != None: return result
table[index] = ""
return None
def main():
table = ['' for i in range(12)]
solution = search(table)
if solution != None:
print(solution)
else:
print("sorry no solution and u failed the quiz")
if __name__ == "__main__":
main()

14
Unit 2/testing.py Normal file
View File

@ -0,0 +1,14 @@
from tkinter import *
from graphics import *
def main():
frame = GraphWin('Map', 300, 200) # pop-up window
frame.setCoords(0, 0, 299, 199) # 300 by 200
shape = Polygon([Point(50, 100), Point(100, 150), Point(150, 100)]) # Triangle
shape.setFill("red")
shape.setOutline("black")
shape.draw(frame)
mainloop()
main()

123
Unit 3/Umaretiya_r_U3_L1.py Normal file
View File

@ -0,0 +1,123 @@
# Name: Rushil Umaretiya
# Date: 12/10/2020
def successors(state, turn):
sli = [i for i in range(len(state)) if state[i] == '.']
ret = [(state, state[0:i] + turn + state[i+1:]) for i in sli]
return ret # [(previous state, new state), ...]
def terminal_test(state, tc):
if state.find('.') < 0: return True # check empty spot
for li in tc:
check_li = [state[x] for x in li]
if len(set(check_li)) == 1 and check_li[0] != '.':
return True
return False
def utility(turn, tc, state):
# return 1 (turn wins), -1 (turn loses), or 0 (tie)
for li in tc:
check_li = [state[x] for x in li]
if len(set(check_li)) == 1 and check_li[0] != '.':
if turn != check_li[0]:
return 1
else:
return -1
return 0
def minimax(state, turn, tc):
max_val = max_value(state, turn, tc) # returns state
return max_val[1]
def max_value(state, turn, tc):
# return value and state: (val, state)
if terminal_test(state, tc):
return utility('X' if turn == 'O' else 'O', tc, state), state
v = -99999
result = state
for curr_state, successor in successors(state, turn):
min_val, min_state = min_value(successor, 'X' if turn == 'O' else 'O', tc)
if v < min_val:
if v == 1: return v, result
v = min_val
result = successor
return v, result
def min_value(state, turn, tc):
# return value and state: (val, state)
if terminal_test(state, tc):
return utility(turn, tc, state), state
v = 99999
result = state
for curr_state, successor in successors(state, turn):
max_val, max_state = max_value(successor, 'X' if turn == 'O' else 'O', tc)
if v > max_val:
if v == -1: return v, result
v = max_val
result = successor
return v, result
def get_turn(state):
count = {'X': 0, 'O': 0, '.':9}
for s in state: count[s] += 1
return 'O' if count['O'] < count['X'] else 'X'
def conditions_table(n=3, n2=9):
ret = [[] for i in range(n*2+2)]
for i in range(n2):
ret[i//n].append(i) # rows: [0, 1, 2], [3, 4, 5], [6, 7, 8]
ret[n+i%n].append(i) # cols: [0, 3, 6], [1, 4, 7], [2, 5, 8]
if i//n == i % n: ret[n+n].append(i) # diagonal \: [0, 4, 8]
if i // n == n - i%n - 1: ret[n+n+1].append(i) # diagonal /: [2, 4, 6]
return ret
def display(state, n=3, n2=9):
str = ""
for i in range(n2):
str += state[i] + ' '
if i % n == n-1: str += '\n'
return str
def human_play(s, n, turn):
index_li = [x for x in range(len(s)) if s[x] == '.']
for i in index_li:
print ('[%s] (%s, %s)' % (i, i//n, i%n))
index = int(input("What's your input? (Type a number): "))
while s[index] != '.':
index = int(input("Invalid. What's your input? "))
state = s[0:index] + turn + s[index+1:]
return state
def main():
X = input("X is human or AI? (h: human, a: AI) ")
O = input("O is human or AI? (h: human, a: AI) ")
state = input("input state (ENTER if it's an empty state): ")
if len(state) == 0: state = '.........'
turn = get_turn(state)
tc = conditions_table(3, 9)
print ("Game start!")
print (display(state, 3, 9))
while terminal_test(state, tc) == False:
if turn == 'X':
print ("{}'s turn:".format(turn))
if X == 'a': state = minimax(state, turn, tc)
else: state = human_play(state, 3, turn)
print (display(state, 3, 9))
turn = 'O'
else:
print ("{}'s turn:".format(turn))
if O == 'a': state = minimax(state, turn, tc)
else: state = human_play(state, 3, turn)
print (display(state, 3, 9))
turn = 'X'
if utility(turn, tc, state) == 0:
print ("Game over! Tie!")
else:
turn = 'O' if turn == 'X' else 'X'
print ('Game over! ' + turn + ' win!')
if __name__ =='__main__':
main()

View File

@ -0,0 +1,123 @@
# Name: Rushil Umaretiya
# Date: 12/10/2020
def successors(state, turn):
sli = [i for i in range(len(state)) if state[i] == '.']
ret = [(state, state[0:i] + turn + state[i+1:]) for i in sli]
return ret # [(previous state, new state), ...]
def terminal_test(state, tc):
if state.find('.') < 0: return True # check empty spot
for li in tc:
check_li = [state[x] for x in li]
if len(set(check_li)) == 1 and check_li[0] != '.':
return True
return False
def utility(turn, tc, state):
# return 1 (turn wins), -1 (turn loses), or 0 (tie)
for li in tc:
check_li = [state[x] for x in li]
if len(set(check_li)) == 1 and check_li[0] != '.':
if turn != check_li[0]:
return 1
else:
return -1
return 0
def minimax(state, turn, tc):
max_val = max_value(state, turn, tc) # returns state
return max_val[1]
def max_value(state, turn, tc):
# return value and state: (val, state)
if terminal_test(state, tc):
return utility('X' if turn == 'O' else 'O', tc, state), state
v = -99999
result = state
for curr_state, successor in successors(state, turn):
min_val, min_state = min_value(successor, 'X' if turn == 'O' else 'O', tc)
if v < min_val:
if v == 1: return v, result
v = min_val
result = successor
return v, result
def min_value(state, turn, tc):
# return value and state: (val, state)
if terminal_test(state, tc):
return utility(turn, tc, state), state
v = 99999
result = state
for curr_state, successor in successors(state, turn):
max_val, max_state = max_value(successor, 'X' if turn == 'O' else 'O', tc)
if v > max_val:
if v == -1: return v, result
v = max_val
result = successor
return v, result
def get_turn(state):
count = {'X': 0, 'O': 0, '.':9}
for s in state: count[s] += 1
return 'O' if count['O'] < count['X'] else 'X'
def conditions_table(n=3, n2=9):
ret = [[] for i in range(n*2+2)]
for i in range(n2):
ret[i//n].append(i) # rows: [0, 1, 2], [3, 4, 5], [6, 7, 8]
ret[n+i%n].append(i) # cols: [0, 3, 6], [1, 4, 7], [2, 5, 8]
if i//n == i % n: ret[n+n].append(i) # diagonal \: [0, 4, 8]
if i // n == n - i%n - 1: ret[n+n+1].append(i) # diagonal /: [2, 4, 6]
return ret
def display(state, n=3, n2=9):
str = ""
for i in range(n2):
str += state[i] + ' '
if i % n == n-1: str += '\n'
return str
def human_play(s, n, turn):
index_li = [x for x in range(len(s)) if s[x] == '.']
for i in index_li:
print ('[%s] (%s, %s)' % (i, i//n, i%n))
index = int(input("What's your input? (Type a number): "))
while s[index] != '.':
index = int(input("Invalid. What's your input? "))
state = s[0:index] + turn + s[index+1:]
return state
def main():
X = input("X is human or AI? (h: human, a: AI) ")
O = input("O is human or AI? (h: human, a: AI) ")
state = input("input state (ENTER if it's an empty state): ")
if len(state) == 0: state = '.........'
turn = get_turn(state)
tc = conditions_table(3, 9)
print ("Game start!")
print (display(state, 3, 9))
while terminal_test(state, tc) == False:
if turn == 'X':
print ("{}'s turn:".format(turn))
if X == 'a': state = minimax(state, turn, tc)
else: state = human_play(state, 3, turn)
print (display(state, 3, 9))
turn = 'O'
else:
print ("{}'s turn:".format(turn))
if O == 'a': state = minimax(state, turn, tc)
else: state = human_play(state, 3, turn)
print (display(state, 3, 9))
turn = 'X'
if utility(turn, tc, state) == 0:
print ("Game over! Tie!")
else:
turn = 'O' if turn == 'X' else 'X'
print ('Game over! ' + turn + ' win!')
if __name__ =='__main__':
main()