main.go (2604B)
1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 ) 8 9 const ( 10 FLOOR = '.' 11 EMPTY = 'L' 12 OCCUPIED = '#' 13 ) 14 15 type seats struct { 16 width int 17 height int 18 v []rune 19 } 20 21 func (this *seats) val(x, y int) rune { 22 return this.v[x*this.width+y] 23 } 24 25 func (this *seats) valChecked(x, y int) (rune, bool) { 26 if x >= 0 && x < this.height && y >= 0 && y < this.width { 27 return this.v[x*this.width+y], true 28 } else { 29 return 0, false 30 } 31 } 32 33 func (this *seats) set(x, y int, val rune) { 34 this.v[x*this.width+y] = val 35 } 36 37 func (this seats) copy() seats { 38 return seats{this.width, this.height, append([]rune(nil), this.v...)} 39 } 40 41 func readInput(filename string) (res seats) { 42 file, _ := os.Open(filename) 43 defer file.Close() 44 scanner := bufio.NewScanner(file) 45 for scanner.Scan() { 46 row := scanner.Text() 47 res.height += 1 48 res.width = len(row) 49 for _, ch := range row { 50 res.v = append(res.v, ch) 51 } 52 } 53 return 54 } 55 56 func main() { 57 input := readInput("./input.txt") 58 // 2281 59 fmt.Println(part(input, update1)) 60 // 2085 61 fmt.Println(part(input, update2)) 62 } 63 64 func update1(input seats, x, y int) rune { 65 old := input.val(x, y) 66 if old == FLOOR { 67 return FLOOR 68 } 69 dx := []int{-1, +0, +1, -1, +1, -1, +0, +1} 70 dy := []int{-1, -1, -1, +0, +0, +1, +1, +1} 71 occCount := 0 72 for i := 0; i < len(dx); i++ { 73 val, ok := input.valChecked(x+dx[i], y+dy[i]) 74 if ok && val == OCCUPIED { 75 occCount += 1 76 } 77 } 78 if old == EMPTY && occCount == 0 { 79 return OCCUPIED 80 } 81 if old == OCCUPIED && occCount >= 4 { 82 return EMPTY 83 } 84 return old 85 } 86 87 func update2(input seats, x, y int) rune { 88 old := input.val(x, y) 89 if old == FLOOR { 90 return FLOOR 91 } 92 dx := []int{-1, +0, +1, -1, +1, -1, +0, +1} 93 dy := []int{-1, -1, -1, +0, +0, +1, +1, +1} 94 occCount := 0 95 for i := 0; i < len(dx); i++ { 96 xNew, yNew := x, y 97 for val, ok := FLOOR, true; ok; val, ok = input.valChecked(xNew, yNew) { 98 if val == FLOOR { 99 xNew += dx[i] 100 yNew += dy[i] 101 } else { 102 if val == OCCUPIED { 103 occCount += 1 104 } 105 break 106 } 107 } 108 } 109 if old == EMPTY && occCount == 0 { 110 return OCCUPIED 111 } 112 if old == OCCUPIED && occCount >= 5 { 113 return EMPTY 114 } 115 return old 116 } 117 118 func part(input seats, updater func(seats, int, int) rune) (occCount int) { 119 curr := input.copy() 120 next := input.copy() 121 for updated := true; updated; { 122 updated = false 123 for x := 0; x < curr.height; x++ { 124 for y := 0; y < curr.width; y++ { 125 old := next.val(x, y) 126 next.set(x, y, updater(curr, x, y)) 127 updated = updated || old != next.val(x, y) 128 } 129 } 130 curr, next = next, curr 131 } 132 for _, v := range curr.v { 133 if v == OCCUPIED { 134 occCount += 1 135 } 136 } 137 return 138 }