Tracks
/
Go
Go
/
Exercises
/
Chessboard
Chessboard

Chessboard

Learning Exercise

Introduction

In Go, you can iterate over a slice using for and an index, or you can use range. range also allows you to iterate over a map.

Every iteration returns two values: the index/key and a copy of the element at that index/key.

Iterate over a slice

Easy as pie, loops over a slice, ordered as expected.

xi := []int{10, 20, 30}
for i, x := range xi {
  fmt.Println(i, x)
}
// outputs:
// 0, 10
// 1, 20
// 2, 30

Iterate over a map

Iterating over a map raises a new problem. The order is now random.

hash := map[int]int{9: 10, 99: 20, 999: 30}
for k, v := range hash {
  fmt.Println(k, v)
}
// outputs, for example:
// 99 20
// 999 30
// 9 10
Note

It may seem the above output is incorrect, as one would expect the first key/value pair on the declaration of the map 9 10 to be the first one printed and not the last. However, maps are unordered by nature - there isn't a first or last key/value pair. Because of that, when iterating over the entries of a map, the order by which entries will be visited will be random and not follow any specific pattern. This means the above output is possible but might differ from what you get if you try to run this yourself. To learn more about this see Go Language Spec: range clause.

Iteration omitting key or value

In Go an unused variable will raise an error at build time. Sometimes you only need the value, as per the first example:

xi := []int{10, 20, 30}
for i, x := range xi {
  fmt.Println(x)
}
// Go build failed: i declared but not used

You can replace the i with _ which tells the compiler we don't use that value:

xi := []int{10, 20, 30}
for _, x := range xi {
  fmt.Println(x)
}
// outputs:
// 10
// 20
// 30

If you want to only print the index, you can replace the x with _, or simply omit the declaration:

xi := []int{10, 20, 30}
// for i, _ := range xi {
for i := range xi {
  fmt.Println(i)
}
// outputs:
// 0
// 1
// 2

Defining Types

A type definition creates a new named type, distinct from every other type, even one with the same underlying type.

type File []bool

File here refers to a single vertical column on a chessboard, commonly labeled A to H. Each square in this column is represented by a Boolean value marking whether it's occupied or not. Now that File is defined, we can use it inside other definitions:

type Chessboard map[string]File

board := Chessboard{
    "A": File{true, false, true},
    "B": File{false, true, false},
}

Chessboard maps file identifiers to File values. Each File is a slice of Booleans representing the squares in one chess file. Without these type definitions, board would be a map[string][]bool, which would make it harder to understand what we're representing.

Instructions

As a chess enthusiast, you would like to write your own version of the game. Yes, there may be plenty of implementations of chess available online already, but yours will be unique!

Each square of the chessboard is identified by a letter-number pair:

  • The horizontal rows of squares, called ranks, are numbered 1 through 8.
  • The vertical columns of squares, called files, are labeled A through H.
   A B C D E F G H
 8 # _ _ _ # _ _ # 8
 7 _ _ _ _ _ _ _ _ 7
 6 _ _ _ _ # _ _ # 6
 5 _ # _ _ _ _ _ # 5
 4 _ _ _ _ _ _ # # 4
 3 # _ # _ _ _ _ # 3
 2 _ _ _ _ _ _ _ # 2
 1 # _ _ _ _ _ _ # 1
   A B C D E F G H

1. Given a Chessboard and a File, count how many squares are occupied

Implement the CountInFile(board Chessboard, file string) int function. It should count the total number of occupied squares by ranging over a map. Return an integer. Return a count of zero (0) if the given file cannot be found in the map.

CountInFile(board, "A")
// => 3

2. Given a Chessboard and a Rank, count how many squares are occupied

Implement the CountInRank(board Chessboard, rank int) int function. It should count the total number of occupied squares by ranging over the given rank. Return an integer. Return a count of zero (0) if the given rank is not a valid one (not between 1 and 8, inclusive).

CountInRank(board, 2)
// => 1

3. Count how many squares are present in the given chessboard

Implement the CountAll(board Chessboard) int function. It should count how many squares are present in the chessboard and returns an integer. Since you don't need to check the content of the squares, consider using range omitting both index and value.

CountAll(board)
// => 64

4. Count how many squares are occupied in the given chessboard

Implement the CountOccupied(board Chessboard) int function. It should count how many squares are occupied in the chessboard. Return an integer.

CountOccupied(board)
// => 15
Edit via GitHub The link opens in a new window or tab
Go Exercism

Ready to start Chessboard?

Sign up to Exercism to learn and master Go with 34 concepts166 exercises, and real human mentoring, all for free.