Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
6 changes: 6 additions & 0 deletions config.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -429,6 +429,12 @@
"difficulty": 1,
"topics": [
]
},
{
"slug": "simple-linked-list",
"difficulty": 1,
"topics": [
]
}
],
"deprecated": [
Expand Down
67 changes: 67 additions & 0 deletions exercises/simple-linked-list/example.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
class Element(object):
def __init__(self, value):
self.value = value
self.next = None


class LinkedList(object):
def __init__(self, head=None):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The head argument is never used. Maybe it could be used for the from array list creation instead.

self.head = head
self.size = 0

def push(self, new_element):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming needs to be improved. Right now one can push values, than the parameter should be named accordingly or the method should accept Elements instead.

new_e = Element(new_element)

if self.empty():
self.head = new_e
else:
new_e.next = self.head
self.head = new_e
self.size += 1

def pop(self):
if self.empty():
return None
else:
e = self.head

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for undescriptive short variable names, there is enough space for element = self....

self.head = self.head.next
self.size -= 1
return e.value

def empty(self):
return self.size == 0

def get_peek(self):
if self.empty():
return None
else:
return self.head.value

def reverse(self):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention is that reverse/sort/etc work change the actual instance, while reversed/sorted/etc would return a new changed instance leaving the other instance unchanged.

new_list = LinkedList()
if self.size > 0:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to check size and the current element, one check is sufficient. It makes the code more understandable:

defreversed(self):
new_list=LinkedList()
current=self.headwhilecurrent:
new_list.push(current.value)
current=current.nextreturnnew_list

current = self.head
while current.next:
new_list.push(current.value)
current = current.next
new_list.push(current.value)
return new_list

def to_array(self):
arr = []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method also doesn't need two checks for the same thing. There is also no need in cutting variable names short.

defto_array(self):
array= []
current=self.headwhilecurrent:
array.append(current.value)
current=current.nextreturnarray

if self.empty():
return []
current = self.head
while current.next:
arr.append(current.value)
current = current.next
arr.append(current.value)
return arr

def from_array(self, arr=[]):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would either implement the from_array initializer using the __init__(self, array=None) method or a @classmethod (see: https://stackoverflow.com/a/682545).

if len(arr) == 0:
return self
else:
for i in arr:
self.push(i)
return self
65 changes: 65 additions & 0 deletions exercises/simple-linked-list/simple-linked-list_test.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
import unittest

from simple_linked_list import LinkedList


class LinkedListTests(unittest.TestCase):
def setUp(self):
self.slist = LinkedList()

def test_size(self):
self.slist.push(0)
self.assertEqual(1, self.slist.size)
# notice if size is increased
self.slist.push(1)
self.assertEqual(2, self.slist.size)
self.slist.push(2)
self.assertEqual(3, self.slist.size)

def test_pop(self):
# with cero element
self.assertIsNone(self.slist.pop())
# with multiple elements
self.slist.push(1)
self.slist.push(2)
self.slist.push(3)
self.assertEqual(3, self.slist.pop())
self.assertEqual(2, self.slist.pop())
self.assertEqual(1, self.slist.pop())
self.assertIsNone(self.slist.pop())

def test_reverse(self):
# empty reversed LinkedList
empty_reversed = self.slist.reverse()
self.assertEqual(0, empty_reversed.size)
self.assertIsNone(empty_reversed.head)
# push_elements
self.slist.push(1)
self.slist.push(2)
self.slist.push(3)
self.slist.push(4)
reversed_list = self.slist.reverse()
self.assertEqual(1, reversed_list.head.value)
self.assertEqual(1, reversed_list.get_peek())

def test_to_array(self):
# in : empty list out : empty array
self.assertListEqual([], self.slist.to_array())
# push_elements
self.slist.push(1)
self.slist.push(2)
self.slist.push(3)
self.slist.push(4)
self.assertListEqual([4, 3, 2, 1], self.slist.to_array())

def test_from_array(self):
# in : empty array out : empty list
self.assertIsNone(self.slist.from_array([]).head)
# push_elements
new_arr = [1, 2, 3, 4]
self.assertEqual(4, self.slist.from_array(new_arr).head.value)
self.assertEqual(4, self.slist.from_array(new_arr).get_peek())


if __name__ == '__main__':
unittest.main()