github.com/cycloss/advent-of-code@v0.0.0-20221210145555-15039b95faa6/2015/day8.go (about) 1 package aoc2015 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 ) 7 8 type token struct { 9 codeCount, charCount, encodedCount int 10 } 11 12 type tokeniser struct { 13 index int 14 bytes []byte 15 } 16 17 func Day8() { 18 var bytes, _ = ioutil.ReadFile("inputs/day8.txt") 19 var tokeniser = newTokeniser(bytes) 20 var tokens = tokeniser.tokeniseBytes() 21 var codeTotal, charTotal, encodedTotal = calculateTotal(tokens) 22 var res = codeTotal - charTotal 23 fmt.Printf("Result: %d\n", res) 24 // plus 2 for surrounding quotes 25 var encodedDiff = encodedTotal - codeTotal 26 fmt.Printf("Encoded diff: %d\n", encodedDiff) 27 } 28 29 func newTokeniser(b []byte) *tokeniser { 30 return &tokeniser{-1, b} 31 } 32 33 func (t *tokeniser) tokeniseBytes() []*token { 34 var tokens = []*token{} 35 for t.next() { 36 var token = t.getNextToken() 37 tokens = append(tokens, token) 38 } 39 return tokens 40 } 41 42 func (t *tokeniser) next() bool { 43 t.index++ 44 return t.index < len(t.bytes) 45 } 46 47 func (t *tokeniser) current() byte { 48 return t.bytes[t.index] 49 } 50 51 const backslash = byte('\\') 52 const quote = byte('"') 53 const newline byte = '\n' 54 55 func (t *tokeniser) getNextToken() *token { 56 57 var current = t.current() 58 switch current { 59 case newline: 60 return &token{} 61 case backslash: 62 return t.handleEscaped() 63 case quote: 64 // add 3 as should be surrounding quote 65 return &token{codeCount: 1, encodedCount: 3} 66 default: 67 return &token{charCount: 1, codeCount: 1, encodedCount: 1} 68 } 69 } 70 71 func (t *tokeniser) handleEscaped() *token { 72 if !t.next() { 73 return &token{charCount: 1, encodedCount: 1, codeCount: 1} 74 } 75 var current = t.current() 76 switch current { 77 case backslash: 78 // must escape two back slashes 79 return &token{codeCount: 2, charCount: 1, encodedCount: 4} 80 case quote: 81 return &token{codeCount: 2, charCount: 1, encodedCount: 4} 82 default: 83 // must be hex sequence 84 t.index += 2 85 return &token{codeCount: 4, charCount: 1, encodedCount: 5} 86 } 87 } 88 89 func calculateTotal(tokens []*token) (int, int, int) { 90 var codeTotal, charTotal, encodedTotal int 91 for _, token := range tokens { 92 codeTotal += token.codeCount 93 charTotal += token.charCount 94 encodedTotal += token.encodedCount 95 } 96 97 return codeTotal, charTotal, encodedTotal 98 }