<jupyter_start><jupyter_text>Question 1:<jupyter_code>Create a class Sudoku that takes a string as an argument. The string will contain the numbers
of a regular 9x9 sudoku board left to right and top to
bottom, with zeros filling up the empty cells.
Attributes
An instance of the class Sudoku will have one attribute:
 - board: a list representing the board, with sublits for each row, with the
numbers as integers. Empty cell represented with 0.
Methods
An instance of the class Sudoku wil have three methods:
 - get_row(n): will return the row in position n.
 - get_col(n): will return the column in position n.
 - get_sqr([n, m]): will return the square in position n if only one argument is given, 
and the square to which the cell in position (n, m) belongs to if two
arguments are given.

Example

game =
Sudoku("417950030000000700060007000050009106800600000000003400900005000000430000200701580")
game.board [
 [4, 1, 7, 9, 5, 0, 0, 3, 0],
 [0, 0, 0, 0, 0, 0, 7, 0, 0],
 [0, 6, 0, 0, 0, 7, 0, 0, 0],
 [0, 5, 0, 0, 0, 9, 1, 0, 6],
 [8, 0, 0, 6, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 3, 4, 0, 0],
 [9, 0, 0, 0, 0, 5, 0, 0, 0],
 [0, 0, 0, 4, 3, 0, 0, 0, 0],
 [2, 0, 0, 7, 0, 1, 5, 8, 0]
]
game.get_row(0) [4, 1, 7, 9, 5, 0, 0, 3, 0]
game.get_col(8) [0, 0, 0, 6, 0, 0, 0, 0, 0]
game.get_sqr(1) [9, 5, 0, 0, 0, 0, 0, 0, 7]
game.get_sqr(1, 8) [0, 3, 0, 7, 0, 0, 0, 0, 0]
game.get_sqr(8, 3) [0, 0, 5, 4, 3, 0, 7, 0, 1]<jupyter_output><empty_output><jupyter_text>Answer :<jupyter_code>class Sudoku:
    
    def __init__(self,board):
        if type(board) == str:
            self.board = [[int(i) for i in board[j:j+9]] for j in range(0,81,9)]
        elif type(board) == list:
            self.board = board
        
    def get_row(self,nrow):
        return self.board[nrow]
    
    def get_col(self,ncol):
        tboard = list(map(list,zip(*self.board)))
        return tboard[ncol]
    
    def get_sqr(self,nrow,ncol=None):
        
        self.dic = {0:((0,3),(0,3)),1:((0,3),(3,6)),2:((0,3),(6,9)),
               3:((3,6),(0,3)),4:((3,6),(3,6)),5:((3,6),(6,9)),
               6:((6,9),(0,3)),7:((6,9),(3,6)),8:((6,9),(6,9))}
        
        if ncol == None:
            return self._sqr(nrow)
        for i in range(9):
            row,col = self.dic[i]
            if (row[0]<=nrow and nrow<row[1]) and (col[0]<=ncol and ncol<col[1]):
                return self._sqr(i)
        
    def _sqr(self,nrow):
        row,col = self.dic[nrow]
        sq = []
        for i in range(*row):
            for j in range(*col):
                sq.append(self.board[i][j])
        return sq
game = Sudoku("417950030000000700060007000050009106800600000000003400900005000000430000200701580")
game.board
print(game.get_row(0))
print(game.get_col(8))
print(game.get_sqr(1))
print(game.get_sqr(1, 8))
print(game.get_sqr(8, 3))<jupyter_output>[4, 1, 7, 9, 5, 0, 0, 3, 0]
[0, 0, 0, 6, 0, 0, 0, 0, 0]
[9, 5, 0, 0, 0, 0, 0, 0, 7]
[0, 3, 0, 7, 0, 0, 0, 0, 0]
[0, 0, 5, 4, 3, 0, 7, 0, 1]<jupyter_text>Question 2:<jupyter_code>The function input is two non-empty linked lists representing two nonnegative integers. 
The digits are stored in reverse order, and each of their
nodes contains a single digit. Add the two numbers and return the sum as a linked list,
in which the digits are also stored in reversed order. The class
ListNode, building block of the linked list, is defined in the Tests tab.

Class definition
class ListNode:
 def __init__(self, val=0, next=None):
 self.val = val
 self.next = next
