Skip to content

Instantly share code, notes, and snippets.

@samix73
Created December 9, 2022 17:00
Show Gist options
  • Save samix73/e749fd4b62e1a6b8a4db8ca1c5601c56 to your computer and use it in GitHub Desktop.
Save samix73/e749fd4b62e1a6b8a4db8ca1c5601c56 to your computer and use it in GitHub Desktop.
Golang generic graph generator
package main
import (
"encoding/gob"
"encoding/json"
"math/rand"
"os"
"strconv"
"strings"
)
type StringData string
func (s StringData) String() string {
return string(s)
}
func generateData() StringData {
nameList := []string{
"Pants",
"Battle",
"Carrot",
"Sweet",
"Shadow",
"Shoe",
"Beer",
"Green",
"Yellow",
"Dark",
"White",
"Shirt",
"Monkey",
"Silly",
}
return StringData(nameList[rand.Intn(len(nameList))] + nameList[rand.Intn(len(nameList))])
}
type Edge[E DataType] struct {
Data E `json:"data"`
Index int `json:"index"`
Score int `json:"score"`
}
func (e *Edge[E]) String() string {
bobTheBuilder := new(strings.Builder)
bobTheBuilder.WriteString(e.Data.String())
bobTheBuilder.WriteString("\n\t")
bobTheBuilder.WriteString("Weight: " + strconv.Itoa(e.Score))
bobTheBuilder.WriteString("\n\t")
bobTheBuilder.WriteString("-> " + strconv.Itoa(e.Index))
return bobTheBuilder.String()
}
type DataType interface {
String() string
}
type Node[N DataType, E DataType] struct {
Data N `json:"data"`
Edges []*Edge[E] `json:"edges"`
}
func (n *Node[N, E]) String() string {
bobTheBuilder := new(strings.Builder)
bobTheBuilder.WriteString(n.Data.String())
if len(n.Edges) > 0 {
bobTheBuilder.WriteRune('\n')
}
for j, edge := range n.Edges {
bobTheBuilder.WriteRune('\t')
bobTheBuilder.WriteString("#" + strconv.Itoa(j) + ": ")
bobTheBuilder.WriteString(edge.String())
if j < len(n.Edges)-1 {
bobTheBuilder.WriteRune('\n')
}
}
return bobTheBuilder.String()
}
func NewNode[N DataType, E DataType](data N) *Node[N, E] {
return &Node[N, E]{
Data: data,
Edges: make([]*Edge[E], 0),
}
}
func (n *Node[N, E]) canConnect(i int) bool {
for _, edge := range n.Edges {
if edge.Index == i {
return false
}
}
return rand.Float64() < 0.2
}
func (n *Node[N, E]) Connect(i int, score int, data E) {
if !n.canConnect(i) {
return
}
n.Edges = append(n.Edges, &Edge[E]{
Data: data,
Index: i,
Score: score,
})
}
type Graph[N DataType, E DataType] struct {
Nodes []*Node[N, E] `json:"nodes"`
}
func NewGraph[N DataType, E DataType]() *Graph[N, E] {
return &Graph[N, E]{
Nodes: make([]*Node[N, E], 0),
}
}
func (g *Graph[N, E]) AddNode(n *Node[N, E]) {
g.Nodes = append(g.Nodes, n)
}
func (g *Graph[N, E]) Populate(maxNodes, maxScore int, nodeDataGenerator func() N, edgeDataGenerator func() E) {
for i := 0; i < maxNodes; i++ {
g.AddNode(NewNode[N, E](nodeDataGenerator()))
}
for i, n := range g.Nodes {
for j := range g.Nodes {
if i == j {
continue
}
n.Connect(j, rand.Intn(maxScore), edgeDataGenerator())
}
}
}
func (g *Graph[N, E]) String() string {
bobTheBuilder := new(strings.Builder)
for i, node := range g.Nodes {
bobTheBuilder.WriteString("#" + strconv.Itoa(i) + ": ")
bobTheBuilder.WriteString(node.String())
bobTheBuilder.WriteRune('\n')
}
return bobTheBuilder.String()
}
func (g *Graph[N, E]) Dump() error {
f, err := os.Create("dump.json")
if err != nil {
return err
}
defer f.Close()
gobF, err := os.Create("dump.gob")
if err != nil {
return err
}
defer gobF.Close()
if err := gob.NewEncoder(gobF).Encode(g); err != nil {
return err
}
return json.NewEncoder(f).Encode(g)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment