advent2022

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

main.go (4354B)


      1 package main
      2 
      3 import (
      4 	"bufio"
      5 	"fmt"
      6 	"log"
      7 	"os"
      8 	"strconv"
      9 	"strings"
     10 )
     11 
     12 type Pos struct {
     13 	x, y int
     14 }
     15 
     16 type Shape []Pos
     17 type Shapes []Shape
     18 
     19 func (ss Shapes) GetLeftmost() Pos {
     20 	p := Pos{x: -1}
     21 	for _, s := range ss {
     22 		for _, e := range s {
     23 			if p.x == -1 || e.x < p.x {
     24 				p = e
     25 			}
     26 		}
     27 	}
     28 	return p
     29 }
     30 func (ss Shapes) GetRightmost() Pos {
     31 	var p Pos
     32 	for _, s := range ss {
     33 		for _, e := range s {
     34 			if e.x > p.x {
     35 				p = e
     36 			}
     37 		}
     38 	}
     39 	return p
     40 }
     41 func (ss Shapes) GetMaxY() int {
     42 	y := 0
     43 	for _, s := range ss {
     44 		for _, e := range s {
     45 			if e.y > y {
     46 				y = e.y
     47 			}
     48 		}
     49 	}
     50 	return y
     51 }
     52 
     53 type Grid [][]byte
     54 
     55 func (grid Grid) String() string {
     56 	var s string
     57 	for y := 0; y < len(grid); y++ {
     58 		for x := 0; x < len(grid[y]); x++ {
     59 			switch grid[y][x] {
     60 			case 0:
     61 				s += " "
     62 			case 1:
     63 				s += "#"
     64 			case 2:
     65 				s += "o"
     66 			default:
     67 				s += " "
     68 			}
     69 		}
     70 		s += "\n"
     71 	}
     72 	return s
     73 }
     74 func (grid *Grid) Init(width, height int) {
     75 	*grid = make(Grid, height)
     76 	for y := 0; y < height; y++ {
     77 		(*grid)[y] = make([]byte, width)
     78 	}
     79 }
     80 func (grid *Grid) AddShape(s Shape, offset int) {
     81 	for i := 1; i < len(s); i++ {
     82 		x1, y1 := s[i-1].x-offset, s[i-1].y
     83 		x2, y2 := s[i].x-offset, s[i].y
     84 		if x1 > x2 {
     85 			x1, x2 = x2, x1
     86 		}
     87 		if y1 > y2 {
     88 			y1, y2 = y2, y1
     89 		}
     90 		for x := x1; x <= x2; x++ {
     91 			for y := y1; y <= y2; y++ {
     92 				(*grid)[y][x] = 1
     93 			}
     94 		}
     95 	}
     96 }
     97 
     98 func main() {
     99 	if len(os.Args) > 1 {
    100 		day14(os.Args[1])
    101 	} else if len(os.Args) == 1 {
    102 		fmt.Printf("usage: %s inputfile.txt\n", os.Args[0])
    103 	} else {
    104 		fmt.Println("No input data")
    105 	}
    106 }
    107 
    108 func day14(input_file string) {
    109 	fmt.Printf("day 14 input filename: %s\n", input_file)
    110 	input, err := os.Open(input_file)
    111 	if err != nil {
    112 		log.Fatal(err)
    113 	}
    114 	defer input.Close()
    115 	scanner := bufio.NewScanner(input)
    116 	var shapes Shapes
    117 	for scanner.Scan() {
    118 		in := scanner.Text()
    119 		edges := strings.Split(in, " -> ")
    120 		var s Shape
    121 		for _, edge := range edges {
    122 			var p Pos
    123 			xs, ys, found := strings.Cut(edge, ",")
    124 			if !found {
    125 				log.Fatal("invalid input")
    126 			}
    127 			p.x, err = strconv.Atoi(xs)
    128 			if err != nil {
    129 				log.Fatal(err)
    130 			}
    131 			p.y, err = strconv.Atoi(ys)
    132 			if err != nil {
    133 				log.Fatal(err)
    134 			}
    135 			s = append(s, p)
    136 		}
    137 		if len(s) <= 1 {
    138 			log.Fatal("invalid shape", s)
    139 		}
    140 		shapes = append(shapes, s)
    141 	}
    142 	if err = scanner.Err(); err != nil {
    143 		log.Fatal(err)
    144 	}
    145 
    146 	height := shapes.GetMaxY() + 1
    147 	offsetX := shapes.GetLeftmost().x
    148 	width := shapes.GetRightmost().x - offsetX + 2
    149 	var grid Grid
    150 	grid.Init(width, height)
    151 	for _, s := range shapes {
    152 		grid.AddShape(s, offsetX)
    153 	}
    154 	//fmt.Printf("%v\n", grid)
    155 
    156 	i := 0
    157 	for {
    158 		p := Pos{x: 500 - offsetX, y: 1}
    159 		for p.x > 0 && p.x < width-1 && p.y < height-1 {
    160 			if grid[p.y+1][p.x] == 0 {
    161 				p.y += 1
    162 			} else if grid[p.y+1][p.x-1] == 0 {
    163 				p.y += 1
    164 				p.x -= 1
    165 			} else if grid[p.y+1][p.x+1] == 0 {
    166 				p.y += 1
    167 				p.x += 1
    168 			} else {
    169 				break
    170 			}
    171 		}
    172 		if p.x > 0 && p.x < width-1 && p.y < height-1 && grid[p.y][p.x] == 0 {
    173 			grid[p.y][p.x] = 2
    174 		} else {
    175 			break
    176 		}
    177 		i++
    178 		//fmt.Printf("%v\n", grid)
    179 	}
    180 	//fmt.Printf("%v\n", grid)
    181 	fmt.Println("grains of sand 1:", i)
    182 
    183 	var grid2 Grid
    184 	height += 2
    185 	leftmost := shapes.GetLeftmost()
    186 	rightmost := shapes.GetRightmost()
    187 	minx := leftmost.x - (height - leftmost.y)
    188 	maxx := rightmost.x + (height - rightmost.y)
    189 	if minx > 500-height {
    190 		minx = 500 - height
    191 	}
    192 	if maxx < 500+height {
    193 		maxx = 500 + height
    194 	}
    195 	offsetX = minx
    196 	width = maxx - minx + 2
    197 	///fmt.Printf("minx:%d, maxx:%d,offsetx:%d,width:%d,height:%d\n",minx,maxx,offsetX,width,height)
    198 	if offsetX < 0 {
    199 		offsetX = 0
    200 	}
    201 	grid2.Init(width, height)
    202 	for _, s := range shapes {
    203 		grid2.AddShape(s, offsetX)
    204 	}
    205 	floor := Shape{}
    206 	floor = append(floor, Pos{x: 0, y: height - 1})
    207 	floor = append(floor, Pos{x: width - 1, y: height - 1})
    208 	grid2.AddShape(floor, 0)
    209 	//fmt.Printf("%v\n", grid2)
    210 	i = 0
    211 	for {
    212 		p := Pos{x: 500 - offsetX, y: 0}
    213 		for p.x > 0 && p.x < width-1 && p.y < height-1 {
    214 			if grid2[p.y+1][p.x] == 0 {
    215 				p.y += 1
    216 			} else if grid2[p.y+1][p.x-1] == 0 {
    217 				p.y += 1
    218 				p.x -= 1
    219 			} else if grid2[p.y+1][p.x+1] == 0 {
    220 				p.y += 1
    221 				p.x += 1
    222 			} else {
    223 				break
    224 			}
    225 		}
    226 		if p.y < height-1 && grid2[p.y][p.x] == 0 {
    227 			grid2[p.y][p.x] = 2
    228 		} else {
    229 			break
    230 		}
    231 		i++
    232 		//fmt.Printf("%v\n", grid2)
    233 	}
    234 	//fmt.Printf("%v\n", grid2)
    235 	fmt.Println("grains of sand 2:", i)
    236 }