advent2022

Advent of Code 2022 Solutions
git clone git://bsandro.tech/advent2022
Log | Files | Refs | README | LICENSE

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 }