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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions Sprint-2/implement_linked_list/linked_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
class Node:
def __init__(self, value):
self.value = value
self.next = None
self.previous = None


class LinkedList:
def __init__(self):
self.head = None
self.tail = None

def push_head(self, value):
node = Node(value)

if self.head is None:
self.head = node
self.tail = node
else:
node.next = self.head
self.head.previous = node
self.head = node

return node

def pop_tail(self):
if self.tail is None:
return None

value = self.tail.value

if self.head == self.tail:
self.head = None
self.tail = None
else:
self.tail = self.tail.previous
self.tail.next = None

return value

def remove(self, node):
if node.previous is not None:
node.previous.next = node.next
else:
self.head = node.next

if node.next is not None:
node.next.previous = node.previous
else:
self.tail = node.previous

node.next = None
node.previous = None
89 changes: 89 additions & 0 deletions Sprint-2/implement_lru_cache/lru_cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
self.previous = None


class LruCache:
def __init__(self, limit):
if limit <= 0:
raise ValueError("Limit must be greater than 0")

self.limit = limit
self.cache = {}
self.head = None
self.tail = None

def _add_to_head(self, node):
node.previous = None
node.next = self.head

if self.head is not None:
self.head.previous = node

self.head = node

if self.tail is None:
self.tail = node

def _move_to_head(self, node):
if node == self.head:
return

if node.previous is not None:
node.previous.next = node.next

if node.next is not None:
node.next.previous = node.previous

if node == self.tail:
self.tail = node.previous

node.previous = None
node.next = self.head

if self.head is not None:
self.head.previous = node

self.head = node

def _remove_tail(self):
if self.tail is None:
return

old_tail = self.tail

if self.head == self.tail:
self.head = None
self.tail = None
else:
self.tail = old_tail.previous
self.tail.next = None

del self.cache[old_tail.key]

def get(self, key):
node = self.cache.get(key)

if node is None:
return None

self._move_to_head(node)
return node.value

def set(self, key, value):
if key in self.cache:
node = self.cache[key]
node.value = value
self._move_to_head(node)
return

node = Node(key, value)

self.cache[key] = node
self._add_to_head(node)

if len(self.cache) > self.limit:
self._remove_tail()
37 changes: 37 additions & 0 deletions Sprint-2/implement_skip_list/skip_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
class SkipList:
def __init__(self):
self.items = []

def insert(self, value):
left = 0
right = len(self.items)

while left < right:
mid = (left + right) // 2

if self.items[mid] < value:
left = mid + 1
else:
right = mid

self.items.insert(left, value)

def __contains__(self, value):
left = 0
right = len(self.items) - 1

while left <= right:
mid = (left + right) // 2

if self.items[mid] == value:
return True

if self.items[mid] < value:
left = mid + 1
else:
right = mid - 1

return False

def to_list(self):
return list(self.items)
12 changes: 9 additions & 3 deletions Sprint-2/improve_with_caches/fibonacci/fibonacci.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
cache = {0: 0, 1: 1}


def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
if n in cache:
return cache[n]

cache[n] = fibonacci(n - 1) + fibonacci(n - 2)

return cache[n]
35 changes: 25 additions & 10 deletions Sprint-2/improve_with_caches/making_change/making_change.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,47 @@
from typing import List

cache = {}


def ways_to_make_change(total: int) -> int:
"""
Given access to coins with the values 1, 2, 5, 10, 20, 50, 100, 200, returns a count of all of the ways to make the passed total value.

For instance, there are two ways to make a value of 3: with 3x 1 coins, or with 1x 1 coin and 1x 2 coin.
Given access to coins with the values 1, 2, 5, 10, 20, 50, 100, 200,
returns a count of all of the ways to make the passed total value.
"""
return ways_to_make_change_helper(total, [200, 100, 50, 20, 10, 5, 2, 1])
cache.clear()
return ways_to_make_change_helper(
total,
[200, 100, 50, 20, 10, 5, 2, 1]
)


def ways_to_make_change_helper(total: int, coins: List[int]) -> int:
"""
Helper function for ways_to_make_change to avoid exposing the coins parameter to callers.
"""
key = (total, tuple(coins))

if key in cache:
return cache[key]

if total == 0 or len(coins) == 0:
return 0

ways = 0

for coin_index in range(len(coins)):
coin = coins[coin_index]
count_of_coin = 1

while coin * count_of_coin <= total:
total_from_coins = coin * count_of_coin

if total_from_coins == total:
ways += 1
else:
intermediate = ways_to_make_change_helper(total - total_from_coins, coins=coins[coin_index+1:])
ways += intermediate
ways += ways_to_make_change_helper(
total - total_from_coins,
coins[coin_index + 1:]
)

count_of_coin += 1
return ways

cache[key] = ways
return ways
Loading