{"id":24083375,"url":"https://github.com/mitranim/codex","last_synced_at":"2025-04-30T18:23:27.351Z","repository":{"id":26726399,"uuid":"30183918","full_name":"mitranim/codex","owner":"mitranim","description":"Generator of random synthetic words or names","archived":false,"fork":false,"pushed_at":"2020-02-24T07:03:52.000Z","size":52,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-26T06:56:56.291Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mitranim.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-02-02T11:25:22.000Z","updated_at":"2023-09-04T04:28:55.000Z","dependencies_parsed_at":"2022-07-25T16:18:17.436Z","dependency_job_id":null,"html_url":"https://github.com/mitranim/codex","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Fcodex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Fcodex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Fcodex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Fcodex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mitranim","download_url":"https://codeload.github.com/mitranim/codex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251758796,"owners_count":21639111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-09T23:56:30.249Z","updated_at":"2025-04-30T18:23:27.327Z","avatar_url":"https://github.com/mitranim.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![GoDoc](https://godoc.org/github.com/Mitranim/codex?status.svg)](https://godoc.org/github.com/Mitranim/codex)\n\n## Description\n\nGenerator of random synthetic words or names. Takes sample words, analyses them,\nand lazily produces a set of similar derived words. Works for\n[any language](#traitsexaminestring-error).\n\nHas a JavaScript port with about half the performance:\n[`foliant`](https://github.com/Mitranim/foliant).\n\nExample program using `codex`:\n\n```golang\npackage main\n\nimport (\n  \"fmt\"\n  \"github.com/Mitranim/codex\"\n)\n\nfunc main() {\n  source := []string{\"jasmine\", \"katie\", \"nariko\", \"karen\"}\n\n  traits, err := codex.NewTraits(source)\n  if err != nil {\n    panic(err)\n  }\n  gen := traits.Generator()\n\n  // Print twelve random words.\n  for i := 0; i \u003c 12; i++ {\n    fmt.Println(gen())\n  }\n\n  // Printed (your result will be different):\n  //   jarik smiko ikatik arinat nasmin katie\n  //   rikatin smikas minena ikatin jasmika rinaren\n\n  // Find out how many words can be generated from this sample.\n  gen = traits.Generator()\n  i := 0\n  for gen() != \"\" {i++}\n  fmt.Println(\"total:\", i)\n\n  // Printed:\n  //   total: 392\n}\n```\n\n## Contents\n\n* [Description](#description)\n* [Contents](#contents)\n* [Installation](#installation)\n* [API Reference](#api-reference)\n  * [type Traits](#type-traits)\n    * [NewTraits()](#newtraitsstring-traits-error)\n    * [Traits.Examine()](#traitsexaminestring-error)\n    * [Traits.Generator()](#traitsgenerator-func-string)\n* [ToDo / WIP](#todo--wip)\n\n## Installation\n\nIn a shell:\n\n```sh\ngo get github.com/Mitranim/codex\n```\n\nIn your Go files:\n\n```golang\nimport (\n  \"fmt\"\n  \"github.com/Mitranim/codex\"\n)\n\nfunc main() {\n  traits, err := codex.NewTraits([]string{\"sample\", \"pair\"})\n  if err != nil {\n    panic(err)\n  }\n\n  gen := traits.Generator()\n  for word := gen(); word != \"\"; word = gen() {\n    fmt.Println(word)\n  }\n}\n```\n\nTo test the package, `cd` into the package directory and run:\n\n```sh\n# Just tests\ngo test\n```\n\nTo run benchmarks:\n\n```sh\n# With benchmarks\ngo test -bench .\n```\n\n## API Reference\n\nThe entry point for everything is a `Traits` object. It takes existing words as\ninput. Words must consist of known glyphs, as defined by the sound sets in\n[`sounds.go`](sounds.go) or by custom sets assigned to a traits struct (see the\n[reference](#type-traits)). If an invalid word is encountered, an error is\nreturned.\n\n### `type Traits`\n\n```golang\ntype Traits struct {\n  // Minimum and maximum number of sounds.\n  MinNSounds int\n  MaxNSounds int\n  // Minimum and maximum number of vowels.\n  MinNVowels int\n  MaxNVowels int\n  // Maximum number of consequtive vowels.\n  MaxConseqVow int\n  // Maximum number of consequtive consonants.\n  MaxConseqCons int\n  // Set of sounds that occur in the words.\n  SoundSet Set\n  // Set of pairs of sounds that occur in the words.\n  PairSet PairSet\n\n  // Optional custom set of known sounds.\n  KnownSounds Set\n  // Optional custom set of known vowels.\n  KnownVowels Set\n}\n```\n\n`Traits` represent rudimental characteristics of a word or group of words. A\ntraits object unequivocally defines a set of synthetic words that may be derived\nfrom them. They're produced by a generator function made with\n[`Traits.Generator()`](#traitsgenerator-func-string).\n\nThe optional fields `KnownSounds` and `KnownVowels` specify custom sets of\nsounds and vowels. This lets you use `codex` for any character set, including\nnon-Latin alphabets. See\n[`Traits.Examine()`](#traitsexaminestring-error).\n\n#### `NewTraits([]string) (*Traits, error)`\n\nShortcut for creating a `Traits` object and calling its `Examine()` method.\nThese are equivalent:\n\n```golang\ntraits, err := NewTraits([]string{\"mountain\", \"waterfall\", \"grotto\"})\n\ntraits := \u0026Traits{}\nerr := traits.Examine([]string{\"mountain\", \"waterfall\", \"grotto\"})\n```\n\nIgnore this if you're using custom sound sets (e.g. non-Latin).\n\n#### `Traits.Examine([]string) error`\n\nAnalyses the given words and merges their attributes into self.\n\n```golang\ntraits := \u0026Traits{}\nerr := traits.Examine([]string{\"mountain\", \"waterfall\", \"grotto\"})\n```\n\nBy default, this uses the sets of known sounds and vowels defined in\n[`sounds.go`](sounds.go). This includes the 26 letters of the standard US\nEnglish alphabet and some common digraphs like `th`, which are treated as single\nphonemes.\n\nHowever, `codex` is language-independent. Assign custom `KnownSounds` and\n`KnownVowels` to teach it a sound system of your choosing. It can be Greek or\nCyrillic or Elvish or Clingon — doesn't matter as long as the given sounds and\nvowels cover the words in your input. Refer to [`sounds.go`](sounds.go) as an\nexample.\n\nHere's how to teach it Greek:\n\n```golang\ntraits := \u0026codex.Traits{\n  KnownSounds: codex.Set.New(nil,\n    \"α\", \"β\", \"γ\", \"δ\", \"ε\", \"ζ\", \"η\", \"θ\", \"ι\", \"κ\", \"λ\", \"μ\",\n    \"ν\", \"ξ\", \"ο\", \"π\", \"ρ\", \"σ\", \"ς\", \"τ\", \"υ\", \"φ\", \"χ\", \"ψ\", \"ω\"),\n  KnownVowels: codex.Set.New(nil, \"α\", \"ε\", \"η\", \"ι\", \"ο\", \"υ\", \"ω\"),\n}\n\ntraits.Examine([]string{\"ελ\", \"διδασκω\", \"ελληνικο\", \"αλφαβητο\"})\n\ngen := traits.Generator()\nfor word := gen(); word != \"\"; word = gen() {\n  fmt.Println(word)\n}\n\n// \"ιδαλφ\"\n// \"κο\"\n// \"ηνικο\"\n// ...\n```\n\n#### `Traits.Generator() func() string`\n\nCreates a generator function that yields a new random synthetic word on each\ncall. The words are guaranteed to never repeat, and to be randomly distributed\nacross the total set of possible words for these traits.\n\nAfter a generator is exhausted, subsequent calls return `\"\"`.\n\nA traits object is stateless, and `Generator()` produces a completely new\ngenerator on each call. Generators don't affect each other.\n\nThis remains fast even for large source datasets, and is suitable for use on web\nservers and in other applications where responses must be quick.\n\n```golang\ntraits, err := codex.NewTraits([]string{\"goblin\", \"smoke\"})\ngen := traits.Generator()\n\nfor word := gen(); word != \"\"; word = gen() {\n  fmt.Print(word, \" \")\n}\n\n// moblin oblin mobli goblin smobli gobli smoke\n// this generator is exhausted\n```\n\n## ToDo / WIP\n\n### Investigation\n\nConsider providing an option to enable reverse pairs in `Traits.Examine()`.\nCheck the performance impact, particularly with large datasets.\n\n### Algorithms\n\nPerhaps Traits.validPart() should also forbid repeated triples.\n\n### Tests\n\nRandom distribution test for the generators should verify that preceding calls\nmay return words that contain (starting at index 0) words returned from later\ncalls.\n\n### Readme\n\n* Include examples of modifying Traits fields to restrict word characteristics.\n* Document what kind of input data is allowed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitranim%2Fcodex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmitranim%2Fcodex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitranim%2Fcodex/lists"}