isundil 9 жил өмнө
parent
commit
50ab35b77f
1 өөрчлөгдсөн 131 нэмэгдсэн , 0 устгасан
  1. 131 0
      d04/d04.go

+ 131 - 0
d04/d04.go

@@ -0,0 +1,131 @@
+package main
+
+import "strings"
+import "strconv"
+import "bufio"
+import "sort"
+import "fmt"
+import "os"
+
+type KeyValue struct {
+    Key rune
+    Value int
+}
+
+type KeyValues []KeyValue
+func (this KeyValues) Len() int {
+    return len(this)
+}
+func (this KeyValues) Swap(i, j int) {
+    tmp := this[i]
+    this[i] = this[j]
+    this[j] = tmp
+}
+func (this KeyValues) Less(i, j int) bool {
+    if this[i].Value == this[j].Value {
+        return this[i].Key > this[j].Key
+    }
+    return this[i].Value < this[j].Value
+}
+
+type Room struct {
+    EncryptedName string
+    DecryptedName string
+    Checksum string
+    RoomId int
+}
+
+func shiftRune(r rune, shift int) string {
+    if r == '-' {
+        return " "
+    }
+    res := int(r) +shift
+    if res > 'z' {
+        res = res - 'z' + 'a' -1
+    }
+    return string(res)
+}
+
+func NewRoom(roomName string, sectorId int) Room {
+    var result Room
+    letters := make(map[rune]int)
+    letterShift := sectorId %26
+    result.EncryptedName = roomName
+
+    for _, l := range(roomName) {
+        if (l != '-') {
+            letters[l] ++
+        }
+        result.DecryptedName += shiftRune(l, letterShift)
+    }
+
+    sortedLetters := make(KeyValues, len(letters))
+    i := 0
+    for k, v := range letters {
+        sortedLetters[i] = KeyValue{k, v}
+        i++
+    }
+    sort.Sort(sort.Reverse(sortedLetters))
+
+    for i =0; i < 5; i++ {
+        result.Checksum += string(sortedLetters[i].Key)
+    }
+
+    result.RoomId = sectorId
+
+    return result
+}
+
+func (this Room) isValid(checksum string) bool {
+    return this.Checksum == checksum
+}
+
+func parseLine(line string) (Room, string) {
+    words := strings.FieldsFunc(line, func(r rune) bool {
+        return (r == '-' || r == '[' || r == ']')
+    })
+
+    checkSum := words[len(words) -1]
+    sectorId, _ := strconv.Atoi(words[len(words) -2])
+    words = words[:len(words) -2]
+    var roomName string
+    first := true
+
+    for word := range(words) {
+        if (first) {
+            first = false
+        } else {
+            roomName += "-"
+        }
+        roomName += words[word]
+    }
+
+    return NewRoom(roomName, sectorId), checkSum
+}
+
+func main() {
+    reader := bufio.NewReader(os.Stdin)
+    valid := 0
+
+    for true {
+        line, _, err := reader.ReadLine()
+
+        if string(line) != "" {
+            room, checkSum := parseLine(string(line))
+
+            if room.isValid(checkSum) {
+                valid += room.RoomId
+                if strings.Contains(room.DecryptedName, "northpole") {
+                    fmt.Println("Found `North Pole objects` secret room: " +strconv.Itoa(room.RoomId))
+                }
+            }
+        }
+
+        if err != nil {
+            break
+        }
+    }
+
+    fmt.Println(valid)
+}
+