Last active
November 18, 2022 21:13
-
-
Save heyajulia/0c14b7c8dac91020a760cf80f8a0c929 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LinkedListNode { | |
init(value) { | |
this.value = value; | |
this.next = nil; | |
} | |
/// Gets the value of this LinkedListNode. | |
getValue() { return this.value; } | |
/// Returns true if there is another LinkedListNode after this one. | |
hasNext() { return this.next != nil; } | |
/// Sets the next node of this LinkedListNode to next. | |
setNext(next) { this.next = next; } | |
/// Gets the node afer this LinkedListNode Returns nil if there is none. | |
getNext() { return this.next; } | |
} | |
class LinkedList { | |
init() { this.head = nil; } | |
/// Adds value to this LinkedList. | |
add(value) { | |
if (this.head == nil) { | |
this.head = LinkedListNode(value); | |
return; | |
} | |
var node = this.head; | |
while (node.hasNext()) { | |
node = node.getNext(); | |
} | |
node.setNext(LinkedListNode(value)); | |
} | |
/// Returns the value at index. | |
get(index) { | |
if (index < 0) { | |
return nil; | |
} | |
var node = this.head; | |
if (index == 0) { | |
if (node == nil) { | |
return nil; | |
} | |
return node.getValue(); | |
} | |
for (var i = 0; i <= index; i = i + 1) { | |
if (i == index) { | |
if (node == nil) { | |
return nil; | |
} | |
return node.getValue(); | |
} | |
if (node == nil) { | |
return nil; | |
} | |
node = node.getNext(); | |
} | |
// FIXME: Can we get here? | |
} | |
/// Executes fn with every value in this LinkedList. | |
/// | |
/// If fn returns true, iteration stops and forEach returns the current | |
/// node. This should only be called from data structures built upon | |
/// LinkedList. | |
forEach(fn) { | |
var node = this.head; | |
while (node != nil) { | |
if (fn(node.getValue())) { | |
return node; | |
} | |
node = node.getNext(); | |
} | |
} | |
} | |
class LinkedHashMapKeyValuePair { | |
init(key, value) { | |
this.key = key; | |
this.value = value; | |
} | |
/// Returns the key of this LinkedHashMapKeyValuePair. | |
getKey() { return this.key; } | |
/// Returns the value of this LinkedHashMapKeyValuePair. | |
getValue() { return this.value; } | |
/// Sets the value of this LinkedHashMapKeyValuePair. | |
setValue(value) { this.value = value; } | |
} | |
class LinkedHashMap { | |
init() { this.linkedList = LinkedList(); } | |
/// Sets key to value in this LinkedHashMap. | |
set(key, value) { | |
if (!this.contains(key)) { | |
this.linkedList.add(LinkedHashMapKeyValuePair(key, value)); | |
return; | |
} | |
var kvp = this._getKeyValuePairWithKey(key); | |
kvp.getValue().setValue(value); | |
} | |
_getKeyValuePairWithKey(key) { | |
fun createKeyPredicate(key) { | |
fun keyPredicate(kvp) { | |
return kvp.getKey() == key; | |
} | |
return keyPredicate; | |
} | |
var keyPredicate = createKeyPredicate(key); | |
return this.linkedList.forEach(keyPredicate); | |
} | |
/// Returns true if this LinkedHashMap contains key. | |
contains(key) { | |
var kvp = this._getKeyValuePairWithKey(key); | |
return kvp != nil; | |
} | |
/// Returns the value of key or nil if it does not exist. | |
get(key) { | |
var kvp = this._getKeyValuePairWithKey(key); | |
if (kvp == nil) { | |
return nil; | |
} | |
return kvp.getValue().getValue(); | |
} | |
} | |
fun newSuite(suite) { | |
fun assert(condition, message) { | |
if (!condition) { | |
print "[" + suite + "]" + " Assertion failed: " + message + "."; | |
} | |
} | |
return assert; | |
} | |
fun test_LinkedList() { | |
var assert = newSuite("LinkedList"); | |
var ll = LinkedList(); | |
assert(ll.get(0) == nil, "expected the head of an empty list to be be nil"); | |
ll.add(1); | |
assert(ll.get(0) == 1, "expected the first element to be 0"); | |
assert(ll.get(1) == nil, "expected the second (non-existent) element to be nil"); | |
ll.add("muffins"); | |
assert(ll.get(1) != nil, "expected the second (existent) element to be non-nil"); | |
assert(ll.get(1) == "muffins", "expected the second element to be 'muffins'"); | |
assert(ll.get(-1) == nil, "-1: expected out-of-bounds to return nil"); | |
assert(ll.get(2) == nil, "2: expected out-of-bounds to return nil"); | |
assert(ll.get(20210216) == nil, "20210216: expected out-of-bounds to return nil"); | |
var calls = 0; | |
fun countCall(node) { | |
calls = calls + 1; | |
} | |
ll.forEach(countCall); | |
assert(calls == 2, "expected 'calls' to equal 2"); | |
} | |
fun test_LinkedHashMap() { | |
var assert = newSuite("LinkedHashMap"); | |
var hm = LinkedHashMap(); | |
assert(hm.get("foo") == nil, "expected non-existent key to be nil"); | |
hm.set("foo", 123); | |
assert(hm.get("foo") == 123, "expected existent key to be 123"); | |
hm.set("foo", 456); | |
assert(hm.get("foo") == 456, "expected updated key to be 456"); | |
assert(hm.get("bar") == nil, "expected other non-existent key to be nil"); | |
hm.set("bar", hm.get("foo")); | |
assert(hm.get("bar") == 456, "expected other key to equal initial key after set"); | |
hm.set("baz", "cookies!"); | |
assert(hm.contains("foo") | |
and hm.contains("bar") | |
and hm.contains("baz") | |
and !hm.contains("quux"), | |
"expected hash map to contain keys foo bar baz, but not quux"); | |
} | |
test_LinkedList(); | |
test_LinkedHashMap(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment