Skip to content

Instantly share code, notes, and snippets.

@heyajulia
Last active November 18, 2022 21:13
Show Gist options
  • Save heyajulia/0c14b7c8dac91020a760cf80f8a0c929 to your computer and use it in GitHub Desktop.
Save heyajulia/0c14b7c8dac91020a760cf80f8a0c929 to your computer and use it in GitHub Desktop.
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