How to implement a function to return the sum of squares in the proposed form?

Asked

Viewed 1,247 times

0

I did not understand the proposal here. The whole question is in the Commoner, by the statement, I understand to be a delegate. See, they do not need to post codes, I would like only one way to follow. Below the statement. The whole part marked with the code tag is the statement, including the texts. Make a function that returns the sum of the squares I’ve done and it’s working, but I need now the form proposed by this exercise.

function acumular(combiner, nullValue, list)
{
    if (list.length == 0) {
        return nullValue;
    }
    var primeiro = list.removePrimeiro();
    return combiner(primeiro, acumular (combiner, nullValue, list));
}

Implemente a função somaDeQuadrados que retorna a soma de quadrados de uma lista.

somaDeQuadrados([1,2,3,4,5])
retorna o número 55.

Neste caso a função acumular deve ser utilizada. A variável “combiner” é um “ponteiro para função”. A implementação da função “combiner” faz parte da solução.

What I really need is a path, not a code, because I want to do it, like I’ve done all the others.

My big doubt is in the implementation of Combine. I didn’t fully understand what dcastro posted. If someone understood or dcastro itself, can, thank you with any additional help.

My biggest difficulty is in the implementation of the Accumulate function, because it receives an argument of the type of a method (Combiner). My Combiner method is thus implemented:

private int Combiner(int primeiro, int acc)
        {
            acc += primeiro * primeiro;

            return acc;
        }

And the method accumulate I’m getting it like this:

public int acumular(int combiner, int? nullValue, List<int> list)
        {            
            if (list.Count == 0)
                return 0;
            var primeiro = list.First();
            list.RemoveAt(0);

            return Combiner(primeiro, acumular(Combiner(primeiro,1),null,list));
        }

Return 0 is out of the proposed and the parameters in the recursive call to accumulate.

I thought I was wrong, but it worked out the sum of the squares of the form above. I made the call like this:

int[] inteiros = {1,2,3,4,5,6,7};
List<int> lista = new List<int>(inteiros);
lblFat.Text = f.acumular(1,null,lista).ToString();

As there was already the array, I just assign the array to the list, not to be filled in, so it has array and list in the call, but the call does not go to the test.

  • This isn’t exactly in C#, is it? I think it would be nice to edit the question and leave it all in C#. I see no problem to answer objectively, with code. See also if this answer helps you.

  • @Ciganomorrisonmendez, the question is exactly there, to pass to the C#.

  • @pnet I updated my reply with corrections to your current code.

2 answers

3


acumular is a function that traverses a list, from left to right, and that goes calling the function combine passing 2 arguments:

  1. The value currently under examination
  2. The accumulator of the rest of the list

Therefore, combiner must have the following signature:

int combine(int x, int acc)

In the end, she’ll be called like this:

combine(1, combine(2, combine(3, combine(4, combine(5, nullValue)))))

I think these tips should be enough to solve the exercise.

(Note: this function acumular is usually called foldRight / fold in functional programming languages, or Aggregate in the specific case of C#)


Update

Some things wrong with your current code:

  1. the parameter combiner of function acumular should be a pointer to a function (as stated in the statement), not a int. So he must have been the type Func<int, int, int> - that is to say, combiner is a delegate who accepts two integers and returns another integer.
  2. nullValue and' of the type int, not int?
  3. The value of nullValue is not null - I think the parameter name has been misspelled. The value of nullValue is the whole that will be combined with the 5 right at the start. Which integer do you think should be?
  4. The last line of the function acumular is wrong: you cannot call the function Combiner, only the delegate combiner.
  5. In fact, the last line of the function acumular can be copied from the statement without changes: return combiner(primeiro, acumular (combiner, nullValue, list))

If you still have questions, I can put the full answer here, but I think you can get there with just these hints ;)


Solution

public int Acumular(Func<int, int, int> combiner, int nullValue, List<int> list)
{            
    if (list.Count == 0)
        return 0;

    var primeiro = list.First();
    list.RemoveAt(0);

    return combiner(primeiro, Acumular(combiner, nullValue, list));
}

public int Combiner(int x, int acumulador)
{
    return (x*x) + acumulador;    
}

var list = new List<int> {1,2,3,4,5};

Acumular(Combiner, 0, list);

Like combiner will be called recursively, so it will be called so:

combiner(1, combiner(2, combiner(3, combiner(4, combiner(5, nullValue)))))

Replacing combiner by formula x*x + acumulador, and nullValue by 0:

1*1 + (2*2 + (3*3 + (4*4 + (5*5 + 0))))

Which is equal to 55

Fiddle: https://dotnetfiddle.net/ljkCu5

  • I didn’t understand the way you put the call to combine.

  • 1

    @pnet thinks of the notation of a mathematical formula, ex: 1 + (2 + (3 + (5 + x))). I mean, first you’ll be called combine(5, nullValue). The result of this call will be passed to another call combine(4, resultadoAnterior), and so on.

  • 1

    @pnet Yes, that’s it. Try to imagine what the execution of the function would be like acumular if you pass the list as argument [1,2,3,4,5]. Try writing on paper, and keep track of the call stack. Note that it works acumular is recursive - in the end, it will call combine(5, nullValue), and will return the result. Then, this result will be combined with 4, then with the 3, etc.

  • Show, dcastro. Now I think I understand what to do. I will start doing. Today is my last day to deliver and only two more methods to finish. The rest I’ve done.

  • @pnet put the solution

  • It worked, dcastro, on the fly. Thank you really.

Show 1 more comment

2

You can also use a online function

    List<int> list = new List<int> {1,2,3,4,5};

Using the proposed list:

    Func<List<int>, int> Qd = null;
    Qd = 
        x => 
        (x.Count == 0) ? 0 : x.Last() * x.Last() + Qd(x.Take(x.Count-1).ToList<int>());


    var resultado = Qd(list);

Still using Linq

    Func<List<int>, int> Qd = 
        x => 
        x.Select(i => i*i).Sum();
    var resultado = Qd(list);

Using the function passage, as proposed by the statement

    Func<Func<int, int, int>, List<int>, int> Qd = null;
    Qd = 
        (a, c) => 
        (c.Count == 0) ? 0 : a(c.Last(), Qd(a, c.Take(c.Count-1).ToList<int>()));
    Func<int, int, int> QdS = 
        (a, b) => 
        b + (a*a);

    //neste caso a chamada deve ser feita assim:
    var resultado = Qd(QdS, list);

The two examples are in the Dotnetfiddle

  • Po, this way also worked. There are many paths to be followed, rs.

  • This does not answer the question. The object of the exercise was to use the functional approach fold. As @pnet said, "Make a function that returns the sum of the squares I’ve done and it’s working, but I need now the form proposed by this exercise."

  • Now you must respond to the statement. Thank you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.