≪ Today I learned. RSS購読
公開日
タグ
JavaScript
著者
ダーシノ(@bc_rikko)

「しかのこのこのここしたんたん」をマルコフ連鎖でつくる

「しかのこのこのここしたんたん」をマルコフ連鎖でつくる動画をみたので、実装してみる。

const target = "しかのこのこのここしたんたん" as const
cosnt loopLimit = 1_000

type Word = {
  [word: string]: {
    // key: 次にくる語、value: 確率(重み)
    [next: string]: number
  }
}

// 重み付けリスト
const shika: Readonly<Word> = {
    "し": { "か": 0.5, "た": 0.5, },
    "か": { "の": 1 },
    "の": { "こ": 1 },
    "こ": { "の": 0.5, "こ": 0.25, "し": 0.25 },
    "た": { "ん": 1 },
    "ん": { "た": 0.5, " ": 0.5 },
    " ": { " ": 0.5, "し": 0.5 }
} as const

// wordにmatcherが含まれるか判定する
const isMatch = (word: string, matcher: string) => {
  return word.slice(matcher.length * -1) === matcher
}

// 次に現れる語を取得する
const pick = (entries: [string, number][]) => {
  const rnd = Math.random()
  let sum = 0.0;
  for (const [word, weight] of entries) {
    sum += weight
    if (rnd < sum) {
      return word
    }
  }
}

let result = ""
let current = "し"

while (isMatch(result, target) === false && result.length < loopLimit) {
  result += current
  const entries = Object.entries(shika[current])
  current = pick(entries)
}

console.log(result)

デモ

output

参考