day22, simple block code
This commit is contained in:
parent
99c2269df8
commit
7b34b52e5e
|
@ -0,0 +1,97 @@
|
||||||
|
package day22
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type XY struct {
|
||||||
|
X, Y uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type Block struct {
|
||||||
|
XMin, XMax uint
|
||||||
|
YMin, YMax uint
|
||||||
|
Z uint
|
||||||
|
IsSettled bool
|
||||||
|
ZHeight uint
|
||||||
|
Supports []*Block
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) String() string {
|
||||||
|
return fmt.Sprintf("[Block x:%d-%d, y:%d-%d, z:%d, h:%d, isSettled %t]",
|
||||||
|
b.XMin, b.XMax, b.YMin, b.YMax, b.Z, b.ZHeight, b.IsSettled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func AtoIOrPanic(a string) int {
|
||||||
|
n, err := strconv.Atoi(a)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadBlock(line string) (b Block) {
|
||||||
|
re := regexp.MustCompile(`(\d+),(\d+),(\d+)~(\d+),(\d+),(\d+)`)
|
||||||
|
matches := re.FindStringSubmatch(line)
|
||||||
|
|
||||||
|
x1, x2 := AtoIOrPanic(matches[1]), AtoIOrPanic(matches[4])
|
||||||
|
y1, y2 := AtoIOrPanic(matches[2]), AtoIOrPanic(matches[5])
|
||||||
|
z1, z2 := AtoIOrPanic(matches[3]), AtoIOrPanic(matches[6])
|
||||||
|
|
||||||
|
b.XMax = uint(max(x1, x2))
|
||||||
|
b.XMin = uint(min(x1, x2))
|
||||||
|
b.YMax = uint(max(y1, y2))
|
||||||
|
b.YMin = uint(min(y1, y2))
|
||||||
|
b.Z = uint(min(z1, z2))
|
||||||
|
b.ZHeight = uint(max(z1, z2)) - b.Z
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Block) getXY() (coords []XY) {
|
||||||
|
for x := b.XMin; x <= b.XMax; x++ {
|
||||||
|
for y := b.YMin; y <= b.YMax; y++ {
|
||||||
|
coords = append(coords, XY{X: x, Y: y})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadBlockFile(filename string) (blocks []*Block) {
|
||||||
|
bytes, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
text := strings.TrimSpace(string(bytes))
|
||||||
|
for _, line := range strings.Split(text, "\n") {
|
||||||
|
block := ReadBlock(line)
|
||||||
|
blocks = append(blocks, &block)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func BlocksByZ(blocks []*Block) [][]*Block {
|
||||||
|
maxZ := uint(0)
|
||||||
|
for _, block := range blocks {
|
||||||
|
if block.Z > maxZ {
|
||||||
|
maxZ = block.Z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Print("found max z: ", maxZ)
|
||||||
|
|
||||||
|
result := make([][]*Block, maxZ+1)
|
||||||
|
|
||||||
|
for _, block := range blocks {
|
||||||
|
result[block.Z] = append(result[block.Z], block)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package day22
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReadBlock(t *testing.T) {
|
||||||
|
lines := `1,0,1~1,2,1
|
||||||
|
0,0,2~2,0,2
|
||||||
|
0,2,3~2,2,3
|
||||||
|
0,0,4~0,2,4
|
||||||
|
2,0,5~2,2,5
|
||||||
|
0,1,6~2,1,6
|
||||||
|
1,1,8~1,1,9`
|
||||||
|
|
||||||
|
for _, line := range strings.Split(lines, "\n") {
|
||||||
|
b := ReadBlock(line)
|
||||||
|
t.Logf("read %s into block %+v", line, b)
|
||||||
|
t.Logf("XY coords for %+v are : %+v", b, b.getXY())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadFile(t *testing.T) {
|
||||||
|
filename := "example"
|
||||||
|
// filename := "input"
|
||||||
|
blocks := ReadBlockFile(filename)
|
||||||
|
|
||||||
|
byZ := BlocksByZ(blocks)
|
||||||
|
for z, zBlocks := range byZ {
|
||||||
|
zBlocksLine := ""
|
||||||
|
for _, block := range zBlocks {
|
||||||
|
zBlocksLine += block.String()
|
||||||
|
}
|
||||||
|
t.Logf("for level %d blocks %+v", z, zBlocksLine)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
1,0,1~1,2,1
|
||||||
|
0,0,2~2,0,2
|
||||||
|
0,2,3~2,2,3
|
||||||
|
0,0,4~0,2,4
|
||||||
|
2,0,5~2,2,5
|
||||||
|
0,1,6~2,1,6
|
||||||
|
1,1,8~1,1,9
|
|
@ -0,0 +1,32 @@
|
||||||
|
#+title: Notes
|
||||||
|
* ok. let's try this.
|
||||||
|
i'd want to have block type
|
||||||
|
with function to get it's XY coords
|
||||||
|
|
||||||
|
i'd want to settle blocks first.
|
||||||
|
but if i store enough data, for example block.supports slice i'll be able to anser first task.
|
||||||
|
|
||||||
|
(settledOnZ) i would want [][]*Block per level from 0 to up. with references to blocks that settled on that level
|
||||||
|
|
||||||
|
(maxSettledXY) and for going from 0 up i'll want XY of the top block settled with it's level. i guess i could store settled level in the block as well
|
||||||
|
|
||||||
|
then for settling blocks, i will need (sorted map if data is sparse?) go from 0 up,
|
||||||
|
order of processing for blocks on same z level is not important.
|
||||||
|
for each block get it's XY, check maxSettledXY if there's a block check it's Z,
|
||||||
|
for all block XY coords, find maximal settled Z, and refs to all blocks that are directly under with that same Z.
|
||||||
|
|
||||||
|
for the block set settledZ to Z+1, and for all those blocks add the block to 'supports'
|
||||||
|
add block to settledOnZ[Z+1]
|
||||||
|
|
||||||
|
for the second part, i can scan all the blocks, don't even need the settledOnZ, just check if it's 'supports' is empty
|
||||||
|
|
||||||
|
** DONE block type
|
||||||
|
store z, and have 'settledZ', maybe with default -1?
|
||||||
|
** DONE coords type, func to get XY coords of the block
|
||||||
|
** DONE now i guess what? do i want a sorted map? or just map from height to blocks on that hight?
|
||||||
|
let's read file, and calc max height present?
|
||||||
|
i suppose funciton to read file could also be initially entered via test, right?
|
||||||
|
** TODO now go through the z levels, block by block, doing setting.
|
||||||
|
i suppose i could organize setting methods around Space?
|
||||||
|
it will store (settledOnZ) and (maxSettledOnXY)
|
||||||
|
** i can already imagine secon part? what is the most volume that can be disintegrated? or what? most volume is just all
|
|
@ -0,0 +1,10 @@
|
||||||
|
package day22
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Run() int {
|
||||||
|
fmt.Print("oi, hello day 22")
|
||||||
|
return 0
|
||||||
|
}
|
6
main.go
6
main.go
|
@ -4,15 +4,15 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"sunshine.industries/aoc2023/day21"
|
"sunshine.industries/aoc2023/day22"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
log.Print("> starting run:")
|
log.Print("> starting run:")
|
||||||
|
|
||||||
result := day21.Run()
|
result := day22.Run()
|
||||||
log.Printf("\n\nday21 result: %d\n****\n", result)
|
log.Printf("\n\nday22 result: %d\n****\n", result)
|
||||||
endTime := time.Now()
|
endTime := time.Now()
|
||||||
diff := endTime.Sub(startTime)
|
diff := endTime.Sub(startTime)
|
||||||
log.Printf("execution took %s", diff.String())
|
log.Printf("execution took %s", diff.String())
|
||||||
|
|
Loading…
Reference in New Issue