Visualize day 4 using Ebitengine

This commit is contained in:
Nic
2025-12-06 19:03:11 +01:00
parent ab0ba74c38
commit 82c927ed76
4 changed files with 128 additions and 48 deletions

View File

@@ -1,3 +1,14 @@
module day04
go 1.25.5
require github.com/hajimehoshi/ebiten/v2 v2.9.4
require (
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1 // indirect
github.com/ebitengine/hideconsole v1.0.0 // indirect
github.com/ebitengine/purego v0.9.0 // indirect
github.com/jezek/xgb v1.1.1 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
)

14
day04/go.sum Normal file
View File

@@ -0,0 +1,14 @@
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1 h1:+kz5iTT3L7uU+VhlMfTb8hHcxLO3TlaELlX8wa4XjA0=
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1/go.mod h1:lKJoeixeJwnFmYsBny4vvCJGVFc3aYDalhuDsfZzWHI=
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
github.com/ebitengine/hideconsole v1.0.0/go.mod h1:hTTBTvVYWKBuxPr7peweneWdkUwEuHuB3C1R/ielR1A=
github.com/ebitengine/purego v0.9.0 h1:mh0zpKBIXDceC63hpvPuGLiJ8ZAa3DfrFTudmfi8A4k=
github.com/ebitengine/purego v0.9.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/hajimehoshi/ebiten/v2 v2.9.4 h1:IlPJpwtksylmmvNhQjv4W2bmCFWXtjY7Z10Esise1bk=
github.com/hajimehoshi/ebiten/v2 v2.9.4/go.mod h1:DAt4tnkYYpCvu3x9i1X/nK/vOruNXIlYq/tBXxnhrXM=
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=

View File

@@ -1,55 +1,9 @@
package main
import "fmt"
// Update represents a cell that needs to be updated (set to 0)
type Update struct {
Row int
Column int
}
func main() {
// read input
grid := ReadGrid("input.txt")
// count removable cells
count := 0
// track if the algorithm had its initial run for Level 1 compatibility
ranOnce := false
// track cells that need to be updated
updates := []Update{}
// as long as cells need to be updated or at first run
for len(updates) > 0 || !ranOnce {
// update cells
for _, cell := range updates {
grid[cell.Row][cell.Column] = 0
}
// reset update cells
updates = []Update{}
// scan cells
for i := 1; i < len(grid)-1; i++ {
for j := 1; j < len(grid[0])-1; j++ {
// if cell has less than 4 filled neighbors, count cell
// and add cell to list of update cells
if grid[i][j] == 1 && NeighborSum(grid, i, j) < 4 {
count++
updates = append(updates, Update{i, j})
}
}
}
// result for Level 1
if !ranOnce {
ranOnce = true
fmt.Println("Result Level 1:", count)
}
}
// result for Level 2
fmt.Println("Result Level 2:", count)
// run visualization using Ebitengine
RunEbiten(grid)
}

101
day04/vis.go Normal file
View File

@@ -0,0 +1,101 @@
package main
import (
"fmt"
"image/color"
"github.com/hajimehoshi/ebiten/v2"
)
// Update represents a cell that needs to be updated (set to 0)
type Update struct {
Row int
Column int
}
type Grid struct {
Count int
FrameCount int
GridData [][]int
Locked bool
RanOnce bool
UpdateFrames int
Updates []Update
}
func (g *Grid) Update() error {
// only update every nth frame
if g.FrameCount != 0 {
// increase frame count, reset if update is hit
g.FrameCount = (g.FrameCount + 1) % g.UpdateFrames
return nil
}
// increase frame count
g.FrameCount++
// if the automata terminated, print result for Level 2 once and return
if len(g.Updates) == 0 && g.RanOnce {
if !g.Locked {
g.Locked = true
fmt.Println("Result Level 2:", g.Count)
}
return nil
}
// update cells
for _, cell := range g.Updates {
g.GridData[cell.Row][cell.Column] = 0
}
// reset update cells
g.Updates = []Update{}
// scan cells
for i := 1; i < len(g.GridData)-1; i++ {
for j := 1; j < len(g.GridData[0])-1; j++ {
// if cell has less than 4 filled neighbors, count cell
// and add cell to list of update cells
if g.GridData[i][j] == 1 && NeighborSum(g.GridData, i, j) < 4 {
g.Count++
g.Updates = append(g.Updates, Update{i, j})
}
}
}
// result for Level 1
if !g.RanOnce {
g.RanOnce = true
fmt.Println("Result Level 1:", g.Count)
}
return nil
}
func (g *Grid) Draw(screen *ebiten.Image) {
screen.Fill(color.Black)
for i := 1; i < len(g.GridData)-1; i++ {
for j := 1; j < len(g.GridData[0])-1; j++ {
if g.GridData[i][j] == 1 {
screen.Set(i, j, color.White)
}
}
}
}
func (g *Grid) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
return len(g.GridData), len(g.GridData[0])
}
func RunEbiten(grid [][]int) {
ebiten.SetWindowSize(139*4, 139*4)
ebiten.SetWindowTitle("Advent of Code - Day 4")
if err := ebiten.RunGame(&Grid{
GridData: grid,
UpdateFrames: 5,
}); err != nil {
fmt.Println(err)
}
}