5

I've been set a challenge that I'm trying to get my head around, but am struggling with the best (or 'correct') way to implement it. The challenge is to create a simple console app written in Go that calculates the sum of squares of n numbers. However, I must do so without using a for loop and only the standard library.

Having never touched Go before this point, I assumed it would just be a case of using a while loop, yet after digging through the docs I know that functionality in Go is folded into the for statement. No luck there then.

I also know that Go implements goto statements which seem would be an option but in my ~2 years of programming, I've been taught to avoid them like the plague as they're 'terrible form' and only hang around for a few specific cases, thus I cannot imagine that this challenge is looking for me to come up with a goto statement.

While I know that Go has some more complex flow control functionality that I haven't mentioned, I haven't come across anything obvious that would replicate the functionality that I'd get from a simple for loop.

What conceptually can replicate a for loop in go?

8
  • 1
    Are you familiar with the concept of Recursion? gobyexample.com/recursion
    – KChaloux
    Mar 29, 2016 at 13:01
  • 4
    "Theoretical" questions often are on-topic here. My guess is the downvotes are either because 1) it sounds kind of like a code-writing question which is off-topic here 2) when a problem has artificial constraints like "I can't use for because I don't want to" it's usually a very uninteresting problem 3) the alternative solution is a trivial "use recursion" and nothing else. But personally I don't see the need to downvote this, just post the (admittedly trivial and uninteresting) answer then move on.
    – Ixrec
    Mar 29, 2016 at 13:22
  • 1
    I just made a short edit to the question to hopefully make it better scoped. I think this is on topic and well written. It might help to edit your question to include some examples however as it would be a bit more clear what specifically you have tried and are interested in doing.
    – enderland
    Mar 29, 2016 at 13:25
  • 1
    @Ixrec the way you explain it probably even an answer isn't needed, it was likely been asked and answered in prior questions, eg Is there anything that can be done with recursion that can't be done with loops?
    – gnat
    Mar 29, 2016 at 13:27
  • 1
    One alternative in Go is to use channels and goroutines, although that's not something that I'd expect from someone that has "never touched Go before this point." Was this an interview question?
    – kdgregory
    Mar 29, 2016 at 14:56

6 Answers 6

6

Usually challenges like this are intended to either test or teach you the unique idioms of a language or its standard library. Usually the answer would be fairly short, elegant, or at least clever if done "correctly" but tedious and ugly otherwise. For example, this problem solved in idiomatic Scala is:

input.map(x => x*x).sum

Therefore, I would stay away from the solutions, like "just use recursion," that are applicable to any language, and look for things that are unique to Go, like channels and goroutines, and keep refining your solution until it is as easy to understand as a for loop, provided you are familiar with the language. Then you will have learned quite a bit about how to use Go to its own best advantage.

1
  • 1
    This is a fair approach, which is more practical than mine. I brought up the concept of recursion because I believe it's an important one to understand, and to have in your toolbox. I do agree however that in a practical scenario that it's important to know what methods of flow control are idiomatic to your specific language (for example, Ruby has a for loop, but you almost always want to use .each {|x| ...} instead)
    – KChaloux
    Mar 29, 2016 at 20:40
2

I'm not familiar with Go as a language, but I briefly checked it out, and it does support Recursion. If your language supports recursion (and most do), you can implement looping behavior without ever explicitly using a loop.

Recursion is performed when a function makes a call to itself, usually operating on some subset of the original data passed in. Using pseudocode, you could calculate the sums of the squares of a list of numbers this way:

def calculateSquareSums (values : [Int]):
  if values is empty: // This is our 'base case' - it stops the function from recursing
    return 0
  else:
    square : Int = values[0] * values[0]       // Get the square of the first value
    rest : [Int] = values[1..]                 // Get the remaining values
    return square + calculateSquareSums(rest)  // Recursively call this function to process the remaining values

If you were to pass this function a list of values, say [7, 5, 8, 2] it would act as though it had expanded to ((7*7) + ((5*5) + ((8*8) + ((2*2) + 0)))).

Recursion is an extremely powerful concept that has a lot of applications, especially in divide-and-conquer type algorithms. However, it has some downsides and stipulations depending on the language you're using.

  • In many languages, each recursive call pushes a new Stack Frame, meaning that recursive functions that have a lot of calls may cause a Stack Overflow Exception. Some languages can optimize this away for certain cases.
  • Recursive functions can be harder to wrap your head around than simple loops, as you mentally have to keep track of the state going into each call.
1

I do not know the Go language.

If there is or if you can create a function in Go that is the equivalent of JavaScript’s setInterval and clearInterval then it is possible to find the sum of the squares of n numbers using them instead of using any type of for-loop construct. I do not know if this is the best solution. However it is a solution I would accept.

If you have access to a user-interface library within the Go language, it is also possible to find the sum of the squares of n number using events triggered by the user via mouse or keyboard clicks. For every click, the square of a number is added to a running total.

Recursion would be another way of computing the sum of squares of n numbers. However if every function call includes a dynamic allocation of computer memory then recursion would be a poor choice when n is large.

As a demonstration, I created an form-based app instead of a console-based app. The app uses JavaScript's setInterval and clearInterval functions. An input text field is used to enter the array of numbers to process. Another textfield is used to display the sum. If you are interested, the app is a dynamic, interactive diagram in the following PDF document: http://www.aespen.ca/AEnswers/VYJLj1459603849.pdf.

0

Calculate the sum of squares of n numbers in Go without using a for loop.


In Go, you can use computation or recursion.


For example,

package main

import "fmt"

// Computation.
// OEIS: A000330  Square pyramidal numbers:
// a(n) = 0^2 + 1^2 + 2^2 + ... + n^2 = n*(n+1)*(2*n+1)/6.
// 0, 1, 5, 14, 30, 55, 91, 140, 204, 285
// https://oeis.org/A000330
func sumN2C(n int) int {
    return n * (n + 1) * (2*n + 1) / 6
}

// Recursion.
func sumN2R(n int) int {
    if n <= 1 {
        if n == 1 {
            return n
        }
        return 0
    }
    return (n * n) + sumN2R(n-1)
}

func main() {
    for n := 0; n < 10; n++ {
        fmt.Println(n, sumN2C(n), sumN2R(n))
    }
}

Go Playground: https://play.golang.org/p/Tw9yV0duUiG

Output:

0 0 0
1 1 1
2 5 5
3 14 14
4 30 30
5 55 55
6 91 91
7 140 140
8 204 204
9 285 285
0

Discovering recursion may have been the real intent of the challenge, but I think if you're explicitly forbidden from using for but not forbidden from using goto, then yes, use goto.

The reason goto is "bad" is because structured alternatives like for exist. But for the purpose of the challenge, for doesn't exist, so goto is a perfectly suitable substitute. Bear in mind that goto in Go has some caveats that goto in C/C++ don't (as of this writing), which are:

  • "Executing the goto statement must not cause any variables to come into scope that were not already in scope at the point of the goto"
  • "A goto statement outside a block cannot jump to a label inside that block"

These constraints still allow you to make perfectly serviceable loops in Go without using for, such as:

func main() {
    i := 0
loop:
    fmt.Println(i)
    i += 1
    if i < 10 {
        goto loop
    }
}

which does the same thing as

func main() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
    }
}

Who knows, maybe the point of the challenge was to reverse engineer how unstructured programming worked (if only in a fairly simple way).

0

Here is your code. No loop, no arrays. It works!

package main

import (
    "fmt"
    "strconv"
)

var sum = 0
var final = ""

func inputR(R int) {
    if R == 0 {
        return
    }
    var num int
    fmt.Scanln(&num)
    inputR(R - 1)
    if num > 0 {
        sum += num * num
    }
}

func inputT(T int) {
    if T == 0 {
        return
    }
    var R int
    fmt.Scanln(&R)
    sum = 0
    inputR(R)
    final += strconv.Itoa(sum) + "\n"
    inputT(T - 1)
}

func main() {
    var T int
    fmt.Scanln(&T)
    inputT(T)
    fmt.Print(final)
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.