forked from kawsarhussen16/Sprint-Challenge--Hash-BC
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from WebWallen/daniel-wallen
Hash Tables Application, Block Chain Mining, and Data Structures Interview Q's
- Loading branch information
Showing
7 changed files
with
197 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
Explain in detail the workings of a dynamic array: | ||
|
||
* What is the four step process to creating an array? | ||
1. Determine how big it needs to be | ||
2. Request a block of memory that fits those needs | ||
3. Receive the memory address of the reserved block | ||
4. Write your values into the array | ||
|
||
* How much memory does an array require? | ||
It depends how many integers there are. | ||
Each integer requires four bytes of memory. | ||
Thus, we multiply four by the array's length. | ||
|
||
* How do we access the index of an array element? | ||
index * sizeof(type) + start_address | ||
|
||
*What is the runtime complexity of the search operation? | ||
O(1) -- arrays are the most time and space efficient operation | ||
|
||
*What is the difference between arrays and Python lists? | ||
Python lists are just arrays with less complexity and more built-in functionality | ||
|
||
*What is the process for adding an element to the end of an array? | ||
1. Take size of current array and increase it by one. | ||
2. Request a block of memory fitting the new size. | ||
3. Copy each element from old to new space (happens one element at a time). | ||
4. Free the memory from the old array. | ||
|
||
*What is the runtime complexity of the insert operation? | ||
O(n) | ||
|
||
*How does the insert process differ on Python? | ||
1. It allocates a few empty spaces to the end every time an array grows. | ||
2. Each time it grows, the amount of extra spaces will increase as well. | ||
3. Time complexity is usually O(1) but can be O(n). | ||
|
||
*How is this different from the way Python pushes elements to the front? | ||
1. Check if there's an empty space at the end. | ||
2. If not: allocate a new array, place first element, copy the rest, and free memory from old array. | ||
3. If so: move each element to the right (starting from the end) and place new element in front | ||
|
||
*What is the runtime complexity of the append operation? | ||
O(n^2) | ||
|
||
*Why is it so much faster to add an array to the back of array? | ||
In a best case scenario, you can simply add it to the end without operating on any other elements. This is typically 600x faster than adding to front. | ||
|
||
* What is the worse case scenario if you try to extend the storage size of a dynamic array? | ||
If the dynamic array doesn't have any room for a new item, this can cause a temporary slow down. Or O(n) time complexity. | ||
|
||
* What are some examples of hash tables? | ||
1. Associative arrays and dictionaries | ||
2. Objects (Python, Javascript, Ruby) | ||
3. Caches (Memcached) | ||
4. Dynamic programming, memorization | ||
|
||
* What is a hash table anyway? | ||
1. Devide for key/value storage and retrieval | ||
2. Contigious block of memory (next to each other) | ||
3. Key converted to an integer via a hash function | ||
4. Hashed key converted to array index via modulo function | ||
|
||
*What is a hash function? | ||
It achieves one-way mapping from arbitrary data to fixed data size and type | ||
|
||
*What are some different types of hash functions? | ||
1. Deterministic (same input always results in same output) | ||
2. Uniform distribution (on average very far away from original input) | ||
3. Non-invertible (can't use the output to reverse engineer the input used) | ||
|
||
*What is the process for creating a hash table? | ||
1. Declare an empty array (power of 2). | ||
2. Hash the key. | ||
3. Assign value to hash index. | ||
|
||
*What is the storage device for hash table elements? | ||
Linked lists. To retrieve a value, you traverse down the LL until you find matching key. | ||
|
||
*What is the time complexity of a linked list? | ||
O(n) for insertion, deletion, and retrieval. Ditto for space. | ||
|
||
*How does hash table resizing work? | ||
Use a load factor (number of entries / hash table capacity) | ||
When load factor passes a certain threshold, resizing occurs | ||
-Create a new hash table with double capacity | ||
-Copy elements from old to new one-at-a-time | ||
-Resizing is O(n) but occurs at O(logn) frequency | ||
|
||
*Explain the purpose and meaning of blockchain. | ||
1. Blockchain is a data structure and support system holding a public ledger of transactions. | ||
2. It is not owned by any person or entity -- anyone can make a copy. | ||
3. Everyone has access to source code, but it's still secure due to cryptography. | ||
|
||
*What are the blocks, what is the chain? How is the data organized? | ||
Blocks hold index, time stamp, list of transactions, proof used to mine block, and hash of previous block. | ||
Blocks are listed in a chain and must be linked by matching hashes, which prevents people from stealing funds. | ||
Longest chain = what gets trusted. Thus, you'd have to change every single hash since they are all connected. | ||
|
||
*Explain how proof of work functions. How does it operate. How does this protect the chain from attack. What kind of attack is possible? | ||
Proof of work uses several complicated hashing mechanisms to make the task of guessing any identifying information near impossible. | ||
It "proves" that work happened by solving an arbitrary and complicated computational math problem. Risk = gains over 51% computational power. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,4 +11,4 @@ requests = "==2.18.4" | |
flask = "==0.12.2" | ||
|
||
[requires] | ||
python_version = "3.7" | ||
python_version = "3.8" |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
NONAME | ||
daniel-wallen |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,36 @@ | ||
# Hint: You may not need all of these. Remove the unused functions. | ||
from hashtables import (HashTable, | ||
hash_table_insert, | ||
hash_table_remove, | ||
hash_table_retrieve, | ||
hash_table_resize) | ||
hash_table_retrieve) | ||
|
||
|
||
def get_indices_of_item_weights(weights, length, limit): | ||
# Initialize hashtable and set its capacity to 16 | ||
ht = HashTable(16) | ||
|
||
""" | ||
YOUR CODE HERE | ||
""" | ||
|
||
# For the first weight in the range from 0 to length... | ||
for weight_1 in range(0, length): | ||
# Insert the hashtable, [weight key], and weight value | ||
hash_table_insert(ht, weights[weight_1], weight_1) | ||
# For the second weight in the range from 0 to length... | ||
for weight_2 in range(0, length): | ||
# Subtract [weight value] from limit and assign result to matching_weight | ||
matching_weight = limit - weights[weight_2] | ||
# Retrieve the matching weight from hash table and assign to found_weight | ||
found_weight = hash_table_retrieve(ht, matching_weight) | ||
# If we found a weight... | ||
if found_weight: | ||
# Return the found weight and its partner weight_2 | ||
return (found_weight, weight_2) | ||
# Return None (means no matching weight was found) | ||
return None | ||
|
||
test_weights = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] | ||
matching_weights = get_indices_of_item_weights(test_weights, 10, 11) | ||
# Should return 9, 0 (10 + 1 = 11) | ||
print(matching_weights) | ||
|
||
def print_answer(answer): | ||
if answer is not None: | ||
print(str(answer[0] + " " + answer[1])) | ||
else: | ||
print("None") | ||
# def print_answer(answer): | ||
# if answer is not None: | ||
# print(str(answer[0] + " " + answer[1])) | ||
# else: | ||
# print("None") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,47 @@ | ||
# Hint: You may not need all of these. Remove the unused functions. | ||
from hashtables import (HashTable, | ||
hash_table_insert, | ||
hash_table_remove, | ||
hash_table_retrieve, | ||
hash_table_resize) | ||
hash_table_retrieve) | ||
|
||
|
||
class Ticket: | ||
def __init__(self, source, destination): | ||
self.source = source | ||
self.destination = destination | ||
|
||
|
||
def reconstruct_trip(tickets, length): | ||
hashtable = HashTable(length) | ||
# Initialize Hashtable/ pass in the length(capacity), and assign to itinerary | ||
itinerary = HashTable(length) | ||
# Preallocate the route (array) memory by length/capacity | ||
route = [None] * length | ||
# For each ticket we have... | ||
for t in tickets: | ||
# Insert the itinerary (ht), source (key), and desination (value) in the hash table | ||
hash_table_insert(itinerary, t.source, t.destination) | ||
# Retrieve and assign the first ticket -- has destination, but no source (key or initial connecting flight) | ||
ticket = hash_table_retrieve(itinerary, "NONE") | ||
# While the ticket *does* have a destination on its key... | ||
while ticket != "NONE": | ||
# For each index in the range of our route array's length... | ||
for i in range(len(route)): | ||
# Assign each route's destination [value] to ticket, which places it inside the array | ||
route[i] = ticket | ||
# Call retrieve again on the same ticket's key to find the ticket with a matching source | ||
ticket = hash_table_retrieve(itinerary, ticket) | ||
# If the ticket doesn't have a destination... | ||
if ticket == "NONE": | ||
# Place at the end of our route | ||
route[i + 1] # have to increment because we aren't assining a value to ticket | ||
# Break out of the loop since work is done | ||
break | ||
# Return our newly organized route | ||
return route | ||
|
||
""" | ||
YOUR CODE HERE | ||
""" | ||
tickets = [ | ||
Ticket("NONE", "ORD"), | ||
Ticket("ORD", "CID"), | ||
Ticket("CID", "NONE"), | ||
] | ||
|
||
pass | ||
# Should print ORD, CID, NONE | ||
print(reconstruct_trip(tickets, 3)) |