[Odin] Left-to-right recursive expanding[Odin] Left-to-right recursive expanding
😡
Offensive Words
Week 33, 2026
package main
import "core:fmt"
import "core:strings"
import "core:mem"
main :: proc () {
alterations := [] [] string {
{ "o", "0" },
{ "i", "1", "!", "|" },
{ "l", "1", "7", "!", "|" },
{ "s", "2", "5", "$" },
{ "z", "2", "7" },
{ "e", "3", "&" },
{ "a", "4", "@" },
{ "g", "6", "9" },
{ "t", "7", "|" },
{ "b", "8", "|3" },
{ "p", "9", "|*" },
{ "q", "9" },
{ "f", "ph" },
{ "h", "#" },
}
for text in ([?] string {
// "face",
// "abc",
// "def",
"hello world",
"offensive words",
}) {
g: Generator
generator_init(&g, alterations)
generator_expand(&g, text)
generator_print(g)
generator_destroy(&g)
}
}
Generator :: struct {
arena : mem.Dynamic_Arena,
allocator : mem.Allocator,
strings : [dynamic] string,
alterations : [] [] string,
}
generator_init :: proc (g: ^Generator, alterations: [] [] string) {
mem.dynamic_arena_init(&g.arena)
g.allocator = mem.dynamic_arena_allocator(&g.arena)
g.strings = make([dynamic] string, 0, 4000, g.allocator)
g.alterations = alterations
}
generator_destroy :: proc (g: ^Generator) {
mem.dynamic_arena_destroy(&g.arena)
}
generator_expand :: proc(g: ^Generator, s: string, index := 0) {
if index >= len(s) {
append(&g.strings, s)
return
}
next_index := index + 1
current := s[index:next_index]
generator_expand(g, s, next_index)
for alt in g.alterations do if alt[0] == current {
for rep in alt[1:] {
parts := [?] string { s[:index], rep, s[next_index:] }
next_s := strings.concatenate(parts[:], g.allocator)
generator_expand(g, next_s, next_index)
}
break
}
}
generator_print :: proc (g: Generator) {
// assert(len(g.strings) > 0)
// fmt.printfln("---- %q ---- %i ----", g.strings[0], len(g.strings))
for s in g.strings do fmt.println(s)
}