Visualize day 4 using Ebitengine
This commit is contained in:
11
day04/go.mod
11
day04/go.mod
@@ -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
14
day04/go.sum
Normal 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=
|
||||
@@ -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
101
day04/vis.go
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user