aboutsummaryrefslogtreecommitdiff
path: root/2021/16/bits
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--2021/16/bits/scanner.go217
1 files changed, 217 insertions, 0 deletions
diff --git a/2021/16/bits/scanner.go b/2021/16/bits/scanner.go
new file mode 100644
index 0000000..296705d
--- /dev/null
+++ b/2021/16/bits/scanner.go
@@ -0,0 +1,217 @@
+package bits
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+)
+
+type Bits struct {
+ Version byte
+ TypeID byte
+ Value int
+ Operators []*Bits
+ Len int
+}
+
+// Scanner represents a lexical scanner.
+type Scanner struct {
+ r *bufio.Reader
+ buff byte
+ readBits byte
+ parsingDepth int
+}
+
+// NewScanner returns a new instance of Scanner.
+func NewScanner(r io.Reader) *Scanner {
+ return &Scanner{r: bufio.NewReader(r)}
+}
+
+// read reads the next bits from the bufferred reader.
+// Returns the rune(0) if an error occurs (or io.EOF is returned).
+func (s *Scanner) readBit() (bool, error) {
+ var ret bool
+ s.readBits++
+ switch s.readBits {
+ case 2:
+ ret = s.buff&0b0100 != 0
+ case 3:
+ ret = s.buff&0b0010 != 0
+ case 4:
+ ret = s.buff&0b0001 != 0
+ default:
+ var err error
+ s.buff, err = s.r.ReadByte()
+ if err != nil || s.buff == '\n' {
+ return false, err
+ }
+ if s.buff <= '9' {
+ s.buff -= '0'
+ } else {
+ s.buff = s.buff - 'A' + 10
+ }
+ if err != nil {
+ return false, err
+ }
+ s.readBits = 1
+ ret = s.buff&0b1000 != 0
+ }
+ if ret {
+ fmt.Print("1")
+ } else {
+ fmt.Print("0")
+ }
+ return ret, nil
+}
+
+// Scan returns the next Bits packet
+func (s *Scanner) Scan() *Bits {
+ var bits Bits
+ for i := 0; i < 3; i++ {
+ bits.Version <<= 1
+ b, err := s.readBit()
+ if err != nil {
+ return nil
+ }
+ if b {
+ bits.Version++
+ }
+ }
+ fmt.Println("Version:", bits.Version)
+ for i := 0; i < 3; i++ {
+ bits.TypeID <<= 1
+ b, err := s.readBit()
+ if err != nil {
+ return nil
+ }
+ if b {
+ bits.TypeID++
+ }
+ }
+ bits.Len += 6
+ fmt.Println("TypeID:", bits.TypeID)
+ if bits.TypeID == 4 {
+ for {
+ keepGoing, err := s.readBit()
+ if err != nil {
+ return nil
+ }
+ var buff byte
+ for i := 0; i < 4; i++ {
+ buff <<= 1
+ b, err := s.readBit()
+ if err != nil {
+ return nil
+ }
+ if b {
+ buff++
+ }
+ }
+ bits.Len += 5
+ bits.Value = bits.Value<<4 + int(buff)
+ if !keepGoing {
+ break
+ }
+ }
+ fmt.Println("Value:", bits.Value)
+ } else { // operator
+ b, err := s.readBit()
+ if err != nil {
+ return nil
+ }
+ bits.Len++
+ if b {
+ var buff int
+ for i := 0; i < 11; i++ {
+ buff <<= 1
+ b, err := s.readBit()
+ if err != nil {
+ return nil
+ }
+ if b {
+ buff++
+ }
+ }
+ bits.Len += 11
+ fmt.Println("SubPackets type 1, nb of subpackets:", buff)
+ s.parsingDepth++
+ for i := 0; i < buff; i++ {
+ subBits := s.Scan()
+ if subBits == nil {
+ return nil
+ }
+ bits.Operators = append(bits.Operators, subBits)
+ bits.Len += subBits.Len
+ }
+ s.parsingDepth--
+ } else {
+ var buff int
+ for i := 0; i < 15; i++ {
+ buff <<= 1
+ b, err := s.readBit()
+ if err != nil {
+ return nil
+ }
+ if b {
+ buff++
+ }
+ }
+ bits.Len += 15
+ fmt.Println("SubPackets type 0 of len:", buff)
+ s.parsingDepth++
+ for buff > 0 {
+ subBits := s.Scan()
+ if subBits == nil {
+ return nil
+ }
+ bits.Operators = append(bits.Operators, subBits)
+ bits.Len += subBits.Len
+ buff -= subBits.Len
+ fmt.Println("remaining bits:", buff)
+ }
+ s.parsingDepth--
+ }
+ }
+ if s.parsingDepth == 0 {
+ bits.Len += 4 - int(s.readBits)
+ s.readBits = 0
+ }
+ switch bits.TypeID {
+ case 0:
+ for _, sub := range bits.Operators {
+ bits.Value += sub.Value
+ }
+ case 1:
+ bits.Value = 1
+ for _, sub := range bits.Operators {
+ bits.Value *= sub.Value
+ }
+ case 2:
+ bits.Value = bits.Operators[0].Value
+ for _, sub := range bits.Operators {
+ if bits.Value > sub.Value {
+ bits.Value = sub.Value
+ }
+ }
+ case 3:
+ bits.Value = bits.Operators[0].Value
+ for _, sub := range bits.Operators {
+ if bits.Value < sub.Value {
+ bits.Value = sub.Value
+ }
+ }
+ case 5:
+ if bits.Operators[0].Value > bits.Operators[1].Value {
+ bits.Value = 1
+ }
+ case 6:
+ if bits.Operators[0].Value < bits.Operators[1].Value {
+ bits.Value = 1
+ }
+ case 7:
+ if bits.Operators[0].Value == bits.Operators[1].Value {
+ bits.Value = 1
+ }
+ }
+ return &bits
+}