I am creating the Josephus problem using a circular doubly linked list. I am getting an Attribute error, which I assume is because my current_node (first node) does not have a .prev yet.
I understand that the prev of my first node should point to the next of my last node to create a circular doubly linked list.
Can someone guide me on whether I have correctly identified the error? If yes, how can I rectify it?
If not, then what are the other ways I can correct the error?
#Initialize the node
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
def remove(self, n):
print("Student " +str(n)+ " was removed")
class Circle:
# Initializing the DLL
def __init__(self):
self.head = None
self.tail = None
#Inserting elements 2 to n in the dll
def insert_after(self, x, data):
y = Student(data) # make a new Node object.
z = Student(data)
z = x.next
y.prev = x
y.next = z
x.next = y
z.prev = y
def josephus_solution(self, dllist, n, k):
no_of_active_nodes = n
current_node = Student(1)
#last_node = Student(n)
#print(current_node.prev)
for i in range(2, n + 1):
dllist.insert_after(current_node, i)
count = 0
#print(current_node.data)
while (current_node.next != current_node.prev):
#print(current_node.next.prev)
current_node = current_node.next
count += 1
#print(current_node.data)
if (count == k):
current_node.remove(current_node.data)
current_node.prev.next = current_node.next
current_node.next.prev = current_node.prev
count = 0
no_of_active_nodes -= 1
#print(no_of_active_nodes)
if (no_of_active_nodes == 1):
print("Student" + str(current_node.data) + "Recieves the scholarship")
return current_node.data
dllist = Circle()
n = 5 #int(input('Input number of people (n): '))
k = 2 #int(input('The nth person will be executed. Input k: '))
ans = dllist.josephus_solution(dllist, n, k)
Error
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/tmp/ipykernel_24/3762059582.py in <module>
54 n = 5 #int(input('Input number of people (n): '))
55 k = 2 #int(input('The nth person will be executed. Input k: '))
---> 56 ans = dllist.josephus_solution(dllist, n, k)
/tmp/ipykernel_24/3762059582.py in josephus_solution(self, dllist, n, k)
32 #print(current_node.prev)
33 for i in range(2, n + 1):
---> 34 dllist.insert_after(current_node, i)
35 count = 0
36 #print(current_node.data)
/tmp/ipykernel_24/3762059582.py in insert_after(self, x, data)
24 x.next = y
25
---> 26 z.prev = y
27
28 def josephus_solution(self, dllist, n, k):
AttributeError: 'NoneType' object has no attribute 'prev'
The direct reason for the error is that
zisNoneand your code can therefore not access anyprevattribute of it in the linez.prev = y. The cause is that when the first node is created, itsprevandnextattributes are initialised toNone, and when this node is passed asxargument toinsert_after, then withz = x.nextaNonevalue is assigned toz.There are several issues with your approach:
insert_afterit makes no sense to callStudenttwice, since you want to insert one node, not twoCircleclass has aheadand atailattribute, they are never used after their initialisation toNone, so there is actually nothing in the Circle instance that helps you to maintain the list. You might as well define all methods on theStudentclass.josephus_solutionis probably intended to test that only one node remains in the list, but it actually verifies whether there are two left. Admittedly, this works whencurrent_nodeis a node that was just deleted, but then the returned data is the data of the deleted node and not the remaining active node, andcurrent_nodeis not a just-deleted node, then this condition will make the loop exit when it still has two active nodes.Some other remarks:
josephus_solutionas a method, it should not be necessary to also pass an instance as argument.selfis already available to that methodjosephus_solutionwork on an existing linked list.nextorprevattributes should ever beNone, you'll make things easier when initialising them toselfinstead ofNone.removemethod should not be responsible for printing a message, but should on the other hand be responsible for rewiring theprevandnextreferences. At any rate, there is no need for this method to get an argument, as it knows its own attributes throughself.current_node = current_node.nextstatement to be the last line in the body of the loop. This also helps to be sure thatcurrent_nodeis never a just-deleted node when thewhilecondition is evaluated.whilecondition already takes care of when to stop, there should be no reason to keep track with ano_of_active_nodesvariable.There are more remarks to make, but these are what I believe the most important.
Here is a correction of your code, taking all of the above into account: