main.go (4029B)
1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "log" 7 "math" 8 "os" 9 ) 10 11 func main() { 12 if len(os.Args) > 1 { 13 day18(os.Args[1]) 14 } else if len(os.Args) == 1 { 15 fmt.Printf("usage: %s inputfile.txt ROW_NUM\n", os.Args[0]) 16 } else { 17 fmt.Println("No input data") 18 } 19 } 20 21 func day18(input_file string) { 22 fmt.Printf("day 18 input filename: %s\n", input_file) 23 input, err := os.Open(input_file) 24 if err != nil { 25 log.Fatal(err) 26 } 27 defer input.Close() 28 sideTrans := [6]Line{ 29 {{0, 0, 0}, {1, 1, 0}}, 30 {{0, 0, 0}, {1, 0, 1}}, 31 {{0, 0, 0}, {0, 1, 1}}, 32 33 {{0, 0, 1}, {1, 1, 1}}, 34 {{0, 1, 0}, {1, 1, 1}}, 35 {{1, 0, 0}, {1, 1, 1}}, 36 } 37 scanner := bufio.NewScanner(input) 38 sides := make(map[string]bool) // side:is-inner 39 smallest := Vec3{x: math.MaxInt, y: math.MaxInt, z: math.MaxInt} 40 for scanner.Scan() { 41 in := scanner.Text() 42 var c Vec3 43 num, err := fmt.Sscanf(in, "%d,%d,%d", &c.x, &c.y, &c.z) 44 if num != 3 && err != nil { 45 log.Fatal("parse error", err) 46 } 47 if c.x < smallest.x && c.y < smallest.y && c.z < smallest.z { 48 smallest = c 49 } 50 for _, s := range sideTrans { 51 side := Line{ 52 {c.x + s[0].x, c.y + s[0].y, c.z + s[0].z}, 53 {c.x + s[1].x, c.y + s[1].y, c.z + s[1].z}, 54 } 55 if _, exists := sides[side.String()]; exists { 56 sides[side.String()] = true 57 } else { 58 sides[side.String()] = false 59 } 60 } 61 } 62 if err = scanner.Err(); err != nil { 63 log.Fatal(err) 64 } 65 sum := 0 66 borders := [][4]Line{} 67 for k, v := range sides { 68 if !v { 69 sum++ 70 var line Line 71 fmt.Sscanf(k, "%d:%d:%d-%d:%d:%d", &line[0].x, &line[0].y, &line[0].z, &line[1].x, &line[1].y, &line[1].z) 72 b := GetBorders(line) 73 borders = append(borders, b) 74 } 75 } 76 fmt.Println("Part 1:", sum) 77 //fmt.Println(sides) 78 fmt.Println("smallest:", smallest) 79 s1 := smallest 80 s1.y += 1 81 start := Line{smallest, s1} 82 start_index := FindBorders(start, borders)[0] 83 fmt.Println("start_index:", start_index) 84 fmt.Println("start:", start) 85 var queue []int 86 visited := make(map[int]bool) 87 queue = append(queue, start_index) 88 for len(queue) > 0 { 89 bi := queue[0] 90 queue = queue[1:] 91 if _, e := visited[bi]; e { 92 continue 93 } 94 visited[bi] = true 95 b := borders[bi] 96 for i := 0; i < 4; i++ { 97 bis := FindBorders(b[i], borders) 98 for _, b1 := range bis { 99 if _, e := visited[b1]; !e { 100 queue = append(queue, b1) 101 } 102 } 103 } 104 } 105 fmt.Println(len(visited)) 106 } 107 108 func FindBorders(border Line, borders [][4]Line) []int { 109 var out []int 110 for i, b := range borders { 111 for _, l := range b { 112 if l[0].x == border[0].x && 113 l[0].y == border[0].y && 114 l[0].z == border[0].z && 115 l[1].x == border[1].x && 116 l[1].y == border[1].y && 117 l[1].z == border[1].z { 118 out = append(out, i) 119 } 120 } 121 } 122 return out 123 } 124 125 func GetBorders(diag Line) [4]Line { 126 var out [4]Line 127 128 if diag[0].x == diag[1].x { 129 out[0][0] = diag[0] 130 out[0][1] = diag[0] 131 out[0][1].y += 1 132 out[1][0] = out[0][1] 133 out[1][1] = out[0][1] 134 out[1][1].z += 1 135 out[2][0] = diag[0] 136 out[2][1] = diag[0] 137 out[2][1].z += 1 138 out[3][0] = out[2][1] 139 out[3][1] = out[2][1] 140 out[3][1].y += 1 141 } else if diag[0].y == diag[1].y { 142 out[0][0] = diag[0] 143 out[0][1] = diag[0] 144 out[0][1].z += 1 145 out[1][0] = out[0][1] 146 out[1][1] = out[0][1] 147 out[1][1].x += 1 148 out[2][0] = diag[0] 149 out[2][1] = diag[0] 150 out[2][1].x += 1 151 out[3][0] = out[2][1] 152 out[3][1] = out[2][1] 153 out[3][1].z += 1 154 } else if diag[0].z == diag[1].z { 155 out[0][0] = diag[0] 156 out[0][1] = diag[0] 157 out[0][1].y += 1 158 out[1][0] = out[0][1] 159 out[1][1] = out[0][1] 160 out[1][1].x += 1 161 out[2][0] = diag[0] 162 out[2][1] = diag[0] 163 out[2][1].x += 1 164 out[3][0] = out[2][1] 165 out[3][1] = out[2][1] 166 out[3][1].y += 1 167 } else { 168 log.Fatal("invalid side diagonal coordinates") 169 } 170 171 return out 172 } 173 174 func min(a, b int) int { 175 if a < b { 176 return a 177 } else { 178 return b 179 } 180 } 181 182 type Vec3 struct { 183 x, y, z int 184 } 185 186 func (v3 Vec3) String() string { 187 return fmt.Sprintf("%d:%d:%d", v3.x, v3.y, v3.z) 188 } 189 190 type Line [2]Vec3 191 192 func (s Line) String() string { 193 return fmt.Sprintf("%s-%s", s[0].String(), s[1].String()) 194 }