Implementing Iterable class on a Linked List in Dartlang? - linked-list

I know that dart:collection library has a great Linked List implementation. Yet I am trying to implement a linked list myself as a part of a MOOC .
Here is my very simple Linked List implementation
import './node.dart';
class LinkedList {
// root node of the list
Node root = null;
// the number of items on the list
int _count = 0;
// returns true if root is not set
bool isEmpty(){
return this.root == null;
}
// getter for the _count variable;
get count{
return this._count;
}
// push method to push a new item to the end of the list
push(String content) {
Node item = new Node(content);
if (this.root == null) {
this._count += 1;
this.root = item;
} else {
Node iterator = root;
while (iterator.next != null) {
iterator = iterator.next;
}
this._count += 1;
iterator.next = item;
}
return item;
}
}
I would like to have it implement Iterable Class properties and methods like foreach and length . I read the docs for Iterable and IterableMixin class but I'm still struggling to understand how to use them with my LinkedList class since the docs give only example for using a Map as an Iterable .

Extend IterableBase docs and you should be good to go!

Related

Saxonia s9api integrated Extension functions Provide node

we are trying to submit a node using the integrated extension function. The node looks correct as far as it goes, but we can't access the individual elements, because there is always an outOfBound exception appearance.
How can we access the individual elements below the root element?
public ExtensionFunction updateTempNode = new ExtensionFunction() {
public QName getName() {
return new QName("de.dkl.dymoServer.util.ExternalFunctions", "updateTempNode");
}
public SequenceType getResultType() {
return SequenceType.makeSequenceType(
ItemType.BOOLEAN, OccurrenceIndicator.ONE
);
}
public net.sf.saxon.s9api.SequenceType[] getArgumentTypes() {
return new SequenceType[]{
SequenceType.makeSequenceType(
ItemType.STRING, OccurrenceIndicator.ONE),
SequenceType.makeSequenceType(
ItemType.DOCUMENT_NODE, OccurrenceIndicator.ONE)};
}
public XdmValue call(XdmValue[] arguments) {
String sessionId = arguments[0].itemAt(0).getStringValue();
SaplingElement tempNode = TransformationService.tempNodes.get(sessionId);
ItemTypeFactory itemTypeFactory = new ItemTypeFactory(((XdmNode) arguments[1]).getProcessor());
tempNode.withChild(
arguments[1].stream().map(xdmValue -> Saplings.elem(xdmValue.getStringValue()).withText(xdmValue.itemAt(0).getStringValue())).toList()
.toArray(SaplingElement[]::new)
);
System.out.println(tempNode);
return new XdmAtomicValue(true);
}
};
AOOB as I try to iterate
Data expected as document_node
Wild guess is that you want something like
tempNode = tempNode.withChild(
arguments[1]
.select(Steps.child().then(Steps.child()))
.map(childNode -> Saplings.elem(childNode.getNodeName()).withText(childNode.itemAt(0).getStringValue()))
.collect(Collectors.toList())
.toArray(new SaplingElement[]{})
);
which would populate tempNode with copies of the child nodes of the root element of the document node that is arguments[1]. There might be better ways to do that.
.

Iterating through a linked list using recursion gives me a run time error (stack overflow) on LeetCode

I am new to programming and today I wanted to try out the LeetCode problem 234. Palindrome Linked List:
Given the head of a singly linked list, return true if it is a palindrome or false otherwise.
Example 1:
Input: head = [1,2,2,1]
Output: true
but I couldn't even manage the first problem.
I first tried to convert the linked list to a string and compare like:
String[i] == String[length-i-1]
which worked for small lists but not for the gigantic test list where I got:
Time Limit Exceeded
In my second attempt I used recursion like this:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode? next;
* ListNode([this.val = 0, this.next]);
* }
*/
class Solution {
bool isPalindrome(ListNode? head) {
ListNode? current = head;
while(current?.next != null)
current = current?.next;
if (current?.val != head?.val)
return false;
else{
current = null;
isPalindrome(head?.next);
}
return true;
}
}
This also works with small lists, but for the test list I get a run time error:
Stack overflow
I wonder where this issue comes from.
Is it due to the maximum number of nested calls? And where can I find the recursion depth of Dart?
Or is there just a way simpler solution for this?
There are several issues with your attempt:
current = null will only set that variable to null. It does not affect the list. If you want to remove the last element from the list, you'll need access to the node that precedes it, and set its next property to null.
The boolean that the recursive call returns is always ignore. Instead execution continues with the return true statement, which will lead to incorrect results (when false was expected).
Before mentioning another problem, here is the correction for your algorithm:
bool isPalindrome(ListNode? head) {
ListNode? current = head;
ListNode? prev = null;
while(current?.next != null) {
prev = current; // follow behind current
current = current?.next;
}
if (current?.val != head?.val)
return false;
else if (prev == null)
return true; // List has only one node
else {
prev?.next = null; // Detach the tail node
return isPalindrome(head?.next); // Return the recursive result!
}
}
This will do the job correctly, but it is too slow. At every level of recursion almost all of the same nodes are iterated again (with that while loop), so for a list with 100 nodes, there are 100+98+96+94+...+2 iterations. In other words, the time complexity of this algorithm is quadratic. You'll need a different idea for the algorithm.
One idea for an efficient algorithm that doesn't require extra O(n) space, is to:
find the middle node of the list. You can for instance first determine the length of the list with a first iteration, and then in a second iteration you can stop half way.
reverse the second half of the list, giving you two shorter lists. Here you could use recursion if you wanted to.
and then compare those two lists node by node.
There are several Q&A on this algorithm, also on this site, so I'll leave that for your further research.
If you cannot make it work, here is a solution (spoiler!):
class Solution {
int listSize(ListNode? head) {
int size = 0;
while(head?.next != null) {
head = head?.next;
size++;
}
return size;
}
ListNode? nodeAt(ListNode? head, int index) {
while(head?.next != null && index > 0) {
head = head?.next;
index--;
}
return index == 0 ? head : null;
}
ListNode? reverse(ListNode? head) {
ListNode? prev = null;
ListNode? next;
while (head != null) {
next = head.next;
head.next = prev;
prev = head;
head = next;
}
return prev;
}
bool isEqual(ListNode? head1, ListNode? head2) {
// Only compares the nodes that both lists have:
while (head1 != null && head2 != null) {
if (head1.val != head2.val) return false;
head1 = head1.next;
head2 = head2.next;
}
return true;
}
bool isPalindrome(ListNode? head) {
return isEqual(head, reverse(nodeAt(head, listSize(head) >> 1)));
}
}
I can't quite understand your recursion solution without pointers. I solved it using a list. It is not the best solution but is simple.
// Definition for singly-linked list.
// class ListNode {
// int val;
// ListNode? next;
// ListNode([this.val = 0, this.next]);
// }
class Solution {
bool isPalindrome(ListNode? head) {
List<int> stack = [];
ListNode? p = head;
while (p != null) {
stack.add(p.val);
p = p.next;
}
print(stack);
bool isP = true;
while(head!.next!=null&&isP){
var a = stack.removeLast();
print('removed $a');
print('head val ${head.val}');
isP = head.val==a;
head=head.next!;
}
return isP;
}
}
The problem with your solution is
After a while loop current is rightmost node in the list
while (current?.next != null) {
current = current?.next;
}
comparing leftmost and rightmost node of LinkedList
if (current?.val != head?.val)
return false;
Start over with head shifted one place to the right
else {
current = null;
isPalindrome(head?.next);
}
But current is still rightmost node after a while loop
while (current?.next != null) {
current = current?.next;
}
And this will return false
if (current?.val != head?.val)
{
return false;
}
After second recursion program exits returning true

How to compare objects in Vala?

I am using a Gee.ArrayList with an own class for content. I want to use the "contains" method of the ArrayList, but I really don't know how to set up an equals-method in my class, so ArrayList uses it to find out if the object is in the ArrayList or not.
Example:
class Test : GLib.Object {
public int number;
public Test(int n) {
number = n;
}
public bool equals (Test other) {
if (number == other.number) return true;
return false;
}
}
Then, in another file:
var t = new Gee.ArrayList<Test>();
var n1 = new Test(3);
var n2 = new Test(3);
t.add(n1);
t.contains(n2); // returns false, but I want it to return true
Does anybody know that?
When you create the ArrayList, the constructor takes your equality comparator. You can do:
var t = new Gee.ArrayList<Test>(Test.equals);
and the contains should work as you desire.

Mutable vs. Immutable

What should be considered to make a mutable class immutable? For example: Can we still have push and pop methods in an immutable stack class? Or we should simply remove any method that changes the state of the instantiated object?
The bottom line is: You'd be better to remove the method modifying the state of the instantiated object from the class. But if you want to keep it, then it should create a new object with a different state from the original one and return the new object back.
Here is a more specific answer:
There shouldn't be any methods changing the object state in an immutable class.
There are a lot of void methods which change the state of this object in a mutable class. So we should change the signature of them in a way the return a new object instead of changing "this" object's state.
Also there are a lot of non-void methods which change the state of "this" object and return the value they changed in "this". The signature of these methods should also be changed in a way that they return a new object instead of changing the state of "this". Talking about lists, usually another method (like "peek") is also needed to get a certain value. Check the sample bellow to get what do I mean:
Check out these "push" and "pop" methods for a mutable stack class:
public class Stack <E> {
…
public void push (E e) {
ensureCapacity(); // This method checks for capacity
elements[size++] = e;
}
This method adds a new element at the top of the stack and changes the state of "this" object in this way.
public E pop () {
if (size == 0) throw new IllegalStateException("Stack.pop");
E result = elements[--size];
elements[size] = null;
return result;
}
…
}
This method removes the element at the top of the stack and returns it back and changes the state of "this" object by removing the element.
Now, suppose that we need to change these methods to make this stack immutable. Let's deal with "push" method first:
"push" is a void method which changes the state of "this" object by adding a new element to it. To make the stack immutable we will create a new stack similar to "this" and add the new element to this new stack and return it back:
public class ImmStack <E> {
...
/**
* this method pushes the item to a new object and keeps the original object unchanged
* #param e The item to be pushed
* #return A new list
* #PRE An original list object is required as well as an item to be pushed
* #POST A new list would be returned
*/
#SuppressWarnings({ "unchecked", "rawtypes" }) // All items in this.elements[] are of type E
public ImmStack<E> push (E e) {
ImmStack<E> stc = new ImmStack(getNewElements());
stc.elements=ensureCapacity(stc.elements);
stc.elements[size] = e;
stc.size = size +1;
return stc;
}
"pop" method changes the state of "this" object by removing an element. To make the class immutable we will reate a new stack similar to "this" and remove the element from this new stack and return it back:
/**
* This pop method returns a new stack without the element at the top of the original list
* #return The new stack
* #POST The new stack would be returned
*/
#SuppressWarnings({ "unchecked", "rawtypes" }) // All items in this.elements[] are of type E
public ImmStack<E> pop () {
if (size == 0) throw new IllegalStateException("Stack.pop");
ImmStack<E> stc = new ImmStack(getNewElements());
stc.elements=ensureCapacity(stc.elements);
stc.elements[size-1] = null;
stc.size=size-1;
return stc;
}
The old "pop" method was returning the element at the top. We also need a new method which returns the element at the top to cover this feature:
/**
* Returns item at front of queue without removing.
* #return item at front
* #throws java.util.NoSuchElementException if empty
*/
public E top()
{
if (this.isEmpty())
{
throw new NoSuchElementException("Queue underflow");
}
return elements[size-1];
}
This was just an example. You might have more methods to change in your class to make it immutable.
If your stack is immutable, then by definition it cannot be changed. The push() and pop() methods cannot be completed.
When a method cannot be completed successfully, you can throw an exception. When a method can never be completed successfully, the standard exception to throw is UnsupportedOperationException.
For example:
public E[] push (E e) {
throw new UnsupportedOperationException();
}
EDIT:
You note in a comment that your push() method is just returning a deep copy of the stack with the new element. It looks like you're representing the immutable stack as an instance of a class, and the pushed stack as an array.
You can get the size of one of the two arrays referenced by newElements with newElements.length. So you could write code like this:
public E[] push (E e) {
E[] newElements=getNewElements();
int oldLength = newElements.length;
newElements=ensureCapacity(newElements);
int lastIndexInNewArray = oldLength;
newElements[ lastIndexInNewArray ] = e;
return newElements;
}
Below is an implementation of immutable stack in C#.
Pushing and popping give you back an entirely new stack, and Peek lets you look at the top of the stack without popping it.
Note that copying the entire stack is not necessary.
That is how immutable structures are implemented in any nontrivial cases. Nontrivial immutable structures are very useful in certain cases. Posters saying that this cannot be done are much misinformed.
The original code and more information can be found here:
https://blogs.msdn.microsoft.com/ericlippert/2007/12/04/immutability-in-c-part-two-a-simple-immutable-stack/
public interface IStack<T> : IEnumerable<T>
{
IStack<T> Push(T value);
IStack<T> Pop();
T Peek();
bool IsEmpty { get; }
}
public sealed class Stack<T> : IStack<T>
{
private sealed class EmptyStack : IStack<T>
{
public bool IsEmpty { get { return true; } }
public T Peek() { throw new Exception("Empty stack"); }
public IStack<T> Push(T value) { return new Stack<T>(value, this); }
public IStack<T> Pop() { throw new Exception("Empty stack"); }
public IEnumerator<T> GetEnumerator() { yield break; }
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
}
private static readonly EmptyStack empty = new EmptyStack();
public static IStack<T> Empty { get { return empty; } }
private readonly T head;
private readonly IStack<T> tail;
private Stack(T head, IStack<T> tail)
{
this.head = head;
this.tail = tail;
}
public bool IsEmpty { get { return false; } }
public T Peek() { return head; }
public IStack<T> Pop() { return tail; }
public IStack<T> Push(T value) { return new Stack<T>(value, this); }
public IEnumerator<T> GetEnumerator()
{
for(IStack<T> stack = this; !stack.IsEmpty ; stack = stack.Pop())
yield return stack.Peek();
}
IEnumerator IEnumerable.GetEnumerator() {return this.GetEnumerator();}
}

How to implement Iterable<E> in dart?

I still havn't understood how to deal with Iterable/Iterator in Dart.
I think I have to give up and simply return Lists but that's not what I want since it will
lead bad performance in my case.
What I want is to understand how to implement my own Iterable/Iterator.
Why do both of these attempts fail?
library foo;
import 'dart:collection';
// Both attemps below raises the following error:
// ==============================================
//
// Closure call with mismatched arguments: function 'moveNext'
//
// NoSuchMethodError: incorrect number of arguments passed to method named 'moveNext'
// Receiver: Closure: (dynamic) => Iterator<int> from Function 'iterator':.
// Tried calling: moveNext()
main() {
Iterable<int> iterable1 = new OddsIterableDartStyle([1,2,4,6,7,8,9]);
for (int i in iterable1)
print("ODD: $i");
Iterable<int> iterable2 = new OddsIterableJavaStyle([1,2,4,6,7,8,9]);
for (int i in iterable2)
print("ODD: $i");
}
// ------------------------------------------
class OddsIterableDartStyle extends Object with IterableMixin<int> {
List<int> _ints;
OddsIterableDartStyle(this._ints);
Iterator<int> iterator() {
return new OddsIterator(this);
}
}
// ------------------------------------------
class OddsIterableJavaStyle implements Iterable<int> {
List<int> _ints;
OddsIterableJavaStyle(this._ints);
Iterator<int> iterator() {
return new OddsIterator(this);
}
}
// ------------------------------------------
class OddsIterator implements Iterator<int> { // Iterate over odd numbers
List<int> _ints;
int _index;
OddsIterator(this._ints) {
_index = -1;
}
bool moveNext() {
while (++_index < _ints.length) {
if (_ints[_index].isOdd)
return true;
}
return false;
}
int get current => (_index < 0) ? null : _ints[_index];
}
I see two immediate problems:
iterator is a getter. The code shouldn't read Iterator<int> iterator() { ... }, it should be Iterator<int> get iterator { ... } instead.
Your iterators are expecting the underlying integer lists, but you are passing in the wrapper. You probably want to construct your iterator like new OddsIterator(_ints), not like new OddsIterator(this).
Btw, Iterator is supposed to return null if you call current and you have already moved beyond the end.
class Count extends Iterable with Iterator {
Count([this.limit = 10]);
int limit;
int i = 0;
#override
int get current => i;
#override
bool moveNext() {
i++;
return i <= limit;
}
#override
Iterator get iterator => this;
}

Resources