134 lines
2.8 KiB
Go
134 lines
2.8 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"log"
|
||
|
"os"
|
||
|
"regexp"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
var inpArr []string
|
||
|
var input, readInp string
|
||
|
for {
|
||
|
_, err := fmt.Scan(&readInp)
|
||
|
if err != nil {
|
||
|
if err != io.EOF {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
break
|
||
|
}
|
||
|
inpArr = append(inpArr, readInp)
|
||
|
}
|
||
|
input = strings.Join(inpArr, "")
|
||
|
|
||
|
//fmt.Println("Part 1 Solution: " + strconv.Itoa(sumAllInts(input)))
|
||
|
fmt.Println("Part 2 Solution: " + strconv.Itoa(sumAllInts(removeAllValue(input, "red"))))
|
||
|
//removeAllValue(input, "red")
|
||
|
}
|
||
|
|
||
|
func removeAllValue(s string, remove string) string {
|
||
|
ret := s
|
||
|
var removed bool
|
||
|
//ret, _ = removeFirstValue(ret, remove)
|
||
|
ret, removed = removeFirstValue(ret, remove)
|
||
|
for removed {
|
||
|
ret, removed = removeFirstValue(ret, remove)
|
||
|
}
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
// Not quite returning proper JSON... But may be good enough
|
||
|
// for the problem (since we're not looking for JSON output
|
||
|
// anyways
|
||
|
func removeFirstValue(s string, remove string) (string, bool) {
|
||
|
ret := s
|
||
|
var curlIdx []int
|
||
|
removeStart := -1
|
||
|
for i := range s {
|
||
|
if s[i] == '{' {
|
||
|
curlIdx = pushLevel(curlIdx, i)
|
||
|
}
|
||
|
if checkForValueAtIdx(s, ":\""+remove+"\"", i) {
|
||
|
removeStart, curlIdx = popLevel(curlIdx)
|
||
|
ret = strings.Replace(ret, trimAtClose(s[removeStart:]), "", -1)
|
||
|
// Now figure out if we have an abandoned key
|
||
|
if ret[removeStart-1] == ':' {
|
||
|
// Trackback in ret until we find the matching " and remove up to removeStart
|
||
|
remTrackBack := removeStart - 3
|
||
|
for ret[remTrackBack] != '"' {
|
||
|
remTrackBack--
|
||
|
}
|
||
|
}
|
||
|
return ret, true
|
||
|
}
|
||
|
if s[i] == '}' {
|
||
|
_, curlIdx = popLevel(curlIdx)
|
||
|
}
|
||
|
}
|
||
|
return ret, false
|
||
|
}
|
||
|
|
||
|
// Trim string after closing bracket/brace
|
||
|
func trimAtClose(s string) string {
|
||
|
var levelStack []int
|
||
|
for i := range s {
|
||
|
if s[i] == '[' || s[i] == '{' {
|
||
|
levelStack = pushLevel(levelStack, i)
|
||
|
} else if s[i] == ']' || s[i] == '}' {
|
||
|
idx := -1
|
||
|
idx, levelStack = popLevel(levelStack)
|
||
|
if idx == 0 {
|
||
|
endIdx := i + 1
|
||
|
if s[i+1] == ',' {
|
||
|
endIdx++
|
||
|
}
|
||
|
return s[:endIdx]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
// Checks if the s contains v starting at index i
|
||
|
func checkForValueAtIdx(s string, v string, i int) bool {
|
||
|
if len(s) > i+len(v) {
|
||
|
if s[i:i+len(v)] == v {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// Simple Part 1 solution
|
||
|
func sumAllInts(s string) int {
|
||
|
var allIntStrings []string
|
||
|
re := regexp.MustCompile("[-]?[0-9]+")
|
||
|
allIntStrings = append(allIntStrings, re.FindAllString(s, -1)...)
|
||
|
var sum int
|
||
|
for i := range allIntStrings {
|
||
|
sum += mustAtoi(allIntStrings[i])
|
||
|
}
|
||
|
return sum
|
||
|
}
|
||
|
|
||
|
func pushLevel(stack []int, n int) []int {
|
||
|
return append(stack, n)
|
||
|
}
|
||
|
|
||
|
func popLevel(stack []int) (int, []int) {
|
||
|
return stack[len(stack)-1], stack[:len(stack)-1]
|
||
|
}
|
||
|
|
||
|
func mustAtoi(s string) int {
|
||
|
r, err := strconv.Atoi(s)
|
||
|
if err != nil {
|
||
|
fmt.Println("Tried to Atoi " + s)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
return r
|
||
|
}
|