Question

I have to implement class Incrementer and it suppose to implement Iterable.

The output should be:

1 2 3 4 5 6 7 8 9 10 
1 3 5 7 9 
10 9 8 7 6 5 4 3 2 1 
10 9 8 7 6 5 4 3 2 1 
1 2 3 4 6 8 10 
1 2 3 4 5 6 7 8 6 4 2 
10 9 8 7 6 5 6 7 8 9 10

I do get:

2 3 4 5 6 7 8 9 10 
3 5 7 9 11 
9 8 7 6 5 4 3 2 1 

2 3 4 6 8 10 
2 3 4 5 6 7 8 
9 8 7 6 5 6 7 8 9 10 

My Incrementer class looks like that:

    package in;

import java.util.Iterator;

public class Incrementer implements Iterable<Integer> {
    int val, step, a, b;

    private Incrementer(int a, int b, int step) {
        this.step = step;
        this.a = a;
        this.b = b;
        if (step > 0)
            val = a;
        else
            val = b;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {

            @Override
            public boolean hasNext() {
                if (step < 0 && val > a)
                    return true;
                else if (step > 0 && val < b)
                    return true;
                return false;
            }

            @Override
            public Integer next() {
                return val += step;
            }

            @Override
            public void remove() {
            }
        };
    }

    public static Incrementer in(int a, int b) {
        ///tu zmieniamy tresc dla ostatniego przypadku

        if (a < b)
            return new Incrementer(a, b, 1);
        else
            return new Incrementer(b, a, -1);
    }

    public Incrementer by(int step) {
        this.step = step;
        if (this.step < 0 && this.a < this.b || this.step > 0 && this.a > this.b) {
            int tmp = this.a;
            this.a = this.b;
            this.b = tmp;
        }
        return this;
    }

}

and the Testcode:

package in;
import static in.Incrementer.*;

public class Test {

  public static void main(String[] args) {

    for(int k : in(1, 10)) System.out.print(k + " ");
    System.out.println();


    for(int k : in(1, 10).by(2)) System.out.print(k + " ");
    System.out.println();

    for(int k : in(10, 1)) System.out.print(k + " ");
    System.out.println();

    for(int k : in(1, 10).by(-1)) System.out.print(k + " ");
    System.out.println();

    Incrementer inc;
    for (int i : inc = in(1,10) ) {
      if (i == 4) inc.by(2);
      System.out.print(i + " ");
    }
    System.out.println();
    for (int i : inc = in(1,10) ) {
      if (i == 8) inc.by(-2);
      System.out.print(i + " ");
    }
    System.out.println();
    for(int k : inc = in(10, 1)) {
      if (k == 5) inc.by(1);
      System.out.print(k + " ");
    }

  }


}

I do not know where I did mistake.

Was it helpful?

Solution

The mistake is that you doesn't initialize val, so it will start at 0 (the default value).

In your second example, you will return val += step;, with val = 0 and step = 2, so it will start at 2 and continue from there.

In your third example, a = 10, b = 1, step = -1 and val = 0, so you will not enter in

if (step < 0 && val > a)

because val < a, and you will not enter in

else if (step > 0 && val < b)

because step < 0.

EDIT:

In the edited post, you should modify the next() method to return val, and only increase it after :

@Override
public Integer next() {
    int ret = val;
    val += step;
    return val;
}

You should also modify the conditions in the hasNext():

@Override
public boolean hasNext() {
    if (step < 0 && val >= a)
        return true;
    else if (step > 0 && val <= b)
        return true;
    return false;
}

To make you fourth test work, you will have to change the by() method to invert a and b if needed:

public Incrementer by(int step) {
    if ((this.step<0)!=(step<0) && this.val==this.a)
        this.val = this.b;
    else if ((this.step<0)!=(step<0) && this.val==this.b) 
        this.val = this.a;
    else if (this.val!=this.a && this.val!=this.b) {
        this.val -= this.step;
        this.val += step;
    }
    this.step = step;

    return this;
}

You can also test the inverse case:

for(int k : in(10, 1).by(1)) System.out.print(k + " ");

Here is the complete code:

public class Incrementer implements Iterable<Integer> {
    int val, step, a, b;

    private Incrementer(int a, int b, int step) {
        this.step = step;
        this.a = a;
        this.b = b;
        if (step > 0)
            val = a;
        else
            val = b;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {

            @Override
            public boolean hasNext() {
                if (step < 0 && val >= a)
                    return true;
                else if (step > 0 && val <= b)
                    return true;
                return false;
            }

            @Override
            public Integer next() {
                int ret = val;
                val += step;
                return ret;
            }

            @Override
            public void remove() {
            }
        };
    }

    public static Incrementer in(int a, int b) {
        ///tu zmieniamy tresc dla ostatniego przypadku

        if (a < b)
            return new Incrementer(a, b, 1);
        else
            return new Incrementer(b, a, -1);
    }

    public Incrementer by(int step) {
        if ((this.step<0)!=(step<0) && this.val==this.a)
            this.val = this.b;
        else if ((this.step<0)!=(step<0) && this.val==this.b)
            this.val = this.a;
        else if (this.val!=this.a && this.val!=this.b) {
            this.val -= this.step;
            this.val += step;
        }
        this.step = step;

        return this;
    }

}

OTHER TIPS

You make one fundamental mistake to begin with: an Iterable is supposed to be able to issue infinitely many Iterators, but you can only issue one.

Each Iterator should have sufficient internal state so that it can be able to iterate over your set of values.

To fix this and your other problem at the same time, change your code to this in iterator():

@Override
public Iterator<Integer> iterator() {
    return new Iterator<Integer>() {
        int val = a; // <-- HERE

and change your .next() to:

public Integer next()
{
    int ret = val;
    val += step;
    return ret;
}

and remove your other val.

(also, I'd suggest you rename a to start and b to end)


Final remark: in order to fully obey the contract of Iterator, your .remove() should do that:

public void remove()
{
    throw new UnsupportedOperationException();
}

And no, you don't need to declare that the method throws this exception since it is an unchecked exception. See javadoc for RuntimeException.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top