RecursiveList Python - python

So i'm learning about RecursiveLists and our prof has given us a init for the recursivelist class
class RecursiveList:
# === Private Attributes ===
# _first:
# The first item in the list.
# _rest:
# A list containing the items that come after
# the first one.
_first: Optional[Any]
_rest: Optional[RecursiveList]
# === Representation Invariants ===
# _first is None if and only if _rest is None.
# This represents an empty list.
def __init__(self, items: list) -> None:
"""Initialize a new list containing the given items.
The first node in the list contains the first item in <items>.
"""
if items == []:
self._first = None
self._rest = None
else:
self._first = items[0]
self._rest = RecursiveList(items[1:])
now I want to mutate the list by inserting an item to the front of the list but I can't wrap my head around how to do so. I understand that self._rest stores the rest of the list recursively and also that I should move the value of self._first into self._rest, but how do I move an int and turn it so that the recursive function has the rest of them?
def insert_first(self, item: object) -> None:
"""Insert item at the front of this list.
This should work even if this list is empty.
"""

You make a new RecursiveList (btw: This is usually called a Linked List) that you copy your current value to, make its rest point to your current rest, overwrite your own element with the element to be inserted, and set your rest to the new list.
Something like:
def insert_first(self, item: object) -> None:
"""Insert item at the front of this list.
This should work even if this list is empty.
"""
if self._first is None:
# handle case where list is "empty"
self._first = item
else:
new = RecursiveList()
new._first = self._first
new._rest = self._rest
self._first = item
self._rest = new
Before:
1:"e" -→ 2:"l" -→ 3:"l" -→ 4:"o"
After:
1:"h" 2:"l" -→ 3:"l" -→ 4:"o"
| ↑
└→5:"e" -┘
Note that this process is a what is called constant-time operation, because it doesn't matter how large the list is: this process always takes roughly the same amount of time. This (constant-time insertion at the beginning of the list) is somewhat unique to Linked Lists, and does not apply to Python's normal lists, which are based on arrays.

Related

python change the return type from set to list

I make a code below and the return value now is a list of set, if I want to change the return value to return a list of list, is there any way to do this?
class SetSuite:
def __init__(self, list_of_lists):
self.__data = []
# looping through each list in list_of_lists, adding to set using add_set()
for a_list in list_of_lists:
self.add_set(a_list)
# adds a list indicating a set of data into internal list of sets
def add_set(self, a_list):
# converting a_list to set and appending to data
self.__data.append(set(a_list))
# returns the list of sets
def get_sets(self):
return self.__data
# returns the union set of all sets
def union_all(self):
# creating an empty set
union_set = set()
# looping through each set
for a_set in self.__data:
# finding union with current set, storing back in union_set
union_set = union_set.union(a_set)
return union_set
# returns the intersection set of all sets
def intersection_all(self):
# if data list is empty, returning empty set
if len(self.__data) == 0:
return set()
# otherwise taking first set from data list
intersection_set = set(self.__data[0])
# looping through remaining sets and performing intersection on each set,
# storing the result in intersection_set itself
for a_set in self.__data[1:]:
intersection_set = intersection_set.intersection(a_set)
# returning the set
return intersection_set
just return everything as a list like this :
class SetSuite:
def __init__(self, list_of_lists):
self.__data = []
# looping through each list in list_of_lists, adding to set using add_set()
for a_list in list_of_lists:
self.add_set(a_list)
# adds a list indicating a set of data into internal list of sets
def add_set(self, a_list):
# converting a_list to set and appending to data
self.__data.append(a_list)
# returns the list of sets
def get_sets(self):
return self.__data
# returns the union set of all sets
def union_all(self):
# creating an empty set
union_set = set()
# looping through each set
for a_set in self.__data:
# finding union with current set, storing back in union_set
union_set = union_set.union(a_set)
return list(union_set)
# returns the intersection set of all sets
def intersection_all(self):
# if data list is empty, returning empty set
if len(self.__data) == 0:
return []
# otherwise taking first set from data list
intersection_set = set(self.__data[0])
# looping through remaining sets and performing intersection on each set,
# storing the result in intersection_set itself
for a_set in self.__data[1:]:
intersection_set = intersection_set.intersection(a_set)
# returning the set
return list(intersection_set)

How to find/delete duplicate items in stack

The items inside the stack should be unique. Is there a way I can delete the duplicate item inside the stack? And inform the user that his input is already inside the stack?
Here is my code:
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.val = key
def printPreorder(root):
if root:
print(root.val),
printPreorder(root.left)
printPreorder(root.right)
class stack:
def __init__(self):
self.items = []
def push(self, item):
return self.items.append(item)
def pop(self):
return self.items.pop()
print ("Create 3 words using the letters:")
root = Node('n')
root.right = Node('o')
root.left = Node ('w')
printPreorder(root)
print("-----------------------------------")
s1 = stack()
while (s1.size() <3):
FirstList = (input("Enter the word you created: ")).lower()
if FirstList == 'won' or FirstList == 'own' or FirstList == 'now':
s1.push(FirstList)
print(s1.items)
else:
print('Try another word!')
Ideally no you cannot traverse through a stack to find duplicate elements.
But since you are using a list for your stack implementation, you can traverse through it and find duplicate elements but this is not a good idea.
Instead, you can use another data structure, for example, a set can be used to keep track of all the unique elements you have seen so far. Every time .push() is called, you can check if the element is already present in the set. If it is not present, then you can add it to both the stack and set. If present, you can inform the user that it is already present in stack.
And remember to remove the element from the set when you pop from the stack.
You can use set to store unique values. A simple way to check if the stack has unique elements is to compare the size of the set of stack elements and the list of stack elements (since your implementation of a stack is a list).
def isDuplicate(self):
return len(set(self.items())) != len(self.items())
To check if there's a duplicate element in the stack (implemented as a list), you can write an implementation that inserts your elements into a set, and at every step checks whether the element already exists inside the list.
def removeDuplicate(self):
temp_set = set()
for item in self.items():
if item in temp_set:
return item
return None
And then you can remove that duplicate element from the stack using self.items().pop(self.removeDuplicate())

How does the referencing work in python and how to create a sperate copy of linkedlist to compare with original linkedlist

class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
regularListHead = ListNode(-1)
regularListHead.next = head
reverseListHead = head
reverseListPrev = None
reverseListCurrent = reverseListHead
while reverseListCurrent != None:
reverseListNext = reverseListCurrent.next
reverseListCurrent.next = reverseListPrev
reverseListPrev = reverseListCurrent
reverseListCurrent = reverseListNext
reverseListHead = reverseListPrev
a = regularListHead
In my code, I am trying to convert the original list to reversed list and compare both for checking palindrome but when I do the operations to reverse the reverselist then original list is also updated. I am new to python can anyone let me know why this is happening and what could be done to achieve what I want
You only create one new node. All the other nodes are the nodes of your original list, and you update their next properties so the list is reversed.
So if you want to have both the original and the reversed list, you'll have to have two lists, each having their own nodes:
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
if head is None:
return
# Create reversed list
revHead = ListNode(head.val)
current = head.next
while current is not None:
revHead = ListNode(current.val, revHead)
current = current.next
# Compare original with the reversed one
while head is not None:
if head.val != revHead.val:
return False
head = head.next
revHead = revHead.next
return True
This is however not optimal: the comparison loop should only need to perform 𝑛/2 comparisons, not 𝑛.
You may even ask yourself why you would create a linked list for the reversed version: as it is only needed for the palindrome check, you might as well create a standard list, and then do the palindrome check with just that list, which is a piece of cake.
But more importantly, creating a new list (whether a linked list or normal "array" list) requires O(n) extra space. If you are interested in an algorithm for doing this without creating new nodes, then try to implement this:
Count the number of nodes in the list
Use that to identify the first node of the second half of the list. If the number of nodes is odd, let this be the node after the center node.
Apply an in-place list reversal algorithm on that second half. Now you have two shorter lists.
Compare the values in those two lists to see whether they are equal (ignore the center node if there was one). Remember the outcome (false or true)
Optionally repeat step 3 so the reversal is rolled back, and the list is back in its original state. (This is "nice" towards the caller of your function)
Return the result that was found in step 4.

stack function python error

I created the following stack class for a project and am having trouble getting it to function properly. I can't tell if i made the error or it is an error in the main function i was given by my TA, anyways here is my code:
class Stack:
#takes in the object as input argument
#will not return anything
def __init__(self):
#initialise an instance variable to an empty list.
self.items=[]
#takes in the object as input argument
#return value Type: True or False
def isEmpty(self):
#check if the list is empty or not. If empty, return True else return False
if self.items == []:
return True
else:
return False
#takes in the object as the first argument
#takes the element to be inserted into the list as the second argument
#should not return anything
def push(self, x):
#add the element to be inserted at the end of the list
self.items.append(x)
#takes in the object as the input argument
#if the list is not empty then returns the last element deleted from the list. If the list is empty, don't return anything
def pop(self):
#check if the list is Empty
#if Empty: print the list is empty
#if the list is not empty, then remove the last element from the list and return it
if self.isEmpty()==True:
print("the list is empty")
else:
return self.items.pop()
#takes in the object as the input argument
#should not return anything
def printContents(self):
#if the list is not empty, then print each element of the list
print("The content of the list is", self.items)
Based on the comments can anyone give me any advice on how I might make this work more appropriately? Sorry I am not a computer scientist and i am trying my hardest to understand classes and functions for my python class.
from stack import *
def main():
s = Stack()
s.push(1)
s.pop()
s.pop()
s.push(2)
s.push(3)
s.push(4)
s.printContents()
main()
You should take a good look in spaces and alignment. For example printContents is not properly aligned. Note the proper alignment is very, very important in python.
Also you are not printing in printContents. This should work:
class Stack:
#takes in the object as input argument
#will not return anything
def __init__(self):
#initialise an instance variable to an empty list.
self.items=[]
#takes in the object as input argument
#return value Type: True or False
def isEmpty(self):
#check if the list is empty or not. If empty, return True else return False
if self.items == []:
return True
else:
return False
#takes in the object as the first argument
#takes the element to be inserted into the list as the second argument
#should not return anything
def push(self, x):
#add the element to be inserted at the end of the list
self.items.append(x)
#takes in the object as the input argument
#if the list is not empty then returns the last element deleted from the list. If the list is empty, don't return anything
def pop(self):
#check if the list is Empty
#if Empty: print the list is empty
#if the list is not empty, then remove the last element from the list and return it
if self.isEmpty():
print("the list is empty")
else:
return self.items.pop()
#takes in the object as the input argument
#should not return anything
def printContents(self):
#if the list is not empty, then print each element of the list
print("the contents of the list are", self.items)
def main():
s = Stack()
s.push(1)
s.pop()
s.pop()
s.push(2)
s.push(3)
s.push(4)
s.printContents()
main()
You can see it working online here:
https://repl.it/BZW4
Everybody has to start sometime so no worries, and I hope you are not offended by my extended critique, as I am just trying to be helpful.
You probably want the top declaration to be:
class Stack(object):
Leaving off the (object): part is a deprecated form that makes certain features of the class different in ways you probably don't want.
Secondly, declaring an isEmpty method is not really a normal "pythonic" approach. The strong expected python convention is to simply check the truth value of your object, with empty being False. Typical python users of your class will not expect an isEmpty method. You can control the behavior of your object's truth value by defining the special nonzero which you could write like this:
def __nonzero__(self):
return bool(self.items)
This way somebody could use your class like:
stack = Stack()
stack.append("apple")
stack.append("pear")
if stack:
print "stack has stuff in it"
else:
print "stack is empty"
Moreover, there are other things you should overload to make a good stack class. For example you ought support len(stack) and you ought to be able to iterate over your stack. You can define special len and iter methods to do this. Notice if you define the len then you don't need to define the iszero (python will consider your stack False if len returns 0 and you have not defined iszero).
Your printContents method will not print or write anything without a print or write statement, but will return the last element in the stack and throw an index error if the stack is empty. To iterate over each item and print it you could write it like this (from the top item of stack to the first one):
def printContents(self):
for item in reversed(self.items):
print item
However it would be more pythonic to define an iteration method and the use that, so your user can iterate over your stack and print it themselves:
def __iter__(self):
for item in self.items:
yield item
# later in code .....
stack = Stack()
stack.append("apple")
stack.append("pear")
for item in stack:
print item
Hopefully these tips may prove useful. Keep at it, and you will get it before long.
Modify your pop definition in class to this
def pop(self):
#check if items is empty
if len(self.items)==0:
#if empty
return "Nothing to pop"
else:
#if not empty
return str(self.items.pop())+" Popped"

