import node type Node = { isNone->Boolean getOrElse(_:Node)->Node ==(_:Node)->Boolean asString->String elt->Dynamic setElt(_:Dynamic)->Void next->Node setNext(_:Node)->Void at(_:Number)->Node indexOf(_:Dynamic)->Number firstNodeWithProp(_:TestNode)->Node firstNodeWithVal(_:Dynamic)->Node} type TestNode = { apply(_:Node)->Boolean} type Iterator= { reset->Void hasNext->Boolean next->T get->T} type Collection = { size->Number isEmpty->Boolean clear->Void contains(_:T)->Boolean addFirst(_:T)->Void addLast(_:T)->Void firstElement->T lastElement->T removeFirst->T removeLast->T removeValue(_:T)->Dynamic indexOf(_:T)->Number at(_:Number)->T setValue(_:T)at(_:Number)->T add(_:T)at(_:Number)->Void removeFromIndex(_:Number)->T iterator->Iterator asString->String forEachDo(_:Block)->Void map(_:Block)->Collection} type SinglyLinkedList = Collection & {} def missing is public, readable = node.missing // Constructs an empty list method new->SinglyLinkedList is public{LinkedListClass.new} class LinkedListClass.new{ // Number of elements in list var count:Number is readable:= 0 // Reference to first element of list var head:Node is readable:= node.empty // @post value is added to beginning of list // @param value the value to be added method addFirst(value:Dynamic)->Void is public{ head := node.withValue(value)next(head) count := count + 1} // @post value is added to end of list // @param value the value to be added method addLast(value:Dynamic)->Void is public{add(value)at(size + 1)} // @post @return the head of the list method firstElement->Dynamic is public{head.elt} // @post @return the tail of the list method lastElement->Dynamic is public{at(size)} // @pre list is not empty // @post removes and returns value at head of list // @return value actually removed method removeFirst->Dynamic is public{ var temp:Node := head head := head.next count := count - 1 return temp.elt} // @pre list is not empty // @post removes and returns value at tail of list // @return value actually removed method removeLast->Dynamic is public{removeFromIndex(size)} // @pre value is not "missing" // @post removes first element with matching value // @param val the value to be removed // @return the value removed, or misssing if no such // value in list method removeValue(val:Dynamic)->Dynamic is public{ var index:Number := indexOf(val) if(index > 0) then {removeFromIndex(index)} else{ //print "No instance of {val} in list" return missing} } // @post @return number of elements in list method size->Number is public{count} // @pot @return true iff no elements in list method isEmpty->Boolean is public{size == 0} // @post removes all values from list method clear->Void is public{ head := node.empty count := 0} // @pre 1 <= i <= size // @post @return value at location i // @param i the position of value to be retrieved method at(i:Number)->Dynamic is public{nodeAt(i).elt} // @pre 1 <= i <= size // @post @return node at location i // @param i the position of node to be retrieved method nodeAt(i:Number)->Node is confidential{head.at(i)} // @pre 1 <= i <= size // @post sets ith entry of list to newValue // @param i location of entry to be changed // @param newValue the new value // @return former value of entry to be changed method setValue(newValue:Dynamic)at(i:Number)->Dynamic is public{ if(head.isNone || head.at(i).isNone) then {return missing} else{ var oldVal:Dynamic := head.at(i).elt head.at(i).setElt(newValue) oldVal} } // @pre 1 <= i <= size + 1 // @post inserts value at i // @param i the index of the new value // @param value the value to be stored method add(value:Dynamic)at(i:Number)->Void is public{ if(i == 1) then{addFirst(value)} else{ var prev:Node := nodeAt(i-1) if(!prev.isNone) then{ var nNode:Node := node.withValue(value)next(prev.next) count := count + 1 prev.setNext(nNode)} } } // @pre 1 <= i <= size // @post removes value at location i // @param i position of value to be retrieved // @return value removed method removeFromIndex(i:Number)->Dynamic is public{ if(i == 1) then{removeFirst} else{ var prev:Node := nodeAt(i - 1) var target:Node := prev.next if(prev.isNone || target.isNone) then {return missing} else{ count := count - 1 prev.setNext(target.next) target.elt} } } // @pre value is not "missing" // @post @return first location of value in list, or -1 // if value not found // @param value the value sought method indexOf(value:Dynamic)->Number is public{head.indexOf(value)} // @post @return iterator to traverse list from head to tail method iterator->Iterator is public{LLIterator.new(head)} // @post @return string representation of list method asString->String is public{ var str:String := "[" var finger:Node := head while{!finger.isNone} do{ str := str ++ finger.elt ++ ", " finger := finger.next} str ++ "]"} // @pre value is not "missing" // @post @return true iff value found in list // @param value the value sought method contains(value:Dynamic)->Boolean is public{indexOf(value) != -1} // @post applies closure to each element of list // @param closure is a block that takes element of // whatever type current list contains method forEachDo(closure:Block)->Void is public{ for(1..size) do {i-> closure.apply(at(i))} } // @post @return list containing elements of this list with // function mapped to them // @param function is a block that takes element of whatever // type current list contains method map(function:Block)->SinglyLinkedList is public{ var result:SinglyLinkedList := LinkedListClass.new for(1..size) do {i-> result.addLast(function.apply(at(i)))} } } class LLIterator.new(t:Node){ var head:Node is readable := t var current:Node is readable := head method reset->Void is public{current := head} method hasNext->Boolean is public{!current.isNone} method next->Dynamic is public{ var value:Dynamic := current.elt current := current.next value} method get->Dynamic is public{current.elt} }