Coding Odyssey: Embarking on a Matrix Adventure with Go
Published: 2023-12-04 22:16:41

Hey everyone! 👋 I just wrapped up a coding exercise that was quite the brain teaser, and it took me a **solid three days** to crack it. What was the challenge, you ask? Well, it was all about matrices! Buckle up as I walk you through the entire process of creating, analyzing, and tweaking matrices using the power of Go.

###The Matrix Unveiled 🧮

Let's start at the basics. If you're not familiar with what a matrix is, don't worry—I got you covered. A matrix is like a big rectangular table filled with numbers, letters, words, or symbols, neatly arranged in rows and columns. Here's a quick visual:

```markdown
    1  2  3  4
  |------------
1 | 5  8  7  9
2 | 3  1  4  6
3 | 4  6  7  4
4 | 5  6  3  2
```
In this example, each number has an address: (row, column). So, if I want the number at (2, 3), I'd get 4. Easy, right?

##The Matrix Code 🚀

Now, let's dive into the nitty-gritty of the code. First things first, I had to define a custom type:

`type Matrix [][]int`

This custom type sets the stage for the four functions that make up the core of this coding adventure:

###1. New: Creating the Matrix
The New function takes a string and transforms it into a matrix. The string must follow this specific format:


`"1 2 3\n4 5 6\n7 8 9"`

Each "row" is separated by \n, and the numbers within each row are the columns. Check out the code snippet:

```go
func New(s string) (Matrix, error) {
    lines := strings.Split(s, "\n")
    matrix := make(Matrix, len(lines))

    for i, line := range lines {
        // Parse each line to create a row
        numbers := strings.Split(strings.TrimSpace(line), " ")
        row := make([]int, len(numbers))

        for j, number := range numbers {
            val, err := strconv.Atoi(number)
            if err != nil {
                return nil, err
            }
            row[j] = val
        }

        if i > 0 && len(row) != len(matrix[i-1]) {
            return nil, fmt.Errorf("uneven rows")
        }

        matrix[i] = row
    }
```

This code ensures that the string is parsed correctly, and the matrix is constructed without any uneven rows.

###2. Cols: Unveiling the Columns
The Cols method takes a matrix as a parameter and returns its columns in a neat [][]int format. Check out how I tackled this one:

```go
func (m Matrix) Cols() [][]int {

    cols := make([][]int, len(m[0]))
    
    for i := 0; i < len(m[0]); i++ {
        cols[i] = make([]int, 0)
    }
    
    for i := 0; i < len(m); i++ {
        for j := 0; j < len(m[i]); j++ {
            cols[j] = append(cols[j], m[i][j])
        }
    }

    

    return cols
}
```

This snippet cleverly transposes the matrix, turning rows into columns.

###3. Rows: Fetching the Rows
The Rows method takes a matrix and returns its rows. Simple and sweet:

```go
func (m Matrix) Rows() [][]int {
    rows := make([][]int, len(m))
    
    for i := 0; i < len(m); i++ {
        rows[i] = append(rows[i], m[i]...)
    }

    return rows
}
```

This code snippet efficiently copies the rows from the original matrix.

###4. Set: Making Changes
The Set method allows you to change a specific value in the matrix. Just provide the row, column, and the new value:

```go
func (m Matrix) Set(row, col, val int) bool {
	if row >= len(m) || row < 0 || col >= len(m[row]) || col < 0 {
        return false
    }

    m[row][col] = val

    return m[row][col] == val
}
```

This snippet ensures that you're not venturing outside the matrix boundaries and updates the value accordingly.

Here you have a snap of the code all putted down together for you to enjoy:

```go
import (
    "fmt"
    "strconv"
    "strings"
)

type Matrix [][]int

func New(s string) (Matrix, error) {
	lines := strings.Split(s, "\n")
	matrix := make(Matrix, len(lines))

	for i, line := range lines {
		numbers := strings.Split(strings.TrimSpace(line), " ")
		row := make([]int, len(numbers))

		for j, number := range numbers {
			val, err := strconv.Atoi(number)
			if err != nil {
				return nil, err
			}
			row[j] = val
		}

		if i > 0 && len(row) != len(matrix[i-1]) {
			return nil, fmt.Errorf("uneven rows")
		}

		matrix[i] = row
	}

	return matrix, nil
}
// Cols and Rows must return the results without affecting the matrix.
func (m Matrix) Cols() [][]int {

    cols := make([][]int, len(m[0]))
    
    for i := 0; i < len(m[0]); i++ {
        cols[i] = make([]int, 0)
    }
    
    for i := 0; i < len(m); i++ {
        for j := 0; j < len(m[i]); j++ {
            cols[j] = append(cols[j], m[i][j])
        }
    }

    

    return cols
}

func (m Matrix) Rows() [][]int {
    rows := make([][]int, len(m))
    
    for i := 0; i < len(m); i++ {
        rows[i] = append(rows[i], m[i]...)
    }

    return rows
}

func (m Matrix) Set(row, col, val int) bool {
	if row >= len(m) || row < 0 || col >= len(m[row]) || col < 0 {
        return false
    }

    m[row][col] = val

    return m[row][col] == val
}
```

And there you have it—a journey through the matrix! 🚀 If you're a coding enthusiast, give this exercise a shot and share your experience. Happy coding! 😊

I want to say thanks to my great buddy Andres and my dad that helped me go trough this exercise (otherwise it would had taken me longer) thank you both a lot.