Jonathan D. Storm 2 kuukautta sitten
vanhempi
commit
8475399a80
4 muutettua tiedostoa jossa 136 lisäystä ja 0 poistoa
  1. 117 0
      cmd/day_12/main.go
  2. 4 0
      cmd/day_12/test.txt
  3. 10 0
      cmd/day_12/test2.txt
  4. 5 0
      cmd/day_12/test3.txt

+ 117 - 0
cmd/day_12/main.go

@@ -0,0 +1,117 @@
+package main
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"slices"
+)
+
+func trim(l []byte) []byte {
+	if len(l) == 0 {
+		return l
+	}
+	if l[len(l)-1] != '\n' {
+		return l
+	}
+	return l[:len(l)-1]
+}
+
+func main() {
+	width, height := 0, 0
+	r := bufio.NewReader(os.Stdin)
+
+	// Read input
+	plat := make([]byte, 0, 256)
+	for {
+		line, err := r.ReadBytes('\n')
+		if errors.Is(err, io.EOF) {
+			break
+		}
+		if err != nil {
+			log.Fatalf("While reading input: %v", err)
+		}
+		line = trim(line)
+		if width == 0 {
+			width = len(line)
+		}
+		if len(line) != width {
+			log.Fatalf("Expected input line to be of length %d but has length %d", width, len(line))
+		}
+		height++
+		plat = append(plat, line...)
+	}
+
+	// Find regions
+	regions := make([][]int, 1, 32)
+	degree := make([]int, len(plat))
+	incidence := make([]int, len(plat))
+	for i, plot := range plat {
+		up, lt, rt, dn := i-width, i-1, i+1, i+width
+
+		if dn < len(plat) && plot == plat[dn] {
+			degree[i]++
+		}
+		if i/width == rt/width && plot == plat[rt] {
+			degree[i]++
+		}
+		if 0 <= up && plot == plat[up] {
+			degree[i]++
+			regionId := incidence[up]
+			incidence[i] = regionId
+			regions[regionId] = append(regions[regionId], i)
+		}
+		if 0 <= lt && i/width == lt/width && plot == plat[lt] {
+			degree[i]++
+			regionId := incidence[lt]
+			if incidence[i] == 0 {
+				incidence[i] = regionId
+				regions[regionId] = append(regions[regionId], i)
+				continue
+			}
+			if incidence[i] == regionId {
+				continue
+			}
+			// If we made it this far, then incidence[i] was just
+			// set to incidence[plat[up]]. Therefore, plat[up]
+			// exists.
+			// Join subregions with different ids.
+			var src, tgt int
+			switch {
+			case regionId < incidence[i]:
+				tgt, src = regionId, incidence[i]
+			case regionId > incidence[i]:
+				src, tgt = regionId, incidence[i]
+			}
+			for _, pid := range regions[src] {
+				incidence[pid] = tgt
+				regions[tgt] = append(regions[tgt], pid)
+			}
+			regions = slices.Delete(regions, src, src+1)
+			incidence[i] = tgt
+			continue
+		}
+		if incidence[i] > 0 {
+			continue
+		}
+		region := make([]int, 1, 32)
+		region[0] = i
+		regions = append(regions, region)
+		incidence[i] = len(regions) - 1
+	}
+	regions = regions[1:]
+
+	// Find prices
+	total := 0
+	for _, r := range regions {
+		perimeter := 0
+		for _, pid := range r {
+			perimeter += 4 - degree[pid]
+		}
+		total += len(r) * perimeter
+	}
+	fmt.Printf("%d\n", total)
+}

+ 4 - 0
cmd/day_12/test.txt

@@ -0,0 +1,4 @@
+AAAA
+BBCD
+BBCC
+EEEC

+ 10 - 0
cmd/day_12/test2.txt

@@ -0,0 +1,10 @@
+RRRRIICCFF
+RRRRIICCCF
+VVRRRCCFFF
+VVRCCCJFFF
+VVVVCJJCFE
+VVIVCCJJEE
+VVIIICJJEE
+MIIIIIJJEE
+MIIISIJEEE
+MMMISSJEEE

+ 5 - 0
cmd/day_12/test3.txt

@@ -0,0 +1,5 @@
+OOOOO
+OXOXO
+OOOOO
+OXOXO
+OOOOO