Skip to content

Instantly share code, notes, and snippets.

@Kraiden
Created July 16, 2021 04:55
Show Gist options
  • Save Kraiden/c97af7a3790cd9f09e6e9630c758925d to your computer and use it in GitHub Desktop.
Save Kraiden/c97af7a3790cd9f09e6e9630c758925d to your computer and use it in GitHub Desktop.
Simple Markov word generator
import kotlin.random.Random
/**
* A very simple, very dumb markov chain thing for generating made up names for a game I'm playing. Don't judge me on this.
*/
class Markov(input: List<String>){
val dict = HashMap<Char, MutableMap<Char?, Int>>()
private val starters = input.map { it.first() }
init {
input.forEach { name ->
for (i in name.indices){
var currentWeight = dict.getOrPut(name[i].toLowerCase()) { mutableMapOf() }
.getOrPut(name.getOrNull(i+1)?.toLowerCase()) { 0 }
currentWeight++
dict[name[i].toLowerCase()]?.set(name.getOrNull(i+1)?.toLowerCase(), currentWeight)
}
}
}
fun getName(): String {
var name = ""
var curr: Char? = starters.random()
while (curr != null ){
curr?.let{ name += it }
curr = dict[curr.toLowerCase()]?.weightedRandom()
if(name.length < 3){
var i = 0
while (curr == null) {
i++
if(i > 200) return "broken - $name"
curr = dict[name.last().toLowerCase()]?.weightedRandom()
}
}
}
return name
}
private fun Map<Char?, Int>.weightedRandom(): Char? {
val totalWeight = entries.sumBy { it.value }
val r = Random.nextDouble() * totalWeight
var countWeight = 0.0
entries.toList().sortedBy { it.value }.forEach {
countWeight += it.value
if(countWeight >= r) return it.key
}
return null
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment