Open In App

Cyclic Iterator for K variable length vectors

Given K vectors, the task is to design a cyclic iterator that prints the elements of these vectors in a cyclic manner. For example: v1 = {1, 2, 3}, v2 = {4, 5, 6} and v3 = {7, 8, 9} then the output should be 1, 4, 7, 2, 5, 8, 3, 6 and 9. Examples:

Input: v1 = {1, 2}, v2 = {3, 4, 5}, v3 = {6} 
Output: 1 3 6 2 4 5 

Input: v1 = {1, 2}, v2 = {3, 4} 
Output: 1 3 2 4

Approach: Create two arrays, one will store the begin iterators of each vector and other will store the end iterators of each vector. Then print the contents of vectors in a cyclic manner. Since the vectors can be of variable lengths, so skip the vectors all of whose elements have already been printed. 

Below is the implementation of the above approach: 




// C++ implementation of the approach
#include& lt; bits / stdc++.h & gt;
using namespace std;
 
// Class for the cyclic iterator
class Iterator {
public:
    Iterator(vector& lt; int& gt; & a1, vector& lt;
             int& gt; & a2, vector& lt; int& gt; &
             a3, vector& lt; int& gt; & a4, int k);
    int numOfVectors;
    int currIndex;
 
    // Vectors to store the starting and the
    // ending iterators for each of the vector
    vector& lt;
    vector& lt;
    int& gt;
    ::iterator& gt;
    iStart;
    vector& lt;
    vector& lt;
    int& gt;
    ::iterator& gt;
    iEnd;
 
    // Function that returns true if
    // there are elements left to print
    bool hasNext();
 
    // Function that returns the next
    // element in a cyclic manner
    int next();
};
 
// Function that returns true if
// there are elements left to print
bool Iterator::hasNext()
{
 
    // If iterator of any vector has not
    // reached the end then return true
    for (int i = 0; i & lt; numOfVectors; i++) {
        if (iStart[i] != iEnd[i])
            return true;
    }
    return false;
}
 
// Function that returns the next
// element in a cyclic manner
int Iterator::next()
{
    int elem = 0;
    if (iStart[currIndex] != iEnd[currIndex]) {
        elem = *iStart[currIndex]++;
        currIndex = (currIndex + 1) % numOfVectors;
        return elem;
    }
    else {
        currIndex = (currIndex + 1) % numOfVectors;
        return next();
    }
    return elem;
}
 
// Initialise object of the Iterator class
Iterator::Iterator(vector& lt; int& gt; &
                   a1, vector& lt; int& gt; &
                   a2, vector& lt; int& gt; &
                   a3, vector& lt; int& gt; & a4, int k)
{
    numOfVectors = k;
    iStart.resize(numOfVectors);
    iEnd.resize(numOfVectors);
 
    // Store begin iterators
    iStart[0] = a1.begin();
    iStart[1] = a2.begin();
    iStart[2] = a3.begin();
    iStart[3] = a4.begin();
 
    // Store ending iterators
    iEnd[0] = a1.end();
    iEnd[1] = a2.end();
    iEnd[2] = a3.end();
    iEnd[3] = a4.end();
 
    // CurrIndex denotes the vector's index
    // whose element is to be printed next
    currIndex = 0;
}
 
// Function to print the elements in a cyclic manner
void iterateCyclic(vector& lt; int& gt; &
                   a1, vector& lt; int& gt; &
                   a2, vector& lt; int& gt; &
                   a3, vector& lt; int& gt; & a4, int k)
{
 
    // Initialise the iterator
    Iterator it(a1, a2, a3, a4, k);
 
    // Print all the element
    // in a cyclic fashion
    while (it.hasNext()) {
        cout& lt;
        <
        it.next() & lt;
        <
        "
        "
        ;
    }
}
 
// Driver code
int main()
{
    // Initialize the vectors
    vector& lt;
    int& gt;
    a1;
    a1.push_back(1);
    a1.push_back(2);
    a1.push_back(3);
 
    vector& lt;
    int& gt;
    a2;
    a2.push_back(4);
    a2.push_back(5);
    a2.push_back(6);
    a2.push_back(7);
 
    vector& lt;
    int& gt;
    a3;
    a3.push_back(8);
    a3.push_back(9);
 
    vector& lt;
    int& gt;
    a4;
    a4.push_back(10);
    a4.push_back(11);
 
    // Print the elements in a cyclic fashion
    iterateCyclic(a1, a2, a3, a4, 4);
 
    return 0;
}




// ArrayIterator class for cyclic iteration over multiple arrays
class ArrayIterator {
    // Number of vectors (arrays)
    private int numOfVectors;
 
    // Array of iterators for each vector
    private java.util.Iterator<Integer>[] iterators;
 
    // Array of last elements for each vector
    private int[] ends;
 
    // Current index to track the active vector
    private int currIndex;
 
    // Constructor to initialize the iterator with arrays
    // and the number of arrays (k)
    public ArrayIterator(int[] a1, int[] a2, int[] a3, int[] a4, int k) {
        // Number of vectors (arrays)
        this.numOfVectors = k;
 
        // Array of iterators for each vector
        this.iterators = new java.util.Iterator[numOfVectors];
        this.iterators[0] = java.util.Arrays.stream(a1).iterator();
        this.iterators[1] = java.util.Arrays.stream(a2).iterator();
        this.iterators[2] = java.util.Arrays.stream(a3).iterator();
        this.iterators[3] = java.util.Arrays.stream(a4).iterator();
 
        // Array of last elements for each vector
        this.ends = new int[]{a1[a1.length - 1], a2[a2.length - 1], a3[a3.length - 1], a4[a4.length - 1]};
 
        // Current index to track the active vector
        this.currIndex = 0;
    }
 
    // Function to check if there are more elements left in any vector
    public boolean hasNext() {
        for (int i = 0; i < numOfVectors; i++) {
            if (iterators[i].hasNext()) {
                return true;
            }
        }
        return false;
    }
 
    // Function to get the next element in a cyclic manner
    public int next() {
        int elem = 0;
        if (iterators[currIndex].hasNext()) {
            // Get the next element from the current vector
            elem = iterators[currIndex].next();
 
            // If the current element is the last element
            // of the vector, mark it as done
            if (elem == ends[currIndex]) {
                iterators[currIndex] = java.util.Collections.emptyIterator();
            }
 
            // Move to the next vector in a cyclic manner
            currIndex = (currIndex + 1) % numOfVectors;
 
            return elem;
        } else {
            // If the current vector is done, move to the next vector
            currIndex = (currIndex + 1) % numOfVectors;
 
            // Recursively call next to get the element from the next vector
            return next();
        }
    }
}
 
// Function to iterate over vectors cyclically
class Main {
    public static void iterateCyclic(int[] a1, int[] a2, int[] a3, int[] a4, int k) {
        // Create an instance of the ArrayIterator class
        ArrayIterator it = new ArrayIterator(a1, a2, a3, a4, k);
 
        // Iterate and print elements in a cyclic fashion
        // until there are no more elements
        while (it.hasNext()) {
            System.out.print(it.next() + " ");
        }
    }
 
    public static void main(String[] args) {
        // Sample input arrays
        int[] a1 = {1, 2, 3};
        int[] a2 = {4, 5, 6, 7};
        int[] a3 = {8, 9};
        int[] a4 = {10, 11};
 
        // Call the iterateCyclic function with the
        // sample arrays and the number of arrays (4)
        iterateCyclic(a1, a2, a3, a4, 4);
    }
}




class Iterator:
    def __init__(self, a1, a2, a3, a4, k):
        self.numOfVectors = k
        self.iStart = []
        self.iEnd = []
 
        # Store begin iterators
        self.iStart.append(iter(a1))
        self.iStart.append(iter(a2))
        self.iStart.append(iter(a3))
        self.iStart.append(iter(a4))
 
        # Store ending iterators
        self.iEnd.append(a1[-1])
        self.iEnd.append(a2[-1])
        self.iEnd.append(a3[-1])
        self.iEnd.append(a4[-1])
 
        # CurrIndex denotes the vector's index
        # whose element is to be printed next
        self.currIndex = 0
 
    # Function that returns true if
    # there are elements left to print
    def hasNext(self):
 
        # If iterator of any vector has not
        # reached the end then return true
        for i in range(self.numOfVectors):
            if self.iStart[i] != self.iEnd[i]:
                return True
        return False
 
    # Function that returns the next
    # element in a cyclic manner
    def next(self):
        elem = 0
        if self.iStart[self.currIndex] != self.iEnd[self.currIndex]:
            elem = next(self.iStart[self.currIndex])
            self.currIndex = (self.currIndex + 1) % self.numOfVectors
            return elem
        else:
            self.currIndex = (self.currIndex + 1) % self.numOfVectors
            return self.next()
 
def iterateCyclic(a1, a2, a3, a4, k):
    # Initialise the iterator
    it = Iterator(a1, a2, a3, a4, k)
 
    # Print all the element
    # in a cyclic fashion
    while True:
        try:
            print(it.next(), end=' ')
        except StopIteration:
            break
    print()
     
# Driver code
a1 = [1, 2, 3]
a2 = [4, 5, 6, 7]
a3 = [8, 9]
a4 = [10, 11]
 
# Print the elements in a cyclic fashion
iterateCyclic(a1, a2, a3, a4, 4)




using System;
using System.Collections.Generic;
 
// Class for the cyclic iterator
public class Iterator
{
    private int numOfVectors;
    private int currIndex;
    private List<IEnumerator<int>> iStart;
    private List<int> iEnd;
 
