Created
July 16, 2021 04:55
-
-
Save Kraiden/c97af7a3790cd9f09e6e9630c758925d to your computer and use it in GitHub Desktop.
Simple Markov word generator
This file contains 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
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