You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.5 KiB

package main
import (
"AoC2020/helper"
"fmt"
"os"
"regexp"
"strings"
)
func main() {
lineBreak := "\n"
args := os.Args[1:]
input, err := helper.GetFile(args[0])
if err != nil {
fmt.Println(err)
}
rows := strings.Split(input, lineBreak+lineBreak)
rulesInput := strings.Split(rows[0], lineBreak)
ruleNames := getRuleNames(rulesInput)
rules := getRules(rulesInput)
myTicket := getFields(strings.Split(rows[1], lineBreak)[1])
nearbyTicketsInputs := strings.Split(rows[2], lineBreak)[1:]
var nearbyTickets [][]int
for _, val := range nearbyTicketsInputs {
nearbyTickets = append(nearbyTickets, getFields(val))
}
fmt.Printf("RuleNames: %v \n Rules: %v \n myTicket: %v \n nearbyTickets: %v \n", ruleNames, rules, myTicket, nearbyTickets)
part1(rules, nearbyTickets)
fmt.Println()
part2(rules, nearbyTickets,myTicket, ruleNames)
}
func part1(rules [][]int, nearbyTickets [][]int) {
var invalidFields []int
for _, ticket := range nearbyTickets {
invalidFields = append(invalidFields, getInvalidFields(rules, ticket)...)
}
fmt.Printf("Invalid Fields: %v \n", invalidFields)
sum := 0
for _, field := range invalidFields {
sum += field
}
fmt.Printf("Result: %v \n", sum)
}
func part2(rules [][]int, nearbyTickets [][]int, myTicket []int, ruleNames []string) {
validTickets := getValidTickets(rules,nearbyTickets)
var ruleFieldPossibleMapping = make(map[int][]int)
for fieldIndex := 0; fieldIndex < len(validTickets[0]); fieldIndex++ {
ruleIndexes := findFittingRulesForFieldsAtPositionN(rules, validTickets, fieldIndex)
ruleFieldPossibleMapping[fieldIndex] = ruleIndexes
}
fmt.Printf("Possible Mapping: %v \n", ruleFieldPossibleMapping)
var ruleFieldMapping = make(map[int]int)
for len(ruleFieldMapping) < len(ruleFieldPossibleMapping) {
for field, possibleMapping := range ruleFieldPossibleMapping {
if len(possibleMapping) == 1 {
reducePossibleMapping(ruleFieldPossibleMapping,possibleMapping[0])
ruleFieldMapping[field] = possibleMapping[0]
}
}
}
for fieldIndex, ruleIndex := range ruleFieldMapping {
fmt.Printf("Rule: %v Position: %v Value: %v \n", ruleNames[ruleIndex], fieldIndex, myTicket[fieldIndex])
}
}
func reducePossibleMapping(ruleFieldPossibleMapping map[int][]int, possibleMapping int){
for key, val := range ruleFieldPossibleMapping{
ruleFieldPossibleMapping[key] = remove(val,possibleMapping)
}
}
func getRules(input []string) [][]int {
var rules [][]int
for _, val := range input {
r, _ := regexp.Compile("[0-9]*-[0-9]*")
ruleStrings := r.FindAllString(val, -1)
for _, ruleString := range ruleStrings {
rule, _ := helper.MapToNumber(strings.Split(ruleString, "-"))
rules = append(rules, rule)
}
}
return rules
}
func getRuleNames(input []string) []string {
var ruleNames []string
for _, val := range input {
r, _ := regexp.Compile("[a-z| ]*:")
ruleName := r.FindString(val)
ruleNames = append(ruleNames, ruleName)
}
return ruleNames
}
func getFields(ticket string) []int {
fieldValues := strings.Split(ticket, ",")
fields, _ := helper.MapToNumber(fieldValues)
return fields
}
func fullfillsRule(rule []int, field int) bool {
return field >= rule[0] && field <= rule[1]
}
func findFittingRulesForFieldsAtPositionN(rules [][]int, tickets [][]int, position int) []int {
var fittingRules []int
for i := 0; i < len(rules); i += 2 {
if rulesApplyForAllFieldsAtPositionN(rules[i:i+2], tickets, position) {
fittingRules = append(fittingRules,i/2)
}
}
return fittingRules
}
func rulesApplyForAllFieldsAtPositionN(rules [][]int, tickets [][]int, position int) bool {
for _, ticket := range tickets {
if !fullfillsRule(rules[1], ticket[position]) && !fullfillsRule(rules[0], ticket[position]) {
return false
}
}
return true
}
func fullFillAtLeastOneRule(rules [][]int, field int) bool {
for _, val := range rules {
if fullfillsRule(val, field) {
return true
}
}
return false
}
func getInvalidFields(rules [][]int, ticket []int) []int {
var invalidFields []int
for _, field := range ticket {
if !fullFillAtLeastOneRule(rules, field) {
invalidFields = append(invalidFields, field)
}
}
return invalidFields
}
func getValidTickets(rules [][]int, tickets [][]int) [][]int {
var validTickets [][]int
for _, ticket := range tickets {
if len(getInvalidFields(rules,ticket)) == 0 {
validTickets = append(validTickets,ticket)
}
}
return validTickets
}
func remove(s []int, val int) []int {
var newS []int
for _,elem := range s {
if val != elem {
newS = append(newS,elem)
}
}
return newS
}