Home > front end >  I can't think of a condition to increase the decrement in Gradually Decreasing Carousel app
I can't think of a condition to increase the decrement in Gradually Decreasing Carousel app

Time:04-04

Decrementing Carousel is a container, accepting int elements. DecrementingCarousel has a maximum capacity, specified via the constructor. When created, DecrementingCarousel is in accumulating state: you may add elements via the addElement method and can produce a CarouselRun object via the run method. Once the run method is called, DecrementingCarousel is in running state: it refuses adding more elements.

The CarouselRun allows to iterate over elements of the carousel decrementing them one by one with the next method. The next returns the value of the current element.

The CarouselRun iterates over elements in the order of their insertion. When an element is decreased to zero, the CarouselRun will skip it in further iterations. When there are no more elements available for decrementing, the CarouselRun returns -1.

The CarouselRun also has the isFinished method, which indicates, if the carousel has run out of the lements to decrement.

Specification Details

boolean addElement(int element) - adds an element. If element is negative or zero, do not add the element. If container is full, do not add the element. If the run method was called to create a CarouselRun, do not add the element. If element is added successfully, return true. Return false otherwise. CarouselRun run() - returns a CarouselRun to iterate over the elements. If the run method has already been called earlier, it must return null: DecrementingCarousel may generate only one CarouselRun object.

CarouselRun has two public methods:

int next() - returns the current value of the current element, then decreases the current element by one and switches to the next element in insertion order. Skips zero elements. When there is no more elements to decrease, returns -1. boolean isFinished() - when there is no more elements to decrease, returns true. Otherwise, returns false. The code:

public class DecrementingCarousel {
    private final int capacity;
    static int[] carousel;
    int index;
    boolean isRun;

    {
        index = 0;
        isRun = false;
    }

    public DecrementingCarousel(int capacity) {
        this.capacity = capacity;
        carousel = new int[capacity];
    }

    public boolean addElement(int element){
        if (element > 0 && index < capacity && !isRun) {
            carousel[index  ] = element;
            return true;
        }
        return false;
    }

    public CarouselRun run() {
        if (!isRun) {
            isRun = true;
            return new CarouselRun();
        }
        return null;
    }
}

Methods in CarouselRun:

public class CarouselRun {
    protected final int[] array = DecrementingCarousel.carousel.clone();
    protected int position = 0;

    public int next() {
        if (isFinished())
            return -1;
        else {
            while (array[position %= array.length] <= 0) {
                position  ;
            }
        }
        return array[position  ]--;
    }

    public boolean isFinished() {
        for (int el : array)
            if (el > 0)
                return false;
        return true;
    }
}

So this subclass must decrement elements by gradually increasing decrement. When you need to decrement an element for the first time, decrease it by 1. Next time you need to decrement the same element, decrease it by 2. Next time decrease by 3, then by 4 and so on.

public class GraduallyDecreasingCarousel extends DecrementingCarousel{
    public GraduallyDecreasingCarousel(final int capacity) {
        super(capacity);
    }

    @Override
    public CarouselRun run() {
        if (!isRun) {
            isRun = true;
            return new GraduallyDecreasingCarouselRun();
        }
        return null;
    }
}

public class GraduallyDecreasingCarouselRun extends CarouselRun {
    int decrement = 1;

    @Override
    public int next() {
        int beforeDecreasing;
        if (isFinished())
            return -1;
        else {
            while (array[position %= array.length] <= 0) {
                position  ;
                if (position == array.length) {
                    decrement  ;
                }
            }
        }
        beforeDecreasing = array[position];
        array[position  ] -= decrement;
        return beforeDecreasing;
    }

The main method:

public class Main {
    public static void main(String[] args) {
        DecrementingCarousel carousel = new GraduallyDecreasingCarousel(7);

        carousel.addElement(20);
        carousel.addElement(30);
        carousel.addElement(10);

        CarouselRun run = carousel.run();

        System.out.println(run.isFinished()); //false

        System.out.println(run.next()); //20
        System.out.println(run.next()); //30
        System.out.println(run.next()); //10

        System.out.println(">>>>>>>>>>");

        System.out.println(run.next()); //19
        System.out.println(run.next()); //29
        System.out.println(run.next()); //9

        System.out.println(">>>>>>>>>>");

        System.out.println(run.next()); //17
        System.out.println(run.next()); //27
        System.out.println(run.next()); //7

        System.out.println(">>>>>>>>>>");

        System.out.println(run.next()); //14
        System.out.println(run.next()); //24
        System.out.println(run.next()); //4

        System.out.println(">>>>>>>>>>");

        System.out.println(run.next()); //10
        System.out.println(run.next()); //20

        System.out.println(">>>>>>>>>>");

        System.out.println(run.next()); //5
        System.out.println(run.next()); //15

        System.out.println(">>>>>>>>>>");

        System.out.println(run.next()); //9

        System.out.println(">>>>>>>>>>");

        System.out.println(run.next()); //2

        System.out.println(run.isFinished()); //true
        System.out.println(run.next()); //-1
    }
}

it works fine in main but wont pass the tests IDK how to change next method in GraduallyDecreasingCarouselRun

tried counting next calls and reset the counter when its greater than amount of elements to decrease but when theres one element left its wasnt working correctly

CodePudding user response:

Wow. Needed a really long time to fully understand the problem. The problem occurs when you fill the capacity of your array completely.

In that case your check for incrementing the value of decrease inside the while loop can fail, because the modulo assignment will "reset" the position to 0 without going inside the loop and therefore skipping the increment of decrease.

The solution to make the code understandable easier would be to decouple the modulo assignment from the while condition. This is slower and uses more code, but makes it easier to understand and also handles position as the "next" position like stated in the specification. Optimizations are possible, but I just post the unoptimized code here:

public int next() {
    int beforeDecreasing;
    if (isFinished())
        return -1;
    else {
        beforeDecreasing = array[position];
        array[position] -= decrement;
        do {
            position  ;
            if (position == array.length) {
                decrement  ;
                position = 0;
            }
        } while ((array[position] <= 0) && !isFinished());
    }
    return beforeDecreasing;
}

CodePudding user response:

For a "quick win" I would suggest another solution: change the place and check for the increment of decrease: (only snippet from inside the else branch)

int oldPosition = position;
while (array[position %= array.length] <= 0) {
    position  ;
}
if (oldPosition > position) {
    decrement  ;
}
  • Related