Created
January 5, 2023 12:32
-
-
Save D3Ext/845bdc6a22bbdd50fe409d78b7d59b96 to your computer and use it in GitHub Desktop.
Golang implementation of the De Bruijn algorith
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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