DEV Community

Cover image for DAY 16 - Advent of Code 2020 w/ GoLang
Edvin
Edvin

Posted on

DAY 16 - Advent of Code 2020 w/ GoLang

DAY16:
dont like it

I just did not like the code I wrote for this one. Part one was fine and took about 5 lines of code (other than the input parsing). Part two had me flipping and filtering my matrix of fields and values in a lot of messy ways. Granted I could have done it cleaner but I did not revisit the code I should clean up. If I had some of the mapping and reducing functionality of JS, this would've been simpler. Not complaining that Go doesn't have those, but it is worth mentioning.

Oh.. also, my code will either return the correct answer or just hang..

package days

import (
    "fmt"
    "strings"

    inputs "../inputs"
)

// https://adventofcode.com/2020/day/16
// Sixteen : advent of code, day sixteen part1 and 2
func Sixteen() {

    /*
        This struct is being used for input

        type Tickets struct {
            Fields        map[string][]int
            Ticket        []int
            NearbyTickets [][]int
        }
    */
    input := inputs.Day16

    fmt.Print("(Part 1) - Sum of all bad field values: ")
    fmt.Println(sumAllInvalidValuesOnNearbyTickets(input))

    fmt.Println("(Part 2) - : ")

    withValidTicketsOnly := tossBadTickets(input)
    matchingFieldNames := getFieldNames(withValidTicketsOnly)

    departureTotal := 1

    for i, fieldName := range matchingFieldNames {
        if strings.Contains(fieldName, "departure") {
            departureTotal *= withValidTicketsOnly.Ticket[i]
        }
    }

    fmt.Println(departureTotal)
}

func sumAllInvalidValuesOnNearbyTickets(tickets inputs.Tickets) int {
    badSum := 0

    for _, ticket := range tickets.NearbyTickets {
        for _, fieldValue := range ticket {
            if !validForAnyField(fieldValue, tickets) {
                badSum = badSum + fieldValue
            }
        }
    }

    return badSum
}

func validForAnyField(fieldValue int, tickets inputs.Tickets) bool {
    isIt := false

    for _, ranges := range tickets.Fields {
        if (fieldValue >= ranges[0] && fieldValue <= ranges[1]) || (fieldValue >= ranges[2] && fieldValue <= ranges[3]) {
            isIt = true
            break
        } else {
            isIt = false
        }
    }

    return isIt
}

func tossBadTickets(tickets inputs.Tickets) inputs.Tickets {
    toReturn := inputs.Tickets{}
    toReturn.Fields = tickets.Fields
    toReturn.Ticket = tickets.Ticket
    toReturn.NearbyTickets = [][]int{}

    for _, ticket := range tickets.NearbyTickets {
        fullTicketMatch := true
        for _, fieldValue := range ticket {
            if !validForAnyField(fieldValue, tickets) {
                fullTicketMatch = false
                break
            }
        }
        if fullTicketMatch {
            toReturn.NearbyTickets = append(toReturn.NearbyTickets, ticket)
        }
    }

    return toReturn
}

func getFieldName(column []int, fields map[string][]int) []string {
    allMatchingFieldNames := []string{}

    for fieldName, ranges := range fields {
        fullMatch := true
        for _, val := range column {
            if !((val >= ranges[0] && val <= ranges[1]) || (val >= ranges[2] && val <= ranges[3])) {
                fullMatch = false
                break
            }
        }

        if fullMatch {
            allMatchingFieldNames = append(allMatchingFieldNames, fieldName)
        }
    }

    return allMatchingFieldNames
}

func getFieldNames(tickets inputs.Tickets) []string {
    columns := [][]int{}
    column := []int{}

    for col := 0; col < len(tickets.NearbyTickets[0]); col++ {
        column = []int{}
        for row := 0; row < len(tickets.NearbyTickets); row++ {
            column = append(column, tickets.NearbyTickets[row][col])
        }
        columns = append(columns, column)
    }

    matchingFieldNames := [][]string{}

    for _, col := range columns {
        matchingFieldNames = append(matchingFieldNames, getFieldName(col, tickets.Fields))
    }

    return filterFieldNames(matchingFieldNames)
}

func filterFieldNames(allMatchingFieldNames [][]string) []string {
    filtered := []string{}

    for !allSizeOne(allMatchingFieldNames) {
        for i, rows := range allMatchingFieldNames {
            for j, col := range rows {

                anotherOfMe := false

                for k, rowsInner := range allMatchingFieldNames {
                    for y, colInner := range rowsInner {
                        if y != j && k != y {
                            if col == colInner {
                                anotherOfMe = true
                            }
                        }
                    }
                }

                if !anotherOfMe {
                    allMatchingFieldNames[i] = []string{col}
                }
            }
        }
    }

    for _, fieldNameAsSlice := range allMatchingFieldNames {
        filtered = append(filtered, fieldNameAsSlice[0])
    }

    return filtered
}

func allSizeOne(doubleSlice [][]string) bool {
    res := true

    for _, v := range doubleSlice {
        if len(v) > 1 {
            res = false
            break
        }
    }

    return res
}

Enter fullscreen mode Exit fullscreen mode

Link to Github source file

Top comments (0)