List class retaining old values for new list Python

I have created a list class with a few simple methods.
class ListQ(object):
"""List object creation"""
def __init__(self, earlier_list=[]):
self.list=earlier_list
def isEmpty(self):
"""checks if list is empty"""
if len(self.list)==0:
return(True)
else:
return(False)
def put(self, new_item):
"""puts new_item last in list"""
self.list.append(new_item)
def get(self):
"""returns the next item in line"""
self.first_item = self.list.pop(0)
return self.first_item
I also have a function to help create these lists. (Helping to solve a magic card trick btw)
def create_card_list(card_list=None):
"""creates listQ of cards from user input"""
if card_list!=None: #if user already has list of cards
for item in card_list:
item=replace_card_strings(item) #replaces any strings in list
if item == False:
print('One of your cards does not exist, list creation failed')
return(False)
cards=ListQ(card_list)
The replace_card_strings() function has been properly tested and I do not believe it's at fault but here it is anyway.
def replace_card_strings(word):
"""replaces strings of words with their numbers and returns edited list"""
if type(word)!=int:
if word.lower()=='one':
word=1
elif word.lower()=='two':
word=2
elif word.lower()=='three':
word=3
elif word.lower()=='four':
word=4
elif word.lower()=='five':
word=5
elif word.lower()=='six':
word=6
elif word.lower()=='seven':
word=7
elif word.lower()=='eight':
word=8
elif word.lower()=='nine':
word=9
elif word.lower()=='ten':
word=10
elif word.lower()=='jack':
word=11
elif word.lower()=='queen':
word=12
elif word.lower()=='king':
word=13
elif word.lower()=='ace':
word=1
else:
word=False #if card doesnt exist
return(word)
When I run the following test is when the problem start.
cards=create_card_list(['one', 2, 3])
one=cards.get()
two=cards.get()
three=cards.get()
print(one, two, three)
if one==1 and two==2 and three==3:
print("create_card_list gives the correct answer")
else:
print("create_card_list gives the wrong answer")
It prints that the function has given the wrong answer and
the print(one, two, three) prints one 2 3 which is the original list.
Anybody have an idea where I've messed up?
You're not replacing items in the list, only in the loop's context:
Replace the entire loop:
for item in card_list:
item=replace_card_strings(item) #replaces any strings in list
....
Which does not do anything to the list (it does not "replace" the item).
With python's map which is used in order to apply a function to an iterable and create a list of results:
card_list = map(replace_card_strings, card_list)
If you don't want to use map you can use list comprehension:
card_list = [replace_card_strings(card_str) for card_str in card_list]
Now you'll have:
def create_card_list(card_list=None):
"""creates listQ of cards from user input"""
if card_list != None:
card_list = map(replace_card_strings, card_list)
cards=ListQ(card_list)
Tip:
You can replace the lengthy function replace_card_strings:
def replace_card_strings(word):
"""replaces strings of words with their numbers and returns edited list"""
word = word.lower()
string_to_int = {"one":1, "two":2 ...}
return word in string_to_int and string_to_int[word]
This works since and returns the last Truth-y result or the first False-y result.
You can also use dict.get:
# return word in string_to_int and string_to_int[word]
# try and read value from dict, return False otherwise
return string_to_int.get(word, False)
Which is cleaner (thanks #padraic).
Tip 2: You don't want two places referencing, and possibly mutating, the same list. It seems like you're keeping a reference to the same list that's used to construct a card list outside the generated object. This is prone to errors. What you should do is instead copy the list when it's passed:
def __init__(self, earlier_list=[]):
self.list=earlier_list[:]
Tip 3: python has a known "gotcha" with mutable default argument, which is exactly what you use here (earlier_list=[]). This is prone to errors as well since python binds default arguments once. You should instead have:
def __init__(self, earlier_list=None):
# copy passed list or create a new one if none passed.
self.list=earlier_list[:] if earlier_list else []

Categories

Resources