Skip to content

Instantly share code, notes, and snippets.

@Kraiden
Created July 16, 2021 04:55
Show Gist options
  • Select an option

  • Save Kraiden/c97af7a3790cd9f09e6e9630c758925d to your computer and use it in GitHub Desktop.

Select an option

Save Kraiden/c97af7a3790cd9f09e6e9630c758925d to your computer and use it in GitHub Desktop.

Revisions

  1. Kraiden created this gist Jul 16, 2021.
    54 changes: 54 additions & 0 deletions Markov.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    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
    }
    }