CyberSpy

Rantings from a guy with way too much free time

Getting func(y) with Channels

Here's a little golang puzzle

Take a look at the function below that computes a mystery value for the function $f(x)$. Any idea what the function is? Take a close look at the first line where we create a channel. Notice that the channel isn't some boring int or string channel. No, this is a channel of type func(int, chan int, chan bool). Wait what??? That's right, this channel takes a function that takes an integer and two channels as function parameters. We define such a function, x, right aftewards.

func mystery(n int) int {

        fc := make(chan func(int, chan int, chan bool), 1)

        x := func(v int, pipe chan int, done chan bool) {
                if v > (n - 1) {
                        done <- true
                }
                pipe <- (v)
        }

        done := make(chan bool, 1)
        pipe := make(chan int, n)

        fc <- x

        go func(fc chan func(int, chan int, chan bool), pipe chan int, done chan bool) {
                start := 0
                for {
                        f := <-fc
                        f(start, pipe, done)
                        fc <- f
                        start++
                }
        }(fc, pipe, done)

        <-done

        var sigma int = 0
        for {
                var y int
                var ok bool
                select {
                case y, ok = <-pipe:
                        sigma += y
                default:
                        fmt.Printf("empty pipe, break\n")
                        break
                }

                if ok {
                } else {
                        fmt.Printf("sigma = %d\n", sigma)
                        break
                }
        }

		return sigma
}

Still stumped on the composition of $f(x)$? Answer:

$$\text{ }f(x) = \sum_{n=0}^n{\frac{n(n+1)}{2}} $$

Bonus question, how would you modify the code above to compute:

$$\text{ }f(x) = \sum_{n=0}^n{\frac{n(n+1)(2n+1)}{6}} $$

hint: we could refactor the code to make a function that transforms our $x$ value.

func mystery(n int, fx func(int) int) int {

        fc := make(chan func(int, chan int, chan bool), 1)

        x := func(v int, pipe chan int, done chan bool) {
                if v > (n - 1) {
                        done <- true
                }
                pipe <- (v)
        }

        done := make(chan bool, 1)
        pipe := make(chan int, n)

        fc <- x

        go func(fc chan func(int, chan int, chan bool), pipe chan int, done chan bool) {
                start := 0
                for {
                        f := <-fc
                        f(start, pipe, done)
                        fc <- f
                        start++
                }
        }(fc, pipe, done)

        <-done

        var sigma int = 0
        for {
                var y int
                var ok bool
                select {
                case y, ok = <-pipe:
                        sigma += fx(y)
                default:
                        fmt.Printf("empty pipe, break\n")
                        break
                }

                if ok {
                } else {
                        fmt.Printf("sigma = %d\n", sigma)
                        break
                }
        }

		return sigma
}
comments powered by Disqus