    // Constructor
    public Iterator(List<int> a1, List<int> a2, List<int> a3, List<int> a4, int k)
    {
        numOfVectors = k;
        iStart = new List<IEnumerator<int>>(numOfVectors);
        iEnd = new List<int>(numOfVectors);
 
        // Store begin iterators
        iStart.Add(a1.GetEnumerator());
        iStart.Add(a2.GetEnumerator());
        iStart.Add(a3.GetEnumerator());
        iStart.Add(a4.GetEnumerator());
 
        // Store ending iterators (last element of each vector)
        iEnd.Add(a1[a1.Count - 1]);
        iEnd.Add(a2[a2.Count - 1]);
        iEnd.Add(a3[a3.Count - 1]);
        iEnd.Add(a4[a4.Count - 1]);
 
        // CurrIndex denotes the vector's index
        // whose element is to be printed next
        currIndex = 0;
    }
 
    // Function that returns true if
    // there are elements left to print
    public bool HasNext()
    {
        // If iterator of any vector has not
        // reached the end then return true
        for (int i = 0; i < numOfVectors; i++)
        {
            if (iStart[i].Current != iEnd[i])
                return true;
        }
        return false;
    }
 
    // Function that returns the next
    // element in a cyclic manner
    public int Next()
    {
        int elem = 0;
        if (iStart[currIndex].Current != iEnd[currIndex])
        {
            elem = iStart[currIndex].Current;
            iStart[currIndex].MoveNext();
            currIndex = (currIndex + 1) % numOfVectors;
            return elem;
        }
        else
        {
            currIndex = (currIndex + 1) % numOfVectors;
            return Next();
        }
    }
}
 
public class Solution
{
    // Function to print the elements in a cyclic manner
    public static void IterateCyclic(List<int> a1, List<int> a2,
                                     List<int> a3, List<int> a4, int k)
    {
        // Initialize the iterator
        Iterator it = new Iterator(a1, a2, a3, a4, k);
 
        // Print all the elements in a cyclic fashion
        while (it.HasNext())
        {
            Console.Write(it.Next() + " ");
        }
        Console.WriteLine();
    }
 
    // Driver code
    public static void Main()
    {
        // Initialize the vectors
        List<int> a1 = new List<int> { 1, 2, 3 };
        List<int> a2 = new List<int> { 4, 5, 6, 7 };
        List<int> a3 = new List<int> { 8, 9 };
        List<int> a4 = new List<int> { 10, 11 };
 
        // Print the elements in a cyclic fashion
        IterateCyclic(a1, a2, a3, a4, 4);
    }
}




// Iterator class for cyclic iteration over multiple arrays
class Iterator {
    // Constructor to initialize the iterator with arrays
    // and the number of arrays (k)
    constructor(a1, a2, a3, a4, k) {
        // Number of vectors (arrays)
        this.numOfVectors = k;
 
        // Array of iterators for each vector
        this.iterators = [
            a1[Symbol.iterator](),
            a2[Symbol.iterator](),
            a3[Symbol.iterator](),
            a4[Symbol.iterator]()
        ];
 
        // Array of last elements for each vector
        this.ends = [a1[a1.length - 1], a2[a2.length - 1], a3[a3.length - 1], a4[a4.length - 1]];
 
        // Current index to track the active vector
        this.currIndex = 0;
    }
 
    // Function to check if there are more elements left in any vector
    hasNext() {
        for (let i = 0; i < this.numOfVectors; i++) {
            if (!this.iterators[i].done) {
                return true;
            }
        }
        return false;
    }
 
    // Function to get the next element in a cyclic manner
    next() {
        let elem = 0;
        if (!this.iterators[this.currIndex].done) {
            // Get the next element from the current vector
            elem = this.iterators[this.currIndex].next().value;
 
            // If the current element is the last element
            // of the vector, mark it as done
            if (elem === this.ends[this.currIndex]) {
                this.iterators[this.currIndex].done = true;
            }
 
            // Move to the next vector in a cyclic manner
            this.currIndex = (this.currIndex + 1) % this.numOfVectors;
 
            return elem;
        } else {
            // If the current vector is done, move to the next vector
            this.currIndex = (this.currIndex + 1) % this.numOfVectors;
 
            // Recursively call next to get the element from the next vector
            return this.next();
        }
    }
}
 
// Function to iterate over vectors cyclically
function iterateCyclic(a1, a2, a3, a4, k) {
    // Create an instance of the Iterator class
    const it = new Iterator(a1, a2, a3, a4, k);
 
    // Iterate and print elements in a cyclic fashion
    // until there are no more elements
    while (it.hasNext()) {
        process.stdout.write(it.next() + ' ');
    }
}
 
// Sample input arrays
const a1 = [1, 2, 3];
const a2 = [4, 5, 6, 7];
const a3 = [8, 9];
const a4 = [10, 11];
 
// Call the iterateCyclic function with the
// sample arrays and the number of arrays (4)
iterateCyclic(a1, a2, a3, a4, 4);

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





Time Complexity: O(N), where N is the total number of elements of all the vectors combined.
Auxiliary Space: O(M), where M is the total number of vectors.


Article Tags :