search
HomeBackend DevelopmentGolangAdvent of Code Day n Golang: Searching XMAS and X-MAS

Introduction

Moving on to day 4, we have a grid problem in front of us, we are given some numbers in the form of a grid, i.e. some rows and columns with some upper case letters. What we need to do is to find is the word XMAS in any direction (up, left, down, right, diagonals), and in the second part we need to find the word MAS forming an X.

So, let’s see how we can approach this and solve it in golang.

You can check out my solutions here on GitHub.

Advent of Code Day n Golang: Searching XMAS and X-MAS Mr-Destructive / advent_of_code

Advent of Code

Constructing the grid

The most fundamental part of the problem lies in actually converting the text into a grid or a matrix form. We can split the lines, into individual lines and append each character as an element in a list, and that way we can have a list of list of strings which is a matrix or grid-like (2-dimensional) structure.

So, below is the input for the puzzle.

MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX

We need to convert it into something like this

[
    [M M M S X X M A S M]
    [M S A M X M S M S A]
    [A M X S X M A A M M]
    [M S A M A S M S M X]
    [X M A S A M X A M M]
    [X X A M M X X A M A]
    [S M S M S A S X S S]
    [S A X A M A S A A A]
    [M A M M M X M M M M]
    [M X M X A X M A S X]
]

So, this is a list of strings, we can say in golang it is a [][]string . We can do that by creating a function like this:

func ConstructGrid(lines []string) [][]string {
    grid := [][]string{}
    for _, line := range lines {
        row := []string{}
        for _, char := range strings.Split(line, "") {
            row = append(row, char)
        }
        grid = append(grid, row)
    }
    return grid
}

The above function takes in a list of strings and returns a list of list of strings that are individual letters in the grid.

We can read the file bytes and split the bytes on newline characters and then this will be used as the input for this function.

So, once the input is parsed into a grid, we can start thinking about the actual logic of finding the word XMAS in it.

Part 1

So, in the first part, we need to find the word XMAS in the matrix which could be appearing:

  • forwards (as XMAS)

  • backward (as SAMX)

  • upwards

            S
            A
            M
            X
  • downwards
            X
            M
            A
            S    
  • Diagonal upwards (right or up left)
            S
              A
                M
                  X

            OR
                  S
                A
              M 
            X
  • Diagonals downwards (right or left)
                     X
                   M
                 A
               S

            OR

            X
              M
                A
                  S

So, there are 8 directions where XMAS could appear in the grid, there could n number of these XMAS . We need to find the count of these in the grid.

Advent of Code Day n Golang: Searching XMAS and X-MAS

To approach this, we can either find the first character in the word XMAS and then search in all directions one by one and check if we find M and if we have found M in any of the directions, we keep moving ahead in that direction and check if there is A and S in that direction.

The approach looks like this:

  • Initialize the counter to 0

  • Iterate over each line

    • Iterate over each character in the line

      • Check if the character is equal to X
      • If the character is X→

        • Iterate over all the directions (up, down, right, left, up-left, up-right, down-left, down-right)

          • For that direction if we find the character to be M
          • Keep moving ahead in the same direction to find A and S similarly, if we found all the characters XMAS then, increment the counter
          • Else choose another direction in the loop

This looks complex and large but is simple, focus one thing at a time and you can solve this easily.

So, for the implementation of this, we need to define a few things first:

MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX

So, we have defined the list of integers in the directions which are the x and y coordinates that we need to add or subtract to get to the desired location. It is basically like a unit vector, it has a distance of 1 and a direction indicated by or - indicating to move the left or right for x coordinates and up and down for y c-ordinates.

So, let me explain that more clearly, let’s say I am at (1,2) in the grid which is of 4x4 dimension.

[
    [M M M S X X M A S M]
    [M S A M X M S M S A]
    [A M X S X M A A M M]
    [M S A M A S M S M X]
    [X M A S A M X A M M]
    [X X A M M X X A M A]
    [S M S M S A S X S S]
    [S A X A M A S A A A]
    [M A M M M X M M M M]
    [M X M X A X M A S X]
]

So, at 2,1 we have G , so we check some directions for this

up → 0,-1 → 2 0, 1-1 → 2,0, we have moved to C

right → 1,0 → 2 1, 1 0 → 3,1 , we have moved to H

down, left → -1,1 → 2-1, 1 1 → 1, 2, we have moved to J

So, you get the idea, that we are moving in some directions using these coordinates.

We can use these to get the next direction jump we want to make to find if that element has the next character in the word that we are searching.

We will write a function that does this first and abstract the function that checks if we have found the word in the grid.

func ConstructGrid(lines []string) [][]string {
    grid := [][]string{}
    for _, line := range lines {
        row := []string{}
        for _, char := range strings.Split(line, "") {
            row = append(row, char)
        }
        grid = append(grid, row)
    }
    return grid
}

The above function takes in a grid and returns an integer which will be the score i.e. the count of words XMAS found in the grid/matrix.

First, we need to iterate through each of the rows in the grid, for each row, we iterate over the character, so we will have x and y coordinates as the index of the grid. We need to then check if the current character is X or wordList[0] , if that is the case, we iterate over all the directions and check if we can find XMAS i.e. MAS in that direction, if so we increment the counter. What is the FindXMAS function, let’s abstract that away, and pass in the x, y, which are the coordinates of the current word, 1 which will be the word position of the XMAS and in this case, we already have found X we need to find MAS in that direction. We pass the grid and the direction, so this function will return true or false if that direction has MAS in it.

So to iterate:

  • We iterate over the grid and get row and x as the list of strings and index of the current row.

  • For each row i.e. list of strings, we iterate over the list of strings to get char and y as the character (string) and the index of that character in the list of the string.

  • If we find the current character to be equal to X which is the 0th index of the wordList then

    • We iterate over all the directions and call the function FindXMAS to check if the remaining word MAS in that direction
    • If we find all the words, we increment the counter.
  • So, we return the counter as we count the number of words XMAS in the grid/matrix.

Now, we can implement the FindXMAS function, that takes in a x, y coordinates, the wordPosition, the direction and the grid, and return if the word is found.

  • First, we take the current x coordinates and add the direction’s x component (0th index or first element)

  • add current y coordinates to the direction’s y component (1st index or second element)

  • if the word position i.e.. the word index or the word itself in the current function is equal to the wordList, it means that it has found the required word completely

  • We need to check by adding the direction to the x and y coordinates, we are not overshooting the width and height of the grid, so if we do, we return a false

  • The final if is for checking if the current character is equal to the word that we are looking for, it could be M, A , or S . If so, we return the recursively call the FindXMAS function by passing the updated x and y coordinates and the next word in the wordList, we keep the direction the same and pass the entire grid.

MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX

So, we have implemented the FindXMAS function, this will just return if we have found the MAS word by going in a particular direction by updating the coordinates and checking if the word at that position in the gird is the next word in MAS list.

So, this is what the entire first part looks like:

[
    [M M M S X X M A S M]
    [M S A M X M S M S A]
    [A M X S X M A A M M]
    [M S A M A S M S M X]
    [X M A S A M X A M M]
    [X X A M M X X A M A]
    [S M S M S A S X S S]
    [S A X A M A S A A A]
    [M A M M M X M M M M]
    [M X M X A X M A S X]
]

We take in the lines as a list of strings and pass that to ConstructGrid and get the grid, finally, we call TraverseGrid , by passing the grid and getting the score as the count of the words XMAS in the grid.

That’s it from the part 1.

Part 2

For part two, we need to find MAS in the cross shape, like below:

func ConstructGrid(lines []string) [][]string {
    grid := [][]string{}
    for _, line := range lines {
        row := []string{}
        for _, char := range strings.Split(line, "") {
            row = append(row, char)
        }
        grid = append(grid, row)
    }
    return grid
}

So, to solve this, we can do a similar approach but much simpler, we just need to find A as there will always be the word MAS in the center, so we just check if we have A and the top-left, top-right, or bottom-right, bottom-left has M or S .

We get the coordinates of the top-right, top-left positions, down-right, and down-left positions by adding and subtracting 1 from it. We make a basic check if we are not overshooting the boundary of the grid. If we overshoot the boundaries, we won’t find the MAS

But if we are within the grid, we now get the character at those 4 positions, we check if the top-left and bottom-right have M and S or S or M, similarly for top-right and bottom-left has M and S or S or M respectively. This is the diagonal search for M and S above and below the character A.

So, if we have both the diagonal matched we return true.

            S
            A
            M
            X

So, that is the simple implementation for finding the MAS the diagonal.

Now, we need to change the TraverseGrid a bit, as we just iterate over the grid, and check if we have A in the character in the row, i.e. wordList[2]. Now, if we have A, we need to call the FindMAS function with the current coordinates and the grid, if that function returns true, we increment the counter,.

MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX

So, that is the final implementation of part 2, we get the count of MAS in the cross direction.

You can check out my solutions here on GitHub.

Conclusion

So, that is it from day 4 of Advent of Code in Golang, let me know if you have any suggestions, and how you approached it. any better solutions?

Happy Coding :)

The above is the detailed content of Advent of Code Day n Golang: Searching XMAS and X-MAS. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Learn Go String Manipulation: Working with the 'strings' PackageLearn Go String Manipulation: Working with the 'strings' PackageMay 09, 2025 am 12:07 AM

Go's "strings" package provides rich features to make string operation efficient and simple. 1) Use strings.Contains() to check substrings. 2) strings.Split() can be used to parse data, but it should be used with caution to avoid performance problems. 3) strings.Join() is suitable for formatting strings, but for small datasets, looping = is more efficient. 4) For large strings, it is more efficient to build strings using strings.Builder.

Go: String Manipulation with the Standard 'strings' PackageGo: String Manipulation with the Standard 'strings' PackageMay 09, 2025 am 12:07 AM

Go uses the "strings" package for string operations. 1) Use strings.Join function to splice strings. 2) Use the strings.Contains function to find substrings. 3) Use the strings.Replace function to replace strings. These functions are efficient and easy to use and are suitable for various string processing tasks.

Mastering Byte Slice Manipulation with Go's 'bytes' Package: A Practical GuideMastering Byte Slice Manipulation with Go's 'bytes' Package: A Practical GuideMay 09, 2025 am 12:02 AM

ThebytespackageinGoisessentialforefficientbyteslicemanipulation,offeringfunctionslikeContains,Index,andReplaceforsearchingandmodifyingbinarydata.Itenhancesperformanceandcodereadability,makingitavitaltoolforhandlingbinarydata,networkprotocols,andfileI

Learn Go Binary Encoding/Decoding: Working with the 'encoding/binary' PackageLearn Go Binary Encoding/Decoding: Working with the 'encoding/binary' PackageMay 08, 2025 am 12:13 AM

Go uses the "encoding/binary" package for binary encoding and decoding. 1) This package provides binary.Write and binary.Read functions for writing and reading data. 2) Pay attention to choosing the correct endian (such as BigEndian or LittleEndian). 3) Data alignment and error handling are also key to ensure the correctness and performance of the data.

Go: Byte Slice Manipulation with the Standard 'bytes' PackageGo: Byte Slice Manipulation with the Standard 'bytes' PackageMay 08, 2025 am 12:09 AM

The"bytes"packageinGooffersefficientfunctionsformanipulatingbyteslices.1)Usebytes.Joinforconcatenatingslices,2)bytes.Bufferforincrementalwriting,3)bytes.Indexorbytes.IndexByteforsearching,4)bytes.Readerforreadinginchunks,and5)bytes.SplitNor

Go encoding/binary package: Optimizing performance for binary operationsGo encoding/binary package: Optimizing performance for binary operationsMay 08, 2025 am 12:06 AM

Theencoding/binarypackageinGoiseffectiveforoptimizingbinaryoperationsduetoitssupportforendiannessandefficientdatahandling.Toenhanceperformance:1)Usebinary.NativeEndianfornativeendiannesstoavoidbyteswapping.2)BatchReadandWriteoperationstoreduceI/Oover

Go bytes package: short reference and tipsGo bytes package: short reference and tipsMay 08, 2025 am 12:05 AM

Go's bytes package is mainly used to efficiently process byte slices. 1) Using bytes.Buffer can efficiently perform string splicing to avoid unnecessary memory allocation. 2) The bytes.Equal function is used to quickly compare byte slices. 3) The bytes.Index, bytes.Split and bytes.ReplaceAll functions can be used to search and manipulate byte slices, but performance issues need to be paid attention to.

Go bytes package: practical examples for byte slice manipulationGo bytes package: practical examples for byte slice manipulationMay 08, 2025 am 12:01 AM

The byte package provides a variety of functions to efficiently process byte slices. 1) Use bytes.Contains to check the byte sequence. 2) Use bytes.Split to split byte slices. 3) Replace the byte sequence bytes.Replace. 4) Use bytes.Join to connect multiple byte slices. 5) Use bytes.Buffer to build data. 6) Combined bytes.Map for error processing and data verification.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function