class Song:
def __init__(self, name):
self.name = name
self.next = None
def next_song(self, song):
self.next = song
def is_repeating_playlist(self):
"""
:returns: (bool) True if the playlist is repeating, False if not.
"""
return None
first = Song("Hello")
second = Song("Eye of the tiger")
first.next_song(second);
second.next_song(first);
class Song:
def __init__(self, name):
self.name = name
self.next = None
def next_song(self, song):
self.next = song
def is_repeating_playlist(self):
"""
:returns: (bool) True if the playlist is repeating, False if not.
"""
songs = set()
next_song = self
while next_song:
if next_song.name in songs:
return True
else:
songs.add(next_song.name)
next_song = next_song.next or None
return False
first = Song("Anam Nesis - Contemplare")
second = Song("Petre Inspirescu - Anima")
third = Song("VOLK - Cântul Ielelor")
first.next_song(second);
second.next_song(third);
print(first.is_repeating_playlist())
Please make sure you use set() for increased speed.
The function "is_repeating_playlist" works in two steps:
Iterates thru the (next) songs
If it finds the next song in the already added songs list, then the list is repeating
This is a linked list which is a very thoroughly examined data structure in computer science. You want to detect if your linked list has a loop.
Here is an answer adapted from https://www.geeksforgeeks.org/detect-loop-in-a-linked-list/
Because I heavily used that site (and because I wrote the function), you shouldn't hand this in as yours if it is homework. Instead, find more info on linked list and create your own solution.
class Song:
def __init__(self, name):
self.name = name
self.next = None
def next_song(self, song):
self.next = song
Because I didn't use self, I made this a staticmethod.
#staticmethod
def is_repeating_playlist(first_song):
"""
:returns: (bool) True if the playlist is repeating, False if not.
"""
songs_in_playlist = set()
current_song = first_song
while(current_song):
if current_song.name in songs_in_playlist: # if we already saw this song
return True
songs_in_playlist.add(current_song.name)
current_song = current_song.next
return False # no repeats found
Now let's try it out:
first = Song("Hello")
second = Song("Eye of the tiger")
first.next_song(second);
second.next_song(first);
print(Song.is_repeating_playlist(first))
True
And let's check one that doesn't repeat
first = Song("Hello")
second = Song("Eye of the tiger")
third = Song("We Will Rock You")
first.next_song(second);
second.next_song(third);
print(Song.is_repeating_playlist(first))
False
I'm just a newbie.. but check this out. It seems like to work well though.
def is_repeating_playlist(self):
n = self
x = set()
while n is not None:
x.add(n)
n = n.next
if n in x:
return True
return False
I think my solution is a little more performant than the answers already posted. I don't use the "in" keyword in my solution to avoid traversing my song set every iteration, all I use is the length of the set. Using len() actually doesn't require traversing the entire list, it actually runs at O(1) constant time! Here is my reference: Cost of len() function
def is_repeating_playlist(self):
song_set = {self}
songs_traversed = 1
current_song = self
while True:
next = current_song.next
if next == None:
return False
if len(song_set) != songs_traversed:
return True
song_set.add(next)
current_song = next
songs_traversed += 1
I made it using the recursive function. Although I have to break the functions out when the condition is met as many as I call recursive functions.
class Song:
def __init__(self, name):
self.name = name
self.next = None
def next_song(self, song):
self.next = song
def is_repeating_playlist(self):
first = self.name
def recursion(self,first):
if self.next == None:
return False
while not first == self.next.next.name:
recursion(self.next, first)
break
print('break out')
return True
return recursion(self,first)
first = Song("Hello")
second = Song("Eye of the tiger")
third = Song("mamma mia!")
fourth = Song("lion king")
first.next_song(second)
second.next_song(third)
third.next_song(fourth)
fourth.next_song(first)
print(first.is_repeating_playlist())
simple and straightforward
def is_repeating_playlist(self):
songs = set()
while self.next:
if self.next.name in songs:
return True
else:
songs.add(self.next.name)
self.next = self.next.next or None
return False
You should be using a queue where last element links to the first element. To implement this update your class with self.previous
then your queue would look like (added third for clarity):
first = Song("Hello")
second = Song("Eye of the tiger")
third = Song("We are the champions")
first.next_song(second)
first.prev_song(third)
second.next_song(third)
second.prev_song(first)
third.next_song(first)
third.prev_song(second)
I have looked at many very similar questions and cannot figure it out so:
I have a string like this:
{121{12}12{211}2}
I want to read the string into a tree like this:
I am confused as how to tell python to add a whole list as a child node?
I would also like to know how to change the current node to the parent of the old current node?
Here is my code so far:
class Node:
def __init__(self,val):
self.value = val
self.children = []
#init Node class so we can pass in values as nodes and set children to empty list
def add_child(self, obj):
self.children.append(obj)
s=[]
for i in filedata:
if i == leftbrace:
n = Node(i)
#create new child of current node
s = []
#reset list s to blank
if i == rightbrace:
n.add_child(s)
#add list s to current node
#make parent of current node the new current node
else:
s.append(i)
#add i to list s
for c in n.children:
print (c.data)
To make something like this work, it is easiest if you use recursion. Here is one way that this can be done.
Code:
class Node:
def __init__(self, stream):
val = []
children = []
while True:
try:
# get the next character from the stream
ch = next(stream)
# if this is an open brace, then recurse to a child
if ch == '{':
children.append(Node(stream))
# if this is a close brace, we are done on this level
elif ch == '}':
break
# otherwise add this character to our value
else:
val.append(ch)
# stream is empty, we are done
except StopIteration:
break
self.value = ''.join(val)
self.children = children
#classmethod
def from_string(cls, string):
stream = iter(string)
tree_top = Node(stream)
# assert that the string started with '{' and was one top node
assert len(tree_top.children) == 1 and tree_top.value == ''
return tree_top.children[0]
def __str__(self):
return self.value
def __repr__(self):
return "Node('%s', <%d children>)" % (
self.value, len(self.children))
def tree_string(self, level=0):
yield '-' + " " * level + str(self)
for child in self.children:
for child_string in child.tree_string(level+1):
yield child_string
tree = '{121{12}12{211}2}'
for line in Node.from_string(tree).tree_string():
print(line)
Results:
-121122
- 12
- 211
Below I'm attempting to make a simple Keygen as a first project. Somewhere I'm getting the error the Self has not been defined.
I'm guessing it's probably something easy
import random
class KeyGenerator():
def __init__(self):
length = 0
counter = 0
key = []
Letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
def KeyGen4(self):
while self.counter != self.length:
a = random.choice(self.Letters)
print a #test
r = (random.randint(0,1))
print r #test
if r == True:
a = a.upper()
else:
pass
self.key.append(a)
self.counter += 1
s = ''
self.key = s.join(key)
print self.key
return self.key
def start(self):
selection = raw_input('[K]eygen4, [C]ustom length Keygen or [N]umbers? >')
if selection == 'K' or 'k':
length = 4
keyGen4(self)
elif selection == 'N' or 'n':
KeyGenN(self)
elif selection == 'C' or 'c':
length = int(raw_input("Key Length: "))
#KeyGen4(self) # Change later after creating method with more options
start(self)
Your indention is wrong, but I assume this is only a copy-pasting issue.
That start(self) at the bottom doesn't make sense,
and indeed self is not defined there. You should create an instance of the class, and then call its start method:
KeyGenerator().start()
# or
key_gen = KeyGenerator()
key_gen.start()
You have two problems:
you miss indentation on every class-function
you must create an object of the class before you can call any of its functions
Your class should look like this
import random
class KeyGenerator():
def __init__(self):
length = 0
counter = 0
key = []
Letters = ['a','b','c','d','e']
def KeyGen4(self):
while self.counter != self.length:
a = random.choice(self.Letters)
print a #test
r = (random.randint(0,1))
print r #test
if r == True:
a = a.upper()
else:
pass
self.key.append(a)
self.counter += 1
s = ''
self.key = s.join(key)
print self.key
return self.key
def start(self):
selection = raw_input('[K]eygen4, [C]ustom length Keygen or [N]umbers? >')
if selection == 'K' or 'k':
length = 4
self.keyGen4()
elif selection == 'N' or 'n':
self.KeyGenN()
elif selection == 'C' or 'c':
length = int(raw_input("Key Length: "))
#KeyGen4(self) # Change later after creating method with more options
#now make an instance of your class
my_key_gen = KeyGenerator()
my_key_gen.start()
Please note that when calling class functions inside the class, you need to use self.FUNCNAME. All class functions should take "self" as argument. If that is their only argument then you simply call them with self.func(). If they take arguments you still ommit the self, as self.func(arg1, arg2)
By using message passing to fuifill the code such that
s = make_stack()
print(s("is_empty")) # True
s("push")(1)
s("push")(2)
print(s("peek")) # [2]
print(str(s("pop"))) # [2]
My code is supposed to fill in the blanks of
def make_stack():
items = []
def oplookup(msg):
if msg == "is_empty":
# blank #
elif msg == "clear":
# blank #
elif msg == "peek":
# blank #
elif msg == "push":
# blank #
elif msg == "pop":
# blank #
else:
raise Exception("stack doesn't" + msg)
return oplookup
I don't understand the tracing of the code. My own trial code is
def make_stack():
items = []
def oplookup(msg):
if msg == "is_empty":=
return True
elif msg == "clear":
return []
elif msg == "peek":
return make_stack.items[-1]
elif msg == "push":
return items.append(msg)
elif msg == "pop":
return items.pop()
else:
raise Exception("stack doesn't" + msg)
return oplookup
Another question is for having s("push") (1), what argument does (1) take? Is it under msg or item?
I think the first issue you have is that you need to return something callable from oplookup, probably a function. The functions all need to manipulate (or test) the items list (which they can access because they are closures).
Here's what that code might look like:
def make_stack():
items = []
def oplookup(msg):
if msg == "is_empty":
def empty():
return not items
return empty
elif msg == "clear":
def clear():
items[:] = [] # slice assignment, to clear in-place
return clear
#...
Note that in clear I avoid doing an assignment directly to items because it's in the enclosing scope. In Python 2, it's impossible to reassign items, since it is neither local or global variable. In Python 3, reassignment is possible using the nonlocal keyword. Since I don't know what version of Python you're using, I used a slice assignment which works in both versions.
This style of code is not very Pythonic. A much more natural way to do this would be to make a class with methods (but you'd end up with a slightly different API):
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return not self.items
def clear(self):
self.items = [] # this time we can replace the list
def push(self, item):
self.items.append(item)
#...
I'm writing a class for a simple game of 4 in a row, but I'm running into a problem calling a method in the same class. Here's the whole class for the sake of completeness:
class Grid:
grid = None
# creates a new empty 10 x 10 grid
def reset():
Grid.grid = [[0] * 10 for i in range(10)]
# places an X or O
def place(player,x,y):
Grid.grid[x][y] = player
# returns the element in the grid
def getAt(x,y):
return Grid.grid[x][y]
# checks for wins in a certain direction
def checkLine(player,v,count,x,y):
x = x+v[0]
y = y+v[1]
if x < 0 or x > 9:
return
if y < 0 or y > 9:
return
if Grid.grid[x][y] == p:
count = count+1
if count == 4:
return True
checkLine(player,v,count,x,y)
return False
# returns the number of the player that won
def check():
i = 'i'
for x in range(0,10):
for y in range(0,10):
if Grid.grid[x][y] > 0:
p = Grid.grid[x][y]
f = checkLine(p,0,array(i,[1,0]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[0,1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[1,1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,0]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[0,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[1,-1]),x,y)
if f:
return p
f = checkLine(p,0,array(i,[-1,1]),x,y)
if f:
return p
return 0
reset = staticmethod(reset)
place = staticmethod(place)
getAt = staticmethod(getAt)
check = staticmethod(check)
checkLine = staticmethod(checkLine)
I'm trying to call checkLine() from check(), but I get the error "NameError: global name 'checkLine' is not defined". When I call Grid.checkLine() instead, I get "TypeError: 'module' object is not callable"
How do I call checkLine()?
EDIT:
#beer_monk
class Grid(object):
grid = None
# creates a new empty 10 x 10 grid
def reset(self):
Grid.grid = [[0] * 10 for i in range(10)]
# places an X or O
def place(self,player,x,y):
Grid.grid[x][y] = player
# returns the element in the grid
def getAt(self,x,y):
return Grid.grid[x][y]
# checks for wins in a certain direction
def checkLine(self,player,v,count,x,y):
x = x+v[0]
y = y+v[1]
if x < 0 or x > 9:
return
if y < 0 or y > 9:
return
if Grid.grid[x][y] == p:
count = count+1
if count == 4:
return True
checkLine(self,player,v,count,x,y)
return False
# returns the number of the player that won
def check(self):
i = 'i'
for x in range(0,10):
for y in range(0,10):
if Grid.grid[x][y] > 0:
p = Grid.grid[x][y]
for vx in range(-1,2):
for vy in range(-1,2):
f = self.checkLine(p,0,array(i,[vx,vy]),x,y)
if f:
return p
return 0
reset = staticmethod(reset)
place = staticmethod(place)
getAt = staticmethod(getAt)
check = staticmethod(check)
checkLine = staticmethod(checkLine)
Get rid of the class. Use plain functions and module level variable for grid.
The class is not helping you in any way.
PS. If you really want to call checkline from within the class, you'd call Grid.checkline. For example:
class Foo:
#staticmethod
def test():
print('Hi')
#staticmethod
def test2():
Foo.test()
Foo.test2()
prints
Hi
Syntax:
class_Name.function_Name(self)
Example:
Turn.checkHoriz(self)
A reworked example (hopefully showing a better use of classes!)
import itertools
try:
rng = xrange # Python 2.x
except NameError:
rng = range # Python 3.x
class Turn(object):
def __init__(self, players):
self.players = itertools.cycle(players)
self.next()
def __call__(self):
return self.now
def next(self):
self.now = self.players.next()
class Grid(object):
EMPTY = ' '
WIDTH = 10
HEIGHT = 10
WINLENGTH = 4
def __init__(self, debug=False):
self.debug = debug
self.grid = [Grid.EMPTY*Grid.WIDTH for i in rng(Grid.HEIGHT)]
self.player = Turn(['X','O'])
def set(self, x, y):
if self.grid[y][x]==Grid.EMPTY:
t = self.grid[y]
self.grid[y] = t[:x] + self.player() + t[x+1:]
self.player.next()
else:
raise ValueError('({0},{1}) is already taken'.format(x,y))
def get(self, x, y):
return self.grid[y][x]
def __str__(self):
corner = '+'
hor = '='
ver = '|'
res = [corner + hor*Grid.WIDTH + corner]
for row in self.grid[::-1]:
res.append(ver + row + ver)
res.append(corner + hor*Grid.WIDTH + corner)
return '\n'.join(res)
def _check(self, s):
if self.debug: print("Check '{0}'".format(s))
# Exercise left to you!
# See if a winning string exists in s
# If so, return winning player char; else False
return False
def _checkVert(self):
if self.debug: print("Check verticals")
for x in rng(Grid.WIDTH):
winner = self._check([self.get(x,y) for y in rng(Grid.HEIGHT)])
if winner:
return winner
return False
def _checkHoriz(self):
if self.debug: print("Check horizontals")
for y in rng(Grid.HEIGHT):
winner = self._check([self.get(x,y) for x in rng(Grid.WIDTH)])
if winner:
return winner
return False
def _checkUpdiag(self):
if self.debug: print("Check up-diagonals")
for y in rng(Grid.HEIGHT-Grid.WINLENGTH+1):
winner = self._check([self.get(d,y+d) for d in rng(min(Grid.HEIGHT-y, Grid.WIDTH))])
if winner:
return winner
for x in rng(1, Grid.WIDTH-Grid.WINLENGTH+1):
winner = self._check([self.get(x+d,d) for d in rng(min(Grid.WIDTH-x, Grid.HEIGHT))])
if winner:
return winner
return False
def _checkDowndiag(self):
if self.debug: print("Check down-diagonals")
for y in rng(Grid.WINLENGTH-1, Grid.HEIGHT):
winner = self._check([self.get(d,y-d) for d in rng(min(y+1, Grid.WIDTH))])
if winner:
return winner
for x in rng(1, Grid.WIDTH-Grid.WINLENGTH+1):
winner = self._check([self.get(x+d,d) for d in rng(min(Grid.WIDTH-x, Grid.HEIGHT))])
if winner:
return winner
return False
def isWin(self):
"Return winning player or False"
return self._checkVert() or self._checkHoriz() or self._checkUpdiag() or self._checkDowndiag()
def test():
g = Grid()
for o in rng(Grid.WIDTH-1):
g.set(0,o)
g.set(Grid.WIDTH-1-o,0)
g.set(Grid.WIDTH-1,Grid.HEIGHT-1-o)
g.set(o,Grid.HEIGHT-1)
print(g)
return g
g = test()
print g.isWin()
Unlike java or c++, in python all class methods must accept the class instance as the first variable. In pretty much every single python code ive seen, the object is referred to as self. For example:
def reset(self):
self.grid = [[0] * 10 for i in range(10)]
See http://docs.python.org/tutorial/classes.html
Note that in other languages, the translation is made automatically
There are multiple problems in your class definition. You have not defined array which you are using in your code. Also in the checkLine call you are sending a int, and in its definition you are trying to subscript it. Leaving those aside, I hope you realize that you are using staticmethods for all your class methods here. In that case, whenever you are caling your methods within your class, you still need to call them via your class's class object. So, within your class, when you are calling checkLine, call it is as Grid.checkLine That should resolve your NameError problem.
Also, it looks like there is some problem with your module imports. You might have imported a Module by name Grid and you have having a class called Grid here too. That Python is thinking that you are calling your imported modules Grid method,which is not callable. (I think,there is not a full-picture available here to see why the TypeError is resulting)
The best way to resolve the problem, use Classes as they are best used, namely create objects and call methods on those objects. Also use proper namespaces. And for all these you may start with some good introductory material, like Python tutorial.
Instead of operating on an object, you are actually modifying the class itself. Python lets you do that, but it's not really what classes are for. So you run into a couple problems
-You will never be able to make multiple Grids this way
the Grid can't refer back to itself and e.g. call checkLine
After your grid definition, try instantiating your grid and calling methods on it like this
aGrid = Grid()
...
aGrid.checkLine()
To do that you, you first need to modify all of the method definitions to take "self" as your first variable and in check, call self.checkLine()
def check(self):
...
self.checkLine()
...
Also, your repeated checking cries out for a FOR loop. You don't need to write out the cases.
Java programmer as well here, here is how I got it to call an internal method:
class Foo:
variable = 0
def test(self):
self.variable = 'Hi'
print(self.variable)
def test2(self):
Foo.test(self)
tmp = Foo()
tmp.test2()