V
V
Vasily2020-05-28 22:09:21
Algorithms
Vasily, 2020-05-28 22:09:21

Determine that the elements of one collection are the square roots of another?

Whether prompt it is possible to write more optimum algorithm. The task goes like this:


We need to check that everything in the squares collection is the square root of the numbers in the numbers collection. The collections are sorted in ascending order and have no negative values.

update : if the collections are of different lengths, then we consider this as false

Examples of input data and answers:
IN: {1, 2}, {1, 4} OUT: TRUE

IN: {1, 3, 5}, {1, 9, 25, 25} OUT: FALSE



Function signature:
bool TestForSquares(IEnumerable<int> numbers, IEnumerable<int> squares)


My decision:

public static bool TestForSquares(IEnumerable<int> numbers, IEnumerable<int> squares) {
    var isFirstIteration = true;
    var numbersEnumerator = numbers.GetEnumerator();
    var squaresEnumerator = squares.GetEnumerator();

    while (true) {
        bool numberHasNext = numbersEnumerator.MoveNext();
        bool squareHasNext = squaresEnumerator.MoveNext();

        if(numberHasNext != squareHasNext) {
            // случай когда две коллекции имеют разный размер

            return false;
        }

        if(!numberHasNext && !squareHasNext) {

            if (isFirstIteration) {
                // случай когда две коллекции пусты
                return false;
            }

            break;
        }

        var testData = numbersEnumerator.Current * numbersEnumerator.Current;
        if(testData != squaresEnumerator.Current) {
            return false;
        }

        isFirstIteration = false;
    }

    return true;
}


ps

Also interested in a solution with the same optimality but not so verbose.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
L
Lynn "Coffee Man", 2020-05-29
@VasyaM13221

Disclaimer: I don't write in C# so mistakes are possible, but the idea is simple, you should use foreach.
This function will return true if both collections are empty.

public static bool TestForSquares(IEnumerable<int> numbers, IEnumerable<int> squares) {
    var squaresEnumerator = squares.GetEnumerator();

    foreach(int number in numbers) {
        if(!squaresEnumerator.MoveNext()) {
            // в squares закончились элементы, а в numbers ещё нет
            return false;
        }

        if(number * number != squaresEnumerator.Current) {
            return false;
        }
    }

    if(squaresEnumerator.MoveNext()) {
        // в squares ещё остались элементы, а в numbers уже всё закончилось
        return false;
    }

    return true;
}

G
Griboks, 2020-05-28
@Griboks

If we are talking about the optimal length of the code, then you can use something like this:

bool TestForSquares(IEnumerable<int> numbers, IEnumerable<int> squares) =>  numbers.Count == squares.Count && squares.Select(x=>x*x).All(x=>numbers.Contains(x));

Taking into account the edits of the task and comments.

F
freeExec, 2020-05-29
@freeExec

The task of working with sets.

static bool TestSet(IEnumerable<int> numbers, IEnumerable<int> squares)
{
    var ns = new HashSet<int>(numbers.Select(n => (int)Math.Round(Math.Sqrt(n))));
    return ns.IsSupersetOf(squares);
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question