| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- 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)
- }
|