「しかのこのこのここしたんたん」をマルコフ連鎖でつくる
「しかのこのこのここしたんたん」をマルコフ連鎖でつくる動画をみたので、実装してみる。
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)