package main

import (
	"bufio"
	"fmt"
	"os"
	"regexp"
	"strconv"
)

func calcScore(s [][]string) int {
  result := 0
  for i := range s {
    if len(s[i]) % 2 == 0 {
      fmt.Println("The following valid update has an even length, so cannot calculate the middle page: ", s[i])
    } else {
      middle := (len(s[i]) + 1) / 2
      middlePage, _ := strconv.Atoi(s[i][middle - 1])
      result = result + middlePage
    }
  }
  return result
}

func isValid(update []string, rules [][]string) bool {
  valid := true
  for i:=1; i<len(update); i++ { //FOR EACH NUMBER OF THE UPDATE
    for j := range rules { //FOR EACH RULE
      if update[i] != rules[j][0] {
         continue
      } else {
        for k:=0; k<i; k++ { //FOR EACH
          if update[k] == rules[j][1] {
            valid = false
            break
          }
        } 
      }
    }
  }
  return valid
}

func makeValid(update []string, rules [][]string) []string {
  for i:=1; i<len(update); i++ { //FOR EACH NUMBER OF THE UPDATE
    for j := range rules { //FOR EACH RULE
      if update[i] != rules[j][0] {
         continue
      } else {
        for k:=0; k<i; k++ { //FOR EACH
          if update[k] == rules[j][1] {
            temp := update[k]
            update[k] = update[i]
            update[i] = temp
            break
          }
        } 
      }
    }
  }
  if ! isValid(update, rules) {
    update=makeValid(update, rules)
  }
  return update
}

func main() {
  file, _ := os.Open("input")
  defer file.Close()
  scanner := bufio.NewScanner(file)
  ruleRegex := regexp.MustCompile(`[0-9]+\|[0-9]+`)
  updateRegex := regexp.MustCompile(`^(\d+(,\d+)*)$`)
  numberRegex := regexp.MustCompile(`[0-9]+`)
  rules := [][]string{}
  updates := [][]string{}
  for scanner.Scan() {
    line := scanner.Text()
    ruleMatches := ruleRegex.FindAllString(line, -1)
    updateMatches := updateRegex.FindAllString(line, -1)
    rule := []string{}
    update := []string{}    
    for i := range ruleMatches {
      rule = append(rule, numberRegex.FindAllString(ruleMatches[i], -1)...)
    }
    for i := range updateMatches {
      update = append(update, numberRegex.FindAllString(updateMatches[i], -1)...)
    }
    if len(rule) > 0 {
      rules = append(rules, rule)
    }
    if len(update) > 0 {
      updates = append(updates, update)
    }
  }
  validUpdates := [][]string{}
  invalidUpdates := [][]string{}
  for i := range updates {
    if isValid(updates[i], rules) {
      validUpdates = append(validUpdates, updates[i])
    } else {
      valid:=makeValid(updates[i], rules)
      invalidUpdates = append(invalidUpdates, valid)
    }
  }
  validScore := calcScore(validUpdates)
  fmt.Println("Score of valid updates: ", validScore)
  invalidScore := calcScore(invalidUpdates)
  fmt.Println(invalidScore)
}
