如何从原子单词形状生成所有可能的单词?
Posted
技术标签:
【中文标题】如何从原子单词形状生成所有可能的单词?【英文标题】:How to generate all possible words from atomic word shapes? 【发布时间】:2021-09-16 01:43:25 【问题描述】:我正在处理这段代码:
const vowels = ['i', 'a', 'u', 'e', 'E', 'U', 'I', 'o', 'A', 'O', 'o#', 'u#', 'e#', 'i#', 'a#']
const consonants = ['m', 'n', 'q', 'g', 'd', 'b', 'p', 't', 'k', 'h', 'l', 'w', 'f', 's', 'C', 'z', 'v', 'y', 'x', 'r', 'c', 'j', 'Q', 'S', 'Z', '\'']
const tones = ['', '+', '-']
const shapes = [
'ccvt1vt2',
'cvt1vt2',
'cvt',
'ccvt',
'c!vt',
]
const words =
shapes.forEach(shape =>
words[shape] = generate(shape)
)
function generate(shape)
const sets =
v: vowels,
c: consonants,
t: tones
const selectors =
const nodes = []
shape.replace(/(\w)(\d)?/g, (_, $1, $2 = '') =>
selectors[`$$1$$2`] = sets[$1]
nodes.push(`$$1$$2`)
return _
)
// getting lost here
nodes.forEach(node =>
)
function randomBetween(min, max)
return Math.floor(Math.random() * (max - min + 1)) + min
console.log(words)
shapes
数组有如下内容:ccvt1vt2
,其中c
表示辅音,v
表示元音,t
表示音调(来自上述 3 组)。类型旁边的数字只是使我们有不相关的值,而像 cc
这样的相同键表示相同的辅音两次,而 c1c2
表示两个不同的辅音。
目标是生成shape
的所有可能组合。我们该怎么做?
对于这个形状cvt
,我们会开始看到这个结果:
mi
me
ma
mo
mu
...
mi+
me+
ma+
...
ni
ne
na
no
nu
...
我已经尝试过的是:
function cartesian()
var arr = [].slice.call(arguments),
intLength = arr.length,
arrHelper = [1],
arrToReturn = [];
for (var i = arr.length - 1; i >= 0; i--)
arrHelper.unshift(arrHelper[0] * arr[i].length);
for (var i = 0, l = arrHelper[0]; i < l; i++)
arrToReturn.push([]);
for (var j = 0; j < intLength; j++)
arrToReturn[i].push(arr[j][(i / arrHelper[j + 1] | 0) % arr[j].length]);
return arrToReturn;
const vowels = [
'i',
'a',
'u',
'e',
'E',
'U',
'I',
'o',
'A',
'O',
'o#',
'u#',
'e#',
'i#',
'a#',
]
const consonants = [
'm',
'n',
'q',
'g',
'd',
'b',
'p',
't',
'k',
'h',
'l',
'w',
'f',
's',
'C',
'z',
'v',
'y',
'x',
'r',
'c',
'j',
'Q',
'S',
'Z',
'\'',
]
const tones = [
'',
'+',
'-',
]
const nasals = [
'',
'~',
]
const pharyngeals = [
'',
'~',
]
const ejectives = [
'',
'!',
]
const implosives = [
'',
'?',
]
const shapes = [
'ccvt1vt2',
'cvt1vt2',
'cvt',
'ccvt',
'c!vt',
]
const words =
shapes.forEach(shape =>
words[shape] = generate(shape)
)
function generate(shape)
const sets =
v: vowels,
c: consonants,
t: tones,
n: nasals,
p: pharyngeals
const selectors =
const string = []
shape.replace(/(\w)(\d)?/g, (_, $1, $2 = '') =>
selectors[`$$1$$2`] = sets[$1]
string.push(`$$1$$2`)
return _
)
const keys = Object.keys(selectors)
const values = keys.map(selector => selectors[selector])
const combinations = cartesian(...values)
.map(nodes =>
const map =
nodes.forEach((node, i) => map[keys[i]] = node)
return map
)
const result = []
combinations.forEach(combination =>
const out = shape.replace(/(\w+)/g, (_, $1) =>
return combination[$1]
)
result.push(out)
)
return result
function randomBetween(min, max)
return Math.floor(Math.random() * (max - min + 1)) + min
这里是生成随机值的版本,内存中存储的值太多了。
const vowels = [
'i',
'a',
'u',
'e',
'E',
'U',
'I',
'o',
'A',
'O',
'o#',
'u#',
'e#',
'i#',
'a#',
]
const consonants = [
'm',
'n',
'q',
'g',
'd',
'b',
'p',
't',
'k',
'h',
'l',
'w',
'f',
's',
'C',
'z',
'v',
'y',
'x',
'r',
'c',
'j',
'Q',
'S',
'Z',
'\'',
]
const tones = [
'',
'+',
'-',
]
const nasals = [
'',
'~',
]
const focusings = [
'',
'~',
'=',
'Y',
'w',
'h',
]
const explosivities = [
'',
'!',
'?',
]
const shapes = [
'cfevtn',
'cfevt1nvt2n',
'cfecfevtn',
'cfecfevt1nvt2n',
'c1f1e1c2f2e2vtn',
'cfev1tnv2tn',
'cfecfev1tnv2tn',
]
function generate()
const sets =
v: vowels,
c: consonants,
t: tones,
n: nasals,
f: focusings,
e: explosivities
const shape = shapes[randomBetween(0, shapes.length - 1)]
const selectors =
const string = []
shape.replace(/(\w)(\d)?/g, (_, $1, $2 = '') =>
selectors[`$$1$$2`] = sets[$1]
string.push(`$$1$$2`)
return _
)
const values =
Object.keys(selectors).forEach(selector =>
const set = selectors[selector]
const idx = randomBetween(0, set.length - 1)
values[selector] = set[idx]
)
const result = string.map(selector => values[selector]).join('')
return result
function randomBetween(min, max)
return Math.floor(Math.random() * (max - min + 1)) + min
console.log(generate())
console.log(generate())
console.log(generate())
console.log(generate())
【问题讨论】:
试图使其更具可读性!
是什么意思?
到目前为止,您尝试了哪些方法来自行解决此问题?它有什么问题?
@Andreas 我添加了我的尝试,我猜对了吗?
如果您有工作代码,但正在寻找更简单、更清洁、更高效、更优雅等,那么Code Review 更合适。另外:“这是一个生成随机值的版本”:我不明白为什么会出现在您的问题中,因为您明确 要求 生成 all 可能性。它使问题变得混乱。你是在随机生成之后还是在完全生成之后?
【参考方案1】:
这不是您问题的确切答案——因此我向 Stack Overflow 纯粹主义者道歉——但它可能对您有所帮助,具体取决于您的目标。所以我想无论如何我都会分享。 :)
Typescript 的template literal types 可以帮助我们。我们首先定义一些字符串联合类型:
type Vowel = 'i' | 'a' | 'u' | 'e' | 'E' | 'U' | 'I' | 'o' | 'A' | 'O' | 'o#' | 'u#' | 'e#' | 'i#' | 'a#'
type Consonant = 'm' | 'n' | 'q' | 'g' | 'd' | 'b' | 'p' | 't' | 'k' | 'h' | 'l' | 'w' | 'f' | 's' | 'C' | 'z' | 'v' | 'y' | 'x' | 'r' | 'c' | 'j' | 'Q' | 'S' | 'Z' | '\''
type Tone = '' | '+' | '-'
这让我们可以使用模板文字类型来为给定的形状/模式创建每个枚举;例如,对于'cvt'
:
type ShapeString = `$Consonant$Vowel$Tone`
这反过来又允许我们定义一个mapped type,它代表我们的ShapeString
的字典:
type EveryCombinationOfShapeString = [K in ShapeString]: K
现在您的 IDE 应该能够帮助枚举该类型的对象:
const Dictionary: EveryCombinationOfShapeString =
// ...
"Ce-": 'Ce-',
"Ci#": 'Ci#',
"Ci#+": 'Ci#+',
"Ci#-": 'Ci#-',
// ...
^ 我不会在这里发布整个内容,因为它已经有 1000 多行,只有 3 个字符,但我可以确认 WebStorm 能够在大约 30 秒左右为我实现这个对象的所有成员。
我知道这忽略了您问题的c1c1
方面,并且还引入了一种新语言,但我希望它仍然会有所帮助。也许您可以在该对象上使用Object.values
并进行一些额外的过滤/映射。
(为清晰起见进行编辑、重命名、文档链接等)
【讨论】:
是的,我承认这一点。但是,它确实会生成一个 js 对象,可以帮助提问者更接近问题的解决方案:) "也许您可以在该对象上使用 Object.values" 整个问题是如何生成所有可能的值。我不认为“手动生成所有排列然后获取它们”是一个非常好的方法。 不是手工制作的。一个称职的 ide 可以实现给定接口的成员;这就是重点以上是关于如何从原子单词形状生成所有可能的单词?的主要内容,如果未能解决你的问题,请参考以下文章
从给定的单词列表中生成具有“N”长度的所有可能组合(寻找不重复)