Examples
lt1 = ListNode(2)
lt1.add_data([4, 3])
lt2 = ListNode(5)
lt2.add_data([6, 4])
# print(lt1.get_data()) # [2, 4, 3]
# print(lt2.get_data()) # [5, 6, 4]
# print(342 + 465) # 807
add_two_numbers(lt1, lt2).get_data() [7, 0, 8]
lt1 = ListNode(0)
lt2 = ListNode(0)
# print(lt1.get_data()) # [0]
# print(lt2.get_data()) # [0]
# print(0 + 0) # 0
add_two_numbers(lt1, lt2).get_data() [0]
lt1 = ListNode(9)
lt1.add_data([9,9,9,9,9,9])
lt2 = ListNode(9)
lt2.add_data([9,9,9])
# print(lt1.get_data()) # [9, 9, 9, 9, 9, 9, 9]
# print(lt2.get_data()) # [9, 9, 9, 9]
# print(9999999 + 9999) # 10009998
add_two_numbers(lt1, lt2).get_data() [8, 9, 9, 9, 0, 0, 0, 1]<jupyter_output><empty_output><jupyter_text>Answer :<jupyter_code>class ListNode:
    def __init__(self,val=0,next=None):
        self.val = val
        self.next = None
    
    def add_data(self,l1):
        self.l1 = l1
        
class add_two_numbers:
    def __init__(self, obj1, obj2):
        self.obj1 = obj1
        self.obj2 = obj2
        
    def get_data(self):
        
        if self.obj1.val==0 or self.obj2.val == 0:
            return [0]
        self.obj1.l1.insert(0,self.obj1.val)
        self.obj2.l1.insert(0,self.obj2.val)
        n1 = int("".join([str(i) for i in self.obj1.l1[::-1]]))
        n2 = int("".join([str(i) for i in self.obj2.l1[::-1]]))
        return [int(i) for i in str(n1+n2)[::-1]]
lt1 = ListNode(2)
lt1.add_data([4, 3])
lt2 = ListNode(5)
lt2.add_data([6, 4])
add_two_numbers(lt1, lt2).get_data()
lt1 = ListNode(9)
lt1.add_data([9,9,9,9,9,9])
lt2 = ListNode(9)
lt2.add_data([9,9,9])
# print(lt1.get_data()) # [9, 9, 9, 9, 9, 9, 9]
# print(lt2.get_data()) # [9, 9, 9, 9]
# print(9999999 + 9999) # 10009998
add_two_numbers(lt1, lt2).get_data()
lt1 = ListNode(0)
lt2 = ListNode(0)
# print(lt1.get_data()) # [0]
# print(lt2.get_data()) # [0]
# print(0 + 0) # 0
add_two_numbers(lt1, lt2).get_data() [0]<jupyter_output><empty_output><jupyter_text>Question 3:<jupyter_code>Write a class called CoffeeShop, which has three instance variables:
 1. name : a string (basically, of the shop)
 2. menu : a list of items (of dict type), with each item containing the item
    (name of the item), type (whether a food or a drink) and price.
 3. orders : an empty list
    
and seven methods:
 1. add_order: adds the name of the item to the end of the orders list if it
     exists on the menu, otherwise, return "This item is currently unavailable!" 2. fulfill_order: if the orders list is not empty, return "The {item} is ready!". If the orders list is empty, return "All orders have been fulfilled!"
 3. list_orders: returns the item names of the orders taken, otherwise, an
    empty list.
 4. due_amount: returns the total amount due for the orders taken.
 5. cheapest_item: returns the name of the cheapest item on the menu.
 6. drinks_only: returns only the item names of type drink from the menu.
 7. food_only: returns only the item names of type food from the menu.
    
IMPORTANT: Orders are fulfilled in a FIFO (first-in, first-out) order. Examples
tcs.add_order("hot cocoa") "This item is currently unavailable!"
# Tesha's coffee shop does not sell hot cocoa
tcs.add_order("iced tea") "This item is currently unavailable!"
# specifying the variant of "iced tea" will help the process
tcs.add_order("cinnamon roll") "Order added!"
tcs.add_order("iced coffee") "Order added!"
tcs.list_orders ["cinnamon roll", "iced coffee"]
# all items of the current order
tcs.due_amount() 2.17
tcs.fulfill_order() "The cinnamon roll is ready!"
tcs.fulfill_order() "The iced coffee is ready!"
tcs.fulfill_order() "All orders have been fulfilled!"
# all orders have been presumably served
tcs.list_orders() []
# an empty list is returned if all orders have been exhausted
tcs.due_amount() 0.0
# no new orders taken, expect a zero payable
tcs.cheapest_item() "lemonade"
tcs.drinks_only() ["orange juice", "lemonade", "cranberry juice", "pineapple juice", "lemon iced tea", "vanilla chai latte", "hot chocolate", "iced coffee"]
tcs.food_only() ["tuna sandwich", "ham and cheese sandwich", "bacon and egg", "steak", "hamburger", "cinnamon roll"]<jupyter_output><empty_output><jupyter_text>Answer :<jupyter_code>menu = {"drinks_only":{  "orange juice":"price 1", 
                         "lemonade":"price 2", 
                         "cranberry juice":"price 3", 
                         "pineapple juice":"price 4",
                         "lemon iced tea":"price 3", 
                         "vanilla chai latte":"price 4", 
                         "hot chocolate":"price 2", 
                         "iced coffee":"price 3"},
        
        "food_only":{    "tuna sandwich":"price 2", 
                         "ham and cheese sandwich":"price 4",
                         "bacon and egg":"price 3", 
                         "steak":"price 2", 
                         "hamburger":"price `3",
                         "cinnamon roll":"price 2"}}
import re
import copy

class CoffeeShop:
    def __init__(self, name, menu={}, orders=[]):
        self.name = name
        self.menu = menu
        self.orders = orders
        self.iter = iter(orders)
        
    def add_order(self,item):
        
        menu = {**self.menu["drinks_only"],**self.menu["food_only"]}
        if item in menu.keys():
            self.orders.append(item)
            return "Order added!"
        else:
            return "This item is currently unavailable!"
    
    def fulfill_order(self):
        
        item = next(copy.copy(self.iter), 'end')
        if item == 'end':
            return "All orders have been fulfilled!"
        else:
            self.orders.remove(item)
            return f"The {item} is ready!"
        
    def list_orders(self):
        return self.orders
    
    def due_amount(self):
        tot_price = 0
        menu = {**self.menu["drinks_only"],**self.menu["food_only"]}
        for item in self.orders:
            tot_price += int(re.findall("\d+", menu[item])[0])
        return tot_price
            
        pass
    
    def cheapest_item(self):
        menu = {**self.menu["drinks_only"],**self.menu["food_only"]}
        prices = sorted(menu.items(),key=lambda x:x[1])
        return prices[0][0]
    
    def drinks_only(self):
        return list(self.menu["drinks_only"].keys())
    
    def food_only(self):
        return list(self.menu["food_only"].keys())
tcs = CoffeeShop(name= "abcd",menu=menu)
print(tcs.add_order("hot cocoa"))
print(tcs.add_order("cinnamon roll"))
print(tcs.add_order("iced coffee"))
print(tcs.list_orders())
print(tcs.due_amount())
print(tcs.fulfill_order())
print(tcs.fulfill_order())
print(tcs.fulfill_order())
print(tcs.list_orders())
print(tcs.due_amount())
print(tcs.cheapest_item())
print(tcs.drinks_only())
print(tcs.food_only())<jupyter_output>This item is currently unavailable!
Order added!
Order added!
['cinnamon roll', 'iced coffee']
5
The cinnamon roll is ready!
The iced coffee is ready!
All orders have been fulfilled!
[]
0
orange juice
['orange juice', 'lemonade', 'cranberry juice', 'pineapple juice', 'lemon iced tea', 'vanilla chai latte', 'hot chocolate', 'iced coffee']
['tuna sandwich', 'ham and cheese sandwich', 'bacon and egg', 'steak', 'hamburger', 'cinnamon roll']<jupyter_text>Question 4:<jupyter_code>In this challenge, write a funcion loneliest_number to find the last Lonely number inside a sequence. A number is Lonely if the distance from its closest Prime sets a new record of the sequence.
Sequence = from 0 to 3
# Any number lower than 3 doesn't have a Prime preceeding it...
# ...so that you'll consider only its next closest Prime.
0 has distance 2 from its closest Prime (2)
# It's a new record! 0 It's the first lonely number of the sequence1 has distance 1 from its closest Prime (2)
2 has distance 1 from 3
3 has distance 1 from 2
# The sequence 0 to 3 has only one Lonely number: 0
Sequence = Numbers from 5 to 10
5 has distance 2 from its closest Prime (3 or 7)
# It's a new record! 5 It's the first lonely number of the sequence6 has distance 1 from 5 or 7
7 has distance 2 from 5
8 has distance 1 from 7
9 has distance 2 from 7 or 11
10 has distance 1 from 11
# The sequence 5 to 10 has only one Lonely number: 5
Sequence = Numbers from 19 to 24
19 has distance 2 from its closest Prime (17)
# It's a new record! 19 It's the first lonely number of the sequence20 has distance 1 from 19
21 has distance 2 from 5
22 has distance 1 from 23
23 has distance 4 from 17 or 29
# It's a new record! 23 is the second lonely number of the sequence24 has distance 1 from 23
# The sequence 19 to 24 has two Lonely numbers: 19 and 23
The function loneliest_number must accept two integers lo and hi being the inclusive bounds of the sequence to analyze, and returns a dictionay (dict)
object with the following keys and values:
 - number: is the last Lonely number found in the given sequence;
 - distance: is the distance of the number from its closest Prime;
 - closest: is the Prime closest to number (if two Primes are equally distant from number, return the higher Prime).
Examples
loneliest_number(0, 22) {
 number: 0, distance: 2, closest: 2
}
loneliest_number(8, 123) {
 number: 53, distance: 6, closest: 59
}
loneliest_number(938, 1190) {
 number: 1140, distance: 11, closest: 1151
}
loneliest_number(120, 1190) {
 number: 211, distance: 12, closest: 223
}<jupyter_output><empty_output><jupyter_text>Answer :<jupyter_code>def isPrime(n):
    if n <= 1:
        return False
 
    for i in range(2, int(n**(1/2))+1):
        if n % i == 0:
            return False
    return True

def closestPrime(n):
    cn1 = n-1
    cn2 = n+1
    while True:
        if isPrime(cn2):
            return cn2
        if isPrime(cn1):
            return cn1
        cn1 -= 1
        cn2 += 1
        
def loneliest_number(n1,n2):
    dict_ = {"number": 0, "distance": 0, "closest": 0}
    for i in range(n1,n2+1):
        closest = closestPrime(i)
        if abs(i-closest)>dict_["distance"]:
            dict_["number"] = i
            dict_["distance"] = abs(i-closest)
            dict_["closest"] = closest
    return dict_
print(loneliest_number(0, 3))
print(loneliest_number(0, 22))
print(loneliest_number(19, 24))
print(loneliest_number(8, 123))
print(loneliest_number(938, 1190))
print(loneliest_number(120, 1190))<jupyter_output>{'number': 0, 'distance': 2, 'closest': 2}
{'number': 0, 'distance': 2, 'closest': 2}
{'number': 23, 'distance': 4, 'closest': 19}
{'number': 120, 'distance': 7, 'closest': 127}
{'number': 1140, 'distance': 11, 'closest': 1151}
{'number': 211, 'distance': 12, 'closest': 223}<jupyter_text>Question 5:<jupyter_code>Implement a class Selfie that can store the current state of the object in the
form of binary string. It can take multiple pictures and then recover to a state
it was before. During testing an object will be provided with new attributes and
their values. It will store its state. Then the values will be changed. Then it will
be given new attributes. It will store its state again. It will be repeated few
times.
Later the states of the object will be recovered given an index. The return
value should be a new Selfie with the requested historic state and the state
history of the new object should be updated with a copy of current object's
state history.
The object also knows how many states it has stored. If the index is not within
the range of stored states, the object stays as is. If the argument is invalid, n
< 0 or n >= self.n_states(), the current object (or a copy thereof) should be
returned.
Examples
p = Selfie()
p.x = 2
p.save_state()
p.x = 5
p = p.recover_state(0)
p.x 2<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13101215644820297, 'fraction_numerical': 0.05932875264270613, 'mean_word_length': 3.235310576385003, 'pattern_counts': {'":': 19, '<': 40, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '576830', 'license': 'MIT', 'n_tokens_mistral': 5892, 'n_tokens_neox': 5182, 'n_words': 1846, 'path': 'Python Advance Programming Assignment/Assignment_23.ipynb', 'repo_name': 'kpsanjeet/Python-Programming-Basic-Assignment', 'size': '15136'}