|
|
@@ -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)
|
|
|
+}
|
|
|
+
|