这题目有毒之干不过codewars的OJ系统(二)
kata
<4kyu>Guess the Digits and Expression
Description:
Give you a multiplication arithmetic expression:
ABC
* CBA
-------
= 39483
Each character represents a diffrent digit(1-9), and you need to find the arithmetic expression and return the result like this:"123 * 321 = 39483"
solutions
这是我的解决方案:
function guessExpression(exp){
let expression = ''
const reg = /\s*(\w+)\n\*\s*(\w+)\n.*\n[\D]*(\d+)/g
const unitArr = reg.exec(exp).slice(1)
const [aDigit, bDigit] = unitArr
const aDigitLast = aDigit[aDigit.length - 1]
const bDigitLast = bDigit[bDigit.length - 1]
const digitList = [...new Set(aDigit)]
const numResult = parseInt(unitArr[2])
const isOdd = numResult % 2 === 1
function vEach(strs, stat = {}) {
const firstStr = strs[0]
for (let i of [1, 2, 3, 4, 5, 6, 7, 8, 9]) {
if (expression) return
stat[firstStr] = i
if (strs.length > 1) {
vEach(strs.slice(1), stat)
} else {
const realADigit = [].map.call(aDigit, v => stat[v]).join('')
const realBDigit = [].map.call(bDigit, v => stat[v]).join('')
if (realADigit[0] && realBDigit[0] && (~~realADigit * ~~realBDigit === numResult)) {
expression = `${realADigit} * ${realBDigit} = ${numResult}`
if (realADigit.split('').reverse().join('') === realBDigit) {
const min = Math.min(~~realADigit, ~~realBDigit)
const max = Math.max(~~realADigit, ~~realBDigit)
expression = `${min} * ${max} = ${numResult}`
}
}
}
}
}
vEach(digitList.join(''))
return expression
}
提交时报错:execution time out 12000ms
后来想到如果乘积为奇数,则两乘数也为奇数,如果乘积为偶数,则两乘数必有一个为偶数
所以有如下的优化:
......
const firstStr = strs[0]
let mapArr = []
if (isOdd) {
if (firstStr === aDigitLast || firstStr === bDigitLast) {
mapArr = [1, 3, 5, 7, 9]
} else {
mapArr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
} else {
if (firstStr === aDigitLast || firstStr === bDigitLast) {
if (aDigitLast % 2 === 1 && firstStr !== aDigitLast) {
mapArr = [2, 4, 6, 8]
} else if (bDigitLast % 2 === 1 && firstStr !== bDigitLast) {
mapArr = [2, 4, 6, 8]
} else {
mapArr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
} else {
mapArr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
for (let i of mapArr) {
if (expression) return
......
然而并没有什么卵用,执行时间几乎和之前的算法一样。
如此,在网络上搜索相关答案,找到某大佬的解决方案:
function guessExpression(exp) {
let m = exp.match(/([\w\d]+)/g);
let sym = [m[0], m[1]];
let res = +m[2];
let uniq = (sym[0] + sym[1]).split('')
.filter((el, i, arr) => arr.indexOf(el, i+1) === -1);
let nums = new Array(uniq.length).fill(1);
// brute force
while (1) {
let a = sym[0].replace(/./g, c => nums[uniq.indexOf(c)]);
let b = sym[1].replace(/./g, c => nums[uniq.indexOf(c)]);
if ((+a) * (+b) === res) {
return `${a} * ${b} = ${res}`;
}
for (let i = 0; i < nums .length; ++i) {
nums[i] += 1;
if (nums[i] >= 10) {
nums[i] = 1;
} else {
break;
}
}
}
}
使用console.time
测试了下,大佬的解法用时几乎是我解法的一半。
令人沮丧的是:codewars的OJ用大佬的解法也没有通过测试,我不知道要如何optimize my solution.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2016-04-27 ES5中新增的Array方法详细说明
2016-04-27 Codewars-Javascript训练手册:正则表达式(上)
2016-04-27 Codewars-Javascript训练手册:正则表达式(Regular Expressions)