Java solution - beats 98%
Intuition\nThe problem says that if the input passed is a number n(say 5), we need to print all the numbers from 1 to n, each number should be separated by a 0.
# Intuition\nThe problem says that if the input passed is a number n(say 5), we need to print all the numbers from 1 to n, each number should be separated by a 0.\n(n=5 ==> 0102030405)\nWe need to implement three functions, zero(), even() and odd() to print each number from this series 0102030405 using inter-thread communication.\n\n\n# Approach 1\n## Simple approach using synchronized block\nWe can take two exrta variables, one `currentNumber` to keep track of numbers from 1 to n, and another `currentNumberToBePrinted` that stores the number which currently needs to be printed (for instance if `currentNumber` is 1, we first need to print 0, so we set `currentNumberToBePrinted=0` first, let the zero function print 0 and set the value for `currentNumberToBePrinted` to the next number to be printed, and signal the other threads to continue). <br>\n\nSimilarly odd function busy waits till the `currentNumberToBePrinted` is odd, prints the `currentNumberToBePrinted` and increments it.\n\n\n# Code\n```\nclass ZeroEvenOdd {\n    private int n;\n    private int currentNumberToBePrinted;\n    private int currentNumber;\n    \n    public ZeroEvenOdd(int n) {\n        this.n = n;\n        this.currentNumber = 1;\n        this.currentNumberToBePrinted = 0;\n    }\n\n    // printNumber.accept(x) outputs "x", where x is an integer.\n    public void zero(IntConsumer printNumber) throws InterruptedException {\n        while (currentNumber <= n) {\n            synchronized (this) {\n                while (currentNumberToBePrinted != 0) {\n                    wait();\n                }\n\n                if (currentNumber <= n) {\n                    printNumber.accept(0);\n                }\n                currentNumberToBePrinted = currentNumber;   \n                \n                \n                notifyAll();\n            }\n        }\n    }\n\n    public void even(IntConsumer printNumber) throws InterruptedException {\n        while (currentNumber <= n) {\n            synchronized (this) {\n                while (currentNumberToBePrinted == 0 || currentNumberToBePrinted%2 != 0) {\n                    wait();\n                }\n\n                if (currentNumberToBePrinted <= n) {\n                    printNumber.accept(currentNumberToBePrinted);\n                }\n                this.currentNumber += 1;\n                currentNumberToBePrinted = 0;\n                \n\n                notifyAll();\n            }\n        }\n    }\n\n    public void odd(IntConsumer printNumber) throws InterruptedException {\n        while (currentNumber <= n) {\n            synchronized (this) {\n                while (currentNumberToBePrinted == 0 || currentNumberToBePrinted %2 == 0) {\n                    wait();\n                }\n\n\n                if (currentNumberToBePrinted <= n) {\n                    printNumber.accept(currentNumberToBePrinted);\n                }\n                this.currentNumber += 1;\n                currentNumberToBePrinted = 0;\n                \n\n                notifyAll();\n            }\n        }\n    }\n}\n```\n\n# Approach 2\n## Using Reentrant lock and semaphore\nThe overall operating logic for this soluion remains same as of approach 1. <br>\nThis solution makes use of mutex lock and condition variable.\n\nEfficiency wise this solution will be little more efficient than the above as here we have created three condition variables, one each for even, odd and zero.  <br>\n\nUnlike the above solution where we use notifyAll() to signal all the waiting therads to take the monitor and continue, there we have a chance that the current number is even, but odd function gets the CPU.\n\nThis solution solves that problem by using signal() method with the specific condition variable to signal the specific waiting thread (odd or even).\n\nCode is self explanatory.\n\n# Code\n```\nclass ZeroEvenOdd {\n    private int n;\n    private int currentNumberToBePrinted;\n    private int currentNumber;\n\n    private Lock lock = new ReentrantLock();\n    private Condition semZero = lock.newCondition();\n    private Condition semEven = lock.newCondition();\n    private Condition semOdd = lock.newCondition();\n\n    public ZeroEvenOdd(int n) {\n        this.n = n;\n        this.currentNumber = 1;\n        this.currentNumberToBePrinted = 0;\n    }\n\n    // printNumber.accept(x) outputs "x", where x is an integer.\n    public void zero(IntConsumer printNumber) throws InterruptedException {\n        lock.lock();\n        while (currentNumber <= n) {\n            while (currentNumberToBePrinted != 0) {\n                semZero.await();\n            }\n\n            if (currentNumber <= n) {\n                printNumber.accept(0);\n            }\n            currentNumberToBePrinted = currentNumber;\n\n            if (currentNumber %2 == 0) {\n                semEven.signal();\n            } else {\n                semOdd.signal();\n            }\n        }\n        lock.unlock();\n    }\n\n    public void even(IntConsumer printNumber) throws InterruptedException {\n        lock.lock();\n        while (currentNumber <= n) {\n            while (currentNumberToBePrinted == 0 || currentNumberToBePrinted%2 != 0) {\n                semEven.await();\n            }\n\n            if (currentNumberToBePrinted <= n) {\n                printNumber.accept(currentNumberToBePrinted);\n            }\n            this.currentNumber += 1;\n            currentNumberToBePrinted = 0;\n\n\n            semZero.signal();\n        }\n        lock.unlock();\n    }\n\n    public void odd(IntConsumer printNumber) throws InterruptedException {\n        lock.lock();\n        while (currentNumber <= n) {\n            while (currentNumberToBePrinted == 0 || currentNumberToBePrinted %2 == 0) {\n                semOdd.await();\n            }\n\n\n            if (currentNumberToBePrinted <= n) {\n                printNumber.accept(currentNumberToBePrinted);\n            }\n            this.currentNumber += 1;\n            currentNumberToBePrinted = 0;\n\n\n            semZero.signal();\n        }\n        lock.unlock();\n    }\n}\n```
['Concurrency', 'Java']