Skip to content

Instantly share code, notes, and snippets.

@D3Ext
Created January 5, 2023 12:32
Show Gist options
  • Save D3Ext/845bdc6a22bbdd50fe409d78b7d59b96 to your computer and use it in GitHub Desktop.
Save D3Ext/845bdc6a22bbdd50fe409d78b7d59b96 to your computer and use it in GitHub Desktop.
Golang implementation of the De Bruijn algorith
package main
import (
"fmt"
"os"
"strings"
"bytes"
"strconv"
"flag"
)
const characters string = "abcdefABCDEF123" // Characters used in De Bruijn sequence
func DeBruijn(n int) (string) {
var k int = 15
alphabet := characters[0:k]
a := make([]byte, k*n)
var seq []byte
var db func(int, int)
db = func(t, p int) {
if t > n {
if (n % p == 0) {
seq = append(seq, a[1:p+1]...)
}
} else {
a[t] = a[t-p]
db(t+1, p)
for j := int(a[t-p] + 1); j < k; j++ {
a[t] = byte(j)
db(t+1, t)
}
}
}
db(1, 1)
var buf bytes.Buffer
for _, i := range seq {
buf.WriteByte(alphabet[i])
}
b := buf.String()
return b + b[0:n-1]
}
func GeneratePattern(length int) (string) {
return DeBruijn(4)[0:length] // With 4 as value it returns a 50000 length string which is more than neccessary
}
func GetPatternOffset(pattern_str string) (int) { // Find especified pattern in original sequence
original_pattern := DeBruijn(4)
return len(strings.Split(original_pattern, pattern_str)[0]) // Split original cyclic pattern so 0 position is the number of characters to return
}
func ParseFlags() (int, string) {
var pattern_length int
var pattern_to_search string
flag.IntVar(&pattern_length, "l", 0, "length of the pattern to create")
flag.StringVar(&pattern_to_search, "p", "", "pattern to search its offset")
flag.Parse()
return pattern_length, pattern_to_search // Return both values
}
func main() {
pattern_length, pattern_to_search := ParseFlags() // Parse CLI flags
if pattern_length != 0 && pattern_to_search != "" { // Check if two flags were especified to avoid error (just use one)
fmt.Println("Bad parameters!")
fmt.Println("Usage: ./cyclic_pattern -l 256")
fmt.Println(" ./cyclic_pattern -p <pattern to search>")
os.Exit(0)
} else if pattern_length == 0 && pattern_to_search == "" {
flag.PrintDefaults()
os.Exit(0)
}
if pattern_length != 0 {
fmt.Println("Pattern length: " + strconv.Itoa(pattern_length))
cyclic_pattern := GeneratePattern(pattern_length) // Create cyclic pattern using De Brujin algorithm
fmt.Println("Cyclic pattern: " + cyclic_pattern)
os.Exit(0) // Exit program
} else if pattern_to_search != "" {
cyclic_pattern := GeneratePattern(50000)
if strings.Contains(cyclic_pattern, pattern_to_search) {
fmt.Println("Pattern to search: " + pattern_to_search)
offset := GetPatternOffset(pattern_to_search)
fmt.Println("Offset found at: " + strconv.Itoa(offset))
} else {
fmt.Println("Especified pattern offset not found!")
os.Exit(0)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment