How to resolve the algorithm One-dimensional cellular automata step by step in the Go programming language

Published on 12 May 2024 09:40 PM
#Go

How to resolve the algorithm One-dimensional cellular automata step by step in the Go programming language

Table of Contents

Problem Statement

Assume an array of cells with an initial distribution of live and dead cells, and imaginary cells off the end of the array having fixed values. Cells in the next generation of the array are calculated based on the value of the cell and its left and right nearest neighbours in the current generation. If, in the following table, a live cell is represented by 1 and a dead cell by 0 then to generate the value of the cell at a particular index in the array of cellular values you use the following table:

Let's start with the solution:

Step by Step solution about How to resolve the algorithm One-dimensional cellular automata step by step in the Go programming language

The provided code implements a 1D cellular automata called Rule 184. It simulates the evolution of a row of cells, where each cell can be either alive (indicated with a #) or dead (indicated with a _). The initial state of the automaton is given by the start variable, and the evolution is determined by the following rules:

  • If a cell is alive and both its left and right neighbors are alive, it dies (overpopulation).
  • If a cell is alive and either its left or right neighbor is alive, it survives (survival).
  • If a cell is dead and both its left and right neighbors are alive, it comes alive (birth).
  • If a cell is dead and either its left or right neighbor is alive, it remain dead (stay dead).

First implementation: The first implementation uses a generator function (newGenerator) to create a closure that generates the next state of the cellular automata given the current state and the parameters for the off-left, off-right, and dead cells. The closure maintains the current state in two variables, g0 (a string) and g1 (a byte slice). For each iteration, it computes the next state of each cell in g1 based on the rules described above. It then updates g0 to the new state and returns the substring of g0 that represents the row of cells.

Second implementation: The second implementation uses goroutines and synchronization primitives to simulate the cellular automata in parallel. It creates a byte slice a that represents the current state, including the off-left and off-right cells. It then starts a goroutine for each cell in the row. Each goroutine continuously reads the current state of its own cell and its two neighbors, computes the next state based on the rules, and updates the shared a slice with the new state.

To control the synchronization between the goroutines, two sync.WaitGroup are used: read and write. Before each iteration, the read wait group is incremented to indicate that all goroutines need to read the current state before proceeding. After all goroutines have read the state, the read wait group is decremented to allow them to proceed with the computation.

Similarly, before writing the new state to the shared a slice, the write wait group is incremented to indicate that all goroutines need to finish writing before proceeding to the next iteration. After all goroutines have written the new state, the write wait group is decremented to allow them to start the next iteration.

Both implementations print the current state of the cellular automata for the first 10 iterations, showcasing the evolution of the patterns. The initial state is "##########", which represents a row of cells with some alive cells and some dead cells. As the iterations progress, the pattern evolves, with some cells dying, some surviving, and some being born.

Source code in the go programming language

package main

import "fmt"

const (
    start    = "_###_##_#_#_#_#__#__"
    offLeft  = '_'
    offRight = '_'
    dead     = '_'
)

func main() {
    fmt.Println(start)
    g := newGenerator(start, offLeft, offRight, dead)
    for i := 0; i < 10; i++ {
        fmt.Println(g())
    }
}

func newGenerator(start string, offLeft, offRight, dead byte) func() string {
    g0 := string(offLeft) + start + string(offRight)
    g1 := []byte(g0)
    last := len(g0) - 1
    return func() string {
        for i := 1; i < last; i++ {
            switch l := g0[i-1]; {
            case l != g0[i+1]:
                g1[i] = g0[i]
            case g0[i] == dead:
                g1[i] = l
            default:
                g1[i] = dead
            }
        }
        g0 = string(g1)
        return g0[1:last]
    }
}


package main

import (
    "fmt"
    "sync"
)

const (
    start    = "_###_##_#_#_#_#__#__"
    offLeft  = '_'
    offRight = '_'
    dead     = '_'
)

func main() {
    fmt.Println(start)
    a := make([]byte, len(start)+2)
    a[0] = offLeft
    copy(a[1:], start)
    a[len(a)-1] = offRight
    var read, write sync.WaitGroup
    read.Add(len(start) + 1)
    for i := 1; i <= len(start); i++ {
        go cell(a[i-1:i+2], &read, &write)
    }
    for i := 0; i < 10; i++ {
        write.Add(len(start) + 1)
        read.Done()
        read.Wait()
        read.Add(len(start) + 1)
        write.Done()
        write.Wait()
        fmt.Println(string(a[1 : len(a)-1]))
    }
}

func cell(kernel []byte, read, write *sync.WaitGroup) {
    var next byte
    for {
        l, v, r := kernel[0], kernel[1], kernel[2]
        read.Done()
        switch {
        case l != r:
            next = v
        case v == dead:
            next = l
        default:
            next = dead
        }
        read.Wait()
        kernel[1] = next
        write.Done()
        write.Wait()
    }
}


  

You may also check:How to resolve the algorithm Strip comments from a string step by step in the VBScript programming language
You may also check:How to resolve the algorithm Peano curve step by step in the XPL0 programming language
You may also check:How to resolve the algorithm Loops/Nested step by step in the MAXScript programming language
You may also check:How to resolve the algorithm Universal Turing machine step by step in the Julia programming language
You may also check:How to resolve the algorithm Mouse position step by step in the Gambas programming language