DEV Community

Discussion on: Advent of Code 2020 Solution Megathread - Day 11: Seating System

Collapse
 
gubesch profile image
Christian Gubesch

Hi guys!

I tried the problem with go.

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "time"
    "unicode/utf8"
)

func main() {
    start := time.Now()

    reader := getInput("day11")
    grid := [][]rune{}
    count := 1
    // get input and format it to [][]rune
    for line := range reader {
        if len(grid) == 0 {
            grid = append(grid, []rune{})
            for _, r := range strings.Repeat(".", utf8.RuneCountInString(line)+2) {
                grid[0] = append(grid[0], r)
            }
        }
        grid = append(grid, []rune{})
        line = "." + line + "."
        for _, r := range line {
            grid[count] = append(grid[count], r)
        }
        count++
    }
    grid = append(grid, []rune{})
    for _, r := range strings.Repeat(".", len(grid[0])) {
        grid[count] = append(grid[count], r)
    }

    go func() {
        resultPartOne := partOne(copySliceSlice(grid))
        fmt.Printf("Puzzle 1 result: %d\n", resultPartOne)

    }()
    resultPartTwo := partTwo(grid)
    fmt.Printf("Puzzle 2 result: %d\n", resultPartTwo)
    elapsed := time.Since(start)
    fmt.Println("Run took:", elapsed)
}

func partOne(grid [][]rune) int {
    deepCopy := copySliceSlice(grid)
    changeCoutner := -1
    for changeCoutner != 0 {
        changeCoutner = 0
        for y := 0; y < len(grid); y++ {
            for x := 0; x < len(grid[y]); x++ {
                if grid[y][x] == '#' {
                    if checkAdjacent(deepCopy, y, x) >= 4 {
                        changeCoutner++
                        grid[y][x] = 'L'
                    }
                } else if grid[y][x] == 'L' {
                    if checkAdjacent(deepCopy, y, x) == 0 {
                        changeCoutner++
                        grid[y][x] = '#'
                    }
                }
            }
        }
        if changeCoutner > 0 {
            deepCopy = copySliceSlice(grid)
        }
    }
    return getOccupiedSeats(grid)
}

func checkAdjacent(grid [][]rune, y, x int) int {
    positionsToCheck := [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}}
    hitCount := 0
    for _, pos := range positionsToCheck {
        if grid[y+pos[0]][x+pos[1]] == '#' {
            hitCount++
        }
    }
    return hitCount
}

func partTwo(grid [][]rune) int {
    deepCopy := copySliceSlice(grid)
    changeCoutner := -1
    for changeCoutner != 0 {

        changeCoutner = 0
        for y := 0; y < len(grid); y++ {
            for x := 0; x < len(grid[y]); x++ {
                if grid[y][x] == '#' {
                    if checkAdjacentPartTwo(deepCopy, y, x) >= 5 {
                        changeCoutner++
                        grid[y][x] = 'L'
                    }
                } else if grid[y][x] == 'L' {
                    if checkAdjacentPartTwo(deepCopy, y, x) == 0 {
                        changeCoutner++
                        grid[y][x] = '#'
                    }
                }
            }
        }
        if changeCoutner > 0 {
            deepCopy = copySliceSlice(grid)
        }
    }

    return getOccupiedSeats(grid)
}

func checkAdjacentPartTwo(grid [][]rune, y, x int) int {
    positionsToCheck := [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}}
    hitCount := 0
    rows := len(grid)
    colums := len(grid[0])
    for _, pos := range positionsToCheck {
        yToCheck := y + pos[0]
        xToCheck := x + pos[1]

        for (yToCheck >= 0 && yToCheck < rows) && (xToCheck >= 0 && xToCheck < colums) {
            if grid[yToCheck][xToCheck] == '#' {
                hitCount++
                if hitCount == 5 {
                    return hitCount
                }
                break
            } else if grid[yToCheck][xToCheck] == 'L' {
                break
            }
            yToCheck += pos[0]
            xToCheck += pos[1]
        }
    }
    return hitCount
}

func copySliceSlice(grid [][]rune) [][]rune {
    copyOfgrid := make([][]rune, len(grid))
    for i := 0; i < len(grid); i++ {
        sliceCopy := make([]rune, len(grid[i]))
        copy(sliceCopy, grid[i])
        copyOfgrid[i] = sliceCopy
    }
    return copyOfgrid
}

func getOccupiedSeats(grid [][]rune) int {
    counter := 0
    for _, row := range grid {
        for _, r := range row {
            if r == '#' {
                counter++
            }
        }
    }
    return counter
}

func getInput(path string) <-chan string {
    c := make(chan string)

    go func() {
        file, err := os.Open(path)
        if err != nil {
            panic("error in reading file: " + err.Error())
        }
        // scan file
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            c <- scanner.Text()
        }
        close(c)
    }()

    return c
}
Enter fullscreen mode Exit fullscreen mode

Unfortunately I still have a runtime in total of round about 120ms.

Do you have any suggestions for a performance enhancement?

Best regards