05 Go

Part I Assignment

// tells the Go compiler that the package should compile as an executable program
package main

// import standard libraries
import (
    "bufio"
    "fmt"
    "os"
    s "strings"
    "strconv"
)

// as in C
func main() {
    // many functions return error as the second return value
    readFile, err := os.Open("05.input")
    // it can be checked for detecting problems
    if err != nil {
        fmt.Println(err)
    }

    // stacks is a slice with strings (representing crate columns)
    var stacks []string;
    // stacklines are lines from the input file representing the initial piles
    var stacklines []string;

    // Go std library magic for reading the input file
    fileScanner := bufio.NewScanner(readFile)
    fileScanner.Split(bufio.ScanLines)

    // iterate through lines
    for fileScanner.Scan() {
        line := fileScanner.Text()
        // empty line separates the initial positions and the moves
        if len(line) == 0 {
            // initialize stacks from remembered stacklines
            // the first layer of crates
            layer := len(stacklines) -2
            // get the number of columns (roughly 1/4) of max line length
            cols := (len(stacklines[layer])+1)/4
            // start from the first layer of crates
            for layer >= 0 {
                c := 0
                // process columns of crates from left to right
                for c < cols {
                    // extract the crate
                    ss := stacklines[layer][c*4:c*4+3]
                    // append only if there is a crate
                    if s.HasPrefix(ss, "[") {
                        // append a new string if necessary
                        if len(stacks)-1 < c {
                            stacks = append(stacks, ss[1:2])
                        } else {
                            stacks[c] = stacks[c] + ss[1:2]
                        }
                    }
                    c += 1
                }
                layer -= 1
            }
        } else if s.HasPrefix(line, "move") {
            // here we process moves
            // split "move X from Y to Z" and extract integers
            moves := s.Split(line, " ")
            cnt, _ := strconv.Atoi(moves[1])
            from, _ := strconv.Atoi(moves[3])
            to, _ := strconv.Atoi(moves[5])
            n := 0
            // move crate by crate
            for n < cnt {
                // pop the top crate from <from> column
                lastf := len(stacks[from-1])-1
                top := stacks[from-1][lastf]
                stacks[from-1] = stacks[from-1][:lastf]
                // append the top crate to <to> column
                stacks[to-1] = stacks[to-1] + string(top)
                n += 1
            }
        } else {
            // remember stack lines at the beginning
            stacklines = append(stacklines, line)
        }
    }

    n := 0
    out := ""
    for n < len(stacks) {
        // collect the top crate characters from stacks
        out = out + string(stacks[n][len(stacks[n])-1])
        n += 1
    }

    // it's safer to close the open file before exiting
    readFile.Close()

    // print out the top crates of stacks
    fmt.Println(out)
}

Second part

Moving whole columns instead of crate by crate.

Just change the code after the for loop // move crate by crate with this:

// move <cnt> crates in one move
crates := stacks[from-1][len(stacks[from-1])-cnt:len(stacks[from-1])]
stacks[from-1] = stacks[from-1][:len(stacks[from-1])-cnt]
stacks[to-1] = stacks[to-1] + crates

What I learned

first published: 2022-12-05
last modified: 2023-01-21