Wednesday, 31 October 2018

Go Puzzles

Here are a few puzzles intended to help you round out your knowledge of the Go programming language.

Background

In 1983 I had read my copy of K&R from cover to cover (twice I think) and believed I knew everything there was to know about C. I thought K&R (The C Programming Language by Kernighan and Ritchie) was the only book on C that existed but one day I came across another - the C Puzzle Book by Alan Feuer. I bought it and soon discovered that I knew very little about C - such as the myriad possibilities for undefined behavior.

Luckily Go has greatly limited the prospects of undefined behavior. However, I still think there is room for a selection of puzzles to test your knowledge of the language. Most of puzzles below are the result of discovering something I didn't know in my reading of the excellent "Go Programming Language" by Donovan and Kernighan.

The questions are in no particular order but I tried to start with easy ones. Don't worry if you get most of them wrong as some are pretty obscure - I'd get a few wrong myself even though I wrote them all!

The Questions

For brevity most of the puzzles only provide a snippet of Go code. In which case, you can assume that the code is wrapped in a main() function with all relevant imports added.
  1. m := map[string]int{"": 0}
    mcopy := m
    mcopy["1"] = 1
    mcopy["0"] = 0
    mcopy[""] = 1

    print(len(m))

    What does this print?
    a.  1
    b.  2
    c.  3
    d.  4
     
  2. s := []int{1, 2, 3, 4}
    copy(s, []int{42})
    fmt.Println(s)

    What does this print?
    a.  [42]
    b.  [42 1 2 3 4]
    c.  [1 2 3 4 42]
    d.  [42 2 3 4]
     
  3. defer func() {
      defer func() {
        fmt.Print(recover())
      }()
      fmt.Print(recover())
      panic("DEF")
    }()
    panic("ABC")

    What does this print?
    a.  ABC
    b.  DEF
    c.  ABCDEF
    d.  <nil>
     
  4. c := 'c'
    print(strings.IndexFunc("abcdefg", func(r rune) bool {
      return r == c
    }))

    What does this print?
    a.  -1
    b.  2
    c.  3
    d.  compile error: undefined: c
     
  5. s := "世界"
    fmt.Println(len(s), len([]byte(s)))

    What does this print?
    a.  2 2
    b.  6 2
    c.  6 6
    d.  2 6
     
  6. func init() {
      i = make(chan int, 2)
      i <- 1
    }

    var i chan int

    func init() {
      i <- 2
    }

    func main() {
      fmt.Println(<-i)
    }

    What does this print?
    a.  1
    b.  2
    c.  prints nothing and never terminates
    d.  compilation error: init redeclared in this block
     
  7. const (
     a = iota
     b
     c
     d
    )
    fmt.Println(a+b+c+d)

    What does this print?
    a.  0
    b.  4
    c.  6
    d.  10
     
  8. a := [...]int{41, 42, 43, 44, 45}
    s := a[1:2]
    copy(s, []int{1, 2, 3})
    fmt.Println(a[2])

    What does this print?
    a.  2
    b.  3
    c.  42
    d.  43
     
  9. m := map[int]int{1: 1, 2: 2}
    for k := range m {
      if k == 1 {
        delete(m, k)
      }
      fmt.Print(k, len(m), " ")
    }

    What does this print?
    a.  1 1
    b.  1 1 2 1
    c.  2 2 1 1
    d.  either b or c
     
  10. a := []int{0, 1, 2, 3, 4}
    b := a[0:2:4]
    fmt.Println(cap(b) - len(b))

    What does this print?
    a.  0
    b.  2
    c.  3
    d.  4
     
  11. var wg sync.WaitGroup
    wg.Add(1)
    go func(wg sync.WaitGroup) {
      wg.Wait()
      print("A")
    }(wg)
    wg.Done()
    print("B")

    What does this print?
    a.  AB
    b.  B
    c.  BA
    d.  any one of the above
     
  12. i, f := 200, 2e2
    x, y, z := 200+2e2, 200+f, i+2e2
    fmt.Printf("%T %T %T", x, y, z)

    What does this print?
    a.  int float64 int
    b.  float64 float64 int
    c.  float64 float64 float64
    d.  None of the above
     
  13. s := []int{1, 2, 3}[1:2]
    t := append(s, 4, 5, 6)
    fmt.Println(len(s), cap(t))

    What does this print?
    a.  1 4
    b.  2 5
    c.  4 4
    d.  4 6
     
  14. const idx = 2
    a := [...]int{idx: 1, idx+1: 2}
    fmt.Println(a[3])

    What does this print?
    a.  0
    b.  1
    c.  2
    d.  compilation error: invalid array index 3
     
  15. a := 1
    var b interface{} = a
    a = 2
    fmt.Println(b)

    What does this print?
    a.  1
    b.  2
    c.  (interface {})(1)
    d.  (interface {})(2)
     
  16. const (
       a = 0
       b
       c = iota
       d
    )
    fmt.Println(a+b+c+d)

    What does this print?
    a.  1
    b.  2
    c.  5
    d.  6
     
  17. a := [...]int{1, 2}
    _ = append(a[:1], 3)
    _ = append(a[:1], 4, 5)
    fmt.Println(a[1])

    What does this print?
    a.  0
    b.  2
    c.  3
    d.  4
     
  18. s := bytes.NewBufferString("string")
    a := s.String()
    b := s.Bytes()
    m := make(map[interface{}]int)
    m[a] = 1
    m[b] = 2
    log.Println(m[a])

    What does this print?
    a.  1
    b.  2
    c.  compile error: invalid map key
    d.  panics at run-time
     
  19. m := make(map[int]*struct{ i int })
    m[3] = &struct{ i int }{1}
    v := m[3]
    v.i++
    fmt.Println(m[3].i)

    What does this print?
    a.  0
    b.  1
    c.  2
    d.  3
     
  20. a := time.Now().Year
    b, _ := strconv.Atoi(time.Now().Format("06"))
    fmt.Println(b - a())

    What does this print?
    a.  6
    b.  0
    c.  -2000
    d.  18 (current year this century)
     
  21. i := 2
    switch i {
    case 2:
       if i % 2 == 0 {
          fallthrough
       }
       i = 6
    case 3:
       i++
       fallthrough
    default:
       i++
    }
    print(i)

    What does this print?
    a.  4
    b.  5
    c.  6
    d.  compile error: fallthrough statement out of place
     
  22. s := []int{10, 12, 14}
    for _, v := range s {
       v++
    }
    fmt.Println(s[1])

    What does this print?
    a.  11
    b.  12
    c.  13
    d.  14
     
  23. s := []int{1, 2, 3, 4}
    t := make([]int, 2, 3)
    copy(t, s)
    fmt.Println(t)

    What does this print?
    a.  [1 2]
    b.  [1 2 3]
    c.  [1 2 3 4]
    d.  [0 0 3 4]
  24. a := struct{}{}
    b := struct{}{}
    fmt.Printf("%t", &a == &b)

    What does this print?
    a.  false
    b.  true
    c.  bool
    d.  the exact behaviour of this code is undefined
     
  25. var a, b interface{}
    a = "str" + "ing"
    b = "string"
    m := make(map[interface{}]int)
    m[a] = 1
    m[b] = 2
    print(m[a])

    What does this print?
    a.  0
    b.  1
    c.  2
    d.  compile error: invalid map key
     
  26. var t interface{} = 1
    switch t := t.(type) {
    case int, uint:
       fmt.Println(reflect.TypeOf(&t))
    default:
       print("default")
    }

    What does this print?
    a.  *int
    b.  *uint
    c.  default
    d.  *interface{}
     
  27. fmt.Printf("%q\n", string(65))

    What does this print?
    a.  "65"
    b.  "A"
    c.  "\x41"
    d.  "�"
     
  28. const i1, i2, i3 = 2, 3, 2
    a := [...]int{i1: i1, i2: i2, i3: i3}
    print(len(a))

    What does this print?
    a.  2
    b.  3
    c.  4
    d.  compile error: duplicate index in array literal: 2
     
  29. type intA int
    type intB = int
    var a intA = 1
    var b intB = 2
    print(int(a) | b)

    What does this print?
    a.  0
    b.  1
    c.  3
    d.  compile error: invalid operation: int(a) | b (mismatched types int and intB)
     
  30. ctx, cancel := context.WithCancel(context.Background())
    cancel()
    fmt.Println(ctx.Err())

    What does this print?
    a.  <nil>
    b.  deadline exceeded
    c.  context canceled
    d.  does not print anything but causes a panic at run-time
     
  31. const (
       a, b = iota, iota
       c, d = iota+1, iota+2
    )
    print(a+b+c+d)

    What does this print?
    a.  5
    b.  6
    c.  7
    d.  9
     
  32. var a, b interface{}
    a = "main"
    b = main
    fmt.Printf("%t\n", a == b)

    What does this print?
    a.  false
    b.  true
    c.  compile error: invalid interface type
    d.  panics at run-time
     
  33. fmt.Printf("%q", "A\xbc")

    What does this print?
    a.  "A\xbc"
    b.  A
    c.  A�
    d.  "Abc"
     

2 comments:

  1. Where are the answers?

    ReplyDelete
  2. Answers (with explanation) coming soon - stay tuned.

    ReplyDelete