function calc(a, option, b) {
let res;
let formula;
if (option == '+') {
res = a.value + b.value;
formula=a.formula+'+'+b.formula;
}
else if (option == '-') {
res = a.value - b.value;
formula=a.formula+'-'+b.formula;
}
else if (option == '*') {
res = a.value * b.value;
formula=a.formula+'*'+b.formula;
}
else if (option == '/') {
res =a.value / b.value;
formula=a.formula+'/'+b.formula;
}
else if(option == '.'){
res=Number([a.value , b.value].join(""));
formula=a.formula+'.'+b.formula;
}
if (res < 0) {
res= NaN;
}
else if (res % 1 !== 0) {
res=NaN
}
return {
value:res,
formula:'('+formula+')',
};;
};
let cache = {};
function calcSum(nums, options, target) {
let cha=nums.length-1-options.length;
if(cha){
options.push(...'.'.repeat(cha))
}
cache={}
options.sort()
for(let i of nums){
cache[i]={
value:i,
formula:i,
}
}
calcLoop(nums, options, target)
};
function calcLoop(nums, options, target){
if (nums.length === 1 &&options.length==0&& cache[nums[0]].value == target) {
console.log(nums[0]);
return;
}
nums.sort()
let key=[...nums].join()+'|'+options.join();
if(cache[key]){
return
}
cache[key]=true
for (let i of '*+-/.') {
let index = options.indexOf(i);
if (index >= 0) {
let newOptions = [...options];
newOptions.splice(index, 1);
let len=nums.length
for (let j=0;j<len-1;j++) {
let newNums=[...nums];
newNums.splice(nums.indexOf(nums[j]), 1);
for(let k=j+1;k<len;k++){
let newNums2=[...newNums];
newNums2.splice(newNums2.indexOf(nums[k]), 1);
let newNum = calc(cache[nums[j]], i, cache[nums[k]])
if (isNaN(newNum.value)) {
}
else{
cache[newNum.formula]=newNum;
let t=[newNum.formula,...newNums2];
calcLoop(t, newOptions, target);
}
if(i!='+'&&i!='*'){
let newNum = calc(cache[nums[k]], i, cache[nums[j]]);
if (isNaN(newNum.value)) {
}
else{
cache[newNum.formula]=newNum;
let t=[newNum.formula,...newNums2];
calcLoop(t, newOptions, target);
}
}
}
}
}
}
}
第二代使用code calcSum(nums,options,target)
举例
calcSum([1,2,3,4,5],['+','-','*','/'],1)
calcSum([1,1,10,24],['*','*'],1024)
没测过,能用就行
-----------更新---------
class DigitalPuzzleSolution {
constructor( needNum = 5,uid = 0) {
this.targetNeedNum = needNum
if(!uid){
this.getUserInfo()
}
else{
this.uid = uid
}
this.cache = null
if (!this.isNative(console.log)) {
var _frame = document.createElement('iframe');
document.body.appendChild(_frame);
this.console = _frame.contentWindow.console
}
else {
this.console = console
}
this.LasVegasCalcNum=1000000
this.codeMap=null
window.calcSum=this.calcSum
window.calcSum2=this.calcSum2
window.getDigitalPuzzle=this.getDigitalPuzzle
this.optionTypes=''
this.suitOptionTypes=''
this.typeMax=2
}
isNative(method) {
return !!method && (/{\s*\[native code\]\s*}/.test(method + ""))
}
setNeedNum=(needNum = 5)=>{
this.targetNeedNum = needNum
}
setLasVegasCalcNum=(LasVegasCalcNum=1000000)=>{
this.LasVegasCalcNum=LasVegasCalcNum
}
setOptionTypesOrder=(optionTypes="")=>{
this.optionTypes=optionTypes
}
post=(url,done)=>{
var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', url, true);
httpRequest.setRequestHeader("Content-type","application/json; charset=utf-8");
httpRequest.setRequestHeader("authorization","Bearer "+this.authorization);
httpRequest.send();
let that=this
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var json = httpRequest.responseText;
done(JSON.parse(json))
}
};
}
get=(url,done)=>{
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', url, true);
httpRequest.send();
let that=this
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var json = httpRequest.responseText;
done&&done(JSON.parse(json))
}
};
}
getUserInfo=()=>{
let that=this
this.get('/user_api/v1/user/get',function(res){
if(res.err_no===0){
that.uid=res.data.user_id
}
else{
console.log('id获取失败')
}
})
}
getAuth=(done)=>{
let that=this
this.get('/get/token',function(res){
that.authorization=res.data
done()
})
}
getDigitalPuzzle=(type=0)=>{
if(type>=0&&type<this.typeMax){
this.type=type
}
if(!this.uid){
this.console.log('请先设置用户id 如:solution.setUid(12345678)')
return
}
let that=this
this.getAuth(function(){
that.post('https://juejin-game.bytedance.com/game/num-puzz/ugc/start?uid='+that.uid+'&time='+Date.now(),that.run)
})
}
run=(res)=>{
if(res.code===0){
let arg=this.getArgument(res.data)
if(arg){
this.console.log('数字:'+arg.nums+'\n符号:'+arg.options+'\n目标:'+arg.target+'\n所需'+this.targetNeedNum+'个解(如需要更多解请使用setNeedNum)\n解:')
if(this.type==0){
this.calcSum(arg.nums,arg.options,arg.target)
}
else if(this.type==1){
this.calcSum2(arg.nums,arg.options,arg.target)
}
else if(this.type==2){
this.calcSum3(arg.nums,arg.options,arg.target)
}
this.console.log('结束!')
return
}
}
this.console.log('获取参数错误')
}
getArgument(data){
let target=data.target
let nums=[]
let options=[]
let optionMap=['+','-','*','/']
for(let i of data.map){
for(let j of i){
if(j>=0){
if(j%1===0){
nums.push(j)
}
else{
let n=j*10-3
if(n>=0&&n<4){
options.push(optionMap[n])
}
}
}
}
}
return {target,nums,options}
}
setUid=(uid)=>{
this.uid = uid
}
calc(a, option, b){
let res;
let formula;
switch(option){
case '+':
res = a.value + b.value;break;
case '-':
res = a.value - b.value; break;
case '*':
res = a.value * b.value;break;
case '/':
res = a.value / b.value;break;
case '.':
res = Number(a.value +''+b.value);break;
default : ;
}
formula = a.formula + option + b.formula;
if (res < 0) {
res = NaN;
}
else if(res ===Infinity) {
res = NaN;
}
else if (res % 1 !== 0) {
res = NaN;
}
return {
value: res,
formula: '(' + formula + ')',
}
}
calcSum=(nums, options, target)=>{
let cha = nums.length - 1 - options.length;
this.cache = {};
if (cha) {
options.push(...'.'.repeat(cha))
}
this.nowNum = 0
options.sort()
let len = nums.length
for (let i = 0; i < len; i++) {
let num = nums[i]
this.cache[num] = {
value: num,
formula: '' + num,
}
nums[i] = '' + num;
}
nums.sort()
this.getSuiteOptionTypes(options)
this.calcLoop(nums, options, target)
this.cache = null;
};
calcLoop=(nums, options, target)=>{
let cache = this.cache
if (nums.length === 1 && options.length == 0 && cache[nums[0]].value == target) {
this.console.log(nums[0]);
this.nowNum++;
if (this.nowNum >= this.targetNeedNum) {
return true
}
return// nums[0]
}
nums=[...nums]
nums.sort()
let key = [...nums].join() + '|' + options.join();
if (cache[key]) {
return
}
cache[key] = true
for (let i of this.suitOptionTypes) {
let index = options.indexOf(i);
if (index >= 0) {
let newOptions = [...options];
newOptions.splice(index, 1);
let len = nums.length
for (let j = 0; j < len - 1; j++) {
let newNums = [...nums];
newNums.splice(j, 1);
for (let k = j + 1; k < len; k++) {
let newNums2 = [...newNums];
//newNums2.splice(newNums2.indexOf(nums[k]), 1);
let newNum = this.calc(cache[nums[j]], i, cache[nums[k]])
if (isNaN(newNum.value)) {
}
else {
cache[newNum.formula] = newNum;
newNums2[k-1]=newNum.formula//[newNum.formula, ...newNums2]
if (this.calcLoop(newNums2, newOptions, target)) return true;
}
if (i != '+' && i != '*') {
let newNum = this.calc(cache[nums[k]], i, cache[nums[j]]);
if (isNaN(newNum.value)) {
}
else {
cache[newNum.formula] = newNum;
newNums2[k-1]=newNum.formula
if (this.calcLoop(newNums2, newOptions, target)) return true;
}
}
}
}
}
}
}
calcSum2=(nums, options, target)=>{
let cha = nums.length - 1 - options.length;
this.cache = {};
if (cha) {
options.push(...'.'.repeat(cha))
}
this.nowNum = 0
options.sort()
let len = nums.length
nums.sort()
for (let i = 0; i < len; i++) {
let num = nums[i]
nums[i] = {
value: num,
formula: '' + num,
}
}
this.getSuiteOptionTypes(options)
this.calcLoop2(nums, options, target)
this.cache = null;
};
calcLoop2=(nums, options, target)=>{
let cache = this.cache
if (nums.length === 1 && options.length == 0 && nums[0].value == target) {
this.console.log(nums[0].formula);
this.nowNum++;
if (this.nowNum >= this.targetNeedNum) {
return true
}
return// nums[0]
}
let nums2= nums.map((v)=>v.value)
nums2.sort()
let key = nums2.join() + '|' + options.join();
if (cache[key]) {
return
}
cache[key] = true
for (let i of this.suitOptionTypes) {
let index = options.indexOf(i);
if (index >= 0) {
let newOptions = [...options];
newOptions.splice(index, 1);
let len = nums.length
for (let j = 0; j < len - 1; j++) {
let newNums = [...nums];
newNums.splice(j, 1);
for (let k = j + 1; k < len; k++) {
let newNums2 = [...newNums];
//newNums2.splice(newNums2.indexOf(nums[k]), 1);
let newNum = this.calc(nums[j], i, nums[k])
if (isNaN(newNum.value)) {
}
else {
newNums2[k-1]=newNum//[newNum.formula, ...newNums2]
if (this.calcLoop2(newNums2, newOptions, target)) return true;
}
if (i != '+' && i != '*') {
let newNum = this.calc(nums[k], i, nums[j]);
if (isNaN(newNum.value)) {
}
else {
newNums2[k-1]=newNum
if (this.calcLoop2(newNums2, newOptions, target)) return true;
}
}
}
}
}
}
}
getSuiteOptionTypes=(options)=>{
if(this.optionTypes){
this.suitOptionTypes=this.optionTypes
return
}
let obj={}
for(let i of options){
if(obj[i]){
obj[i]++
}
else{
obj[i]=1
}
}
let arr=[]
for(let i in obj){
arr.push({option:i,num:obj[i]})
}
arr.sort((a,b)=>b.num-a.num)
let type=''
for(let i of arr){
type+=i.option
}
this.suitOptionTypes=type
}
}
第3代封装为类,可以直接在游戏控制台使用,增加输出解数量功能(减少运算),自动获取数据(需在游戏界面)使用
//一定要创建对象
let solution=new DigitalPuzzleSolution(needNum,uid)//needNum所需解的数量(默认5条),uid ID,其实可以不填,不填会自动获取,如果不是在游戏界面,则填一个不是0的数,或自己的uid
//下面看自己情况使用
solution.calcSum([1,1,10,24],['*','*'],1024)
calcSum([1,1,10,24],['*','*'],1024)
solution.getDigitalPuzzle()
getDigitalPuzzle()
--------------------------更新--------------------------- 3.1代增加了calcSum2使用了更加狠的剪枝,去除重复策略,相比于calcSum全遍历,结果并不是很全面但是找到解的速度有了较大的提升
solution.calcSum2([2,2,3,4,5,6,15,26,62],['-','/','/','*','*','+','+','-'],2610)
calcSum2([2,2,3,4,5,6,15,26,62],['-','/','/','*','*','+','+','-'],2610)
solution.getDigitalPuzzle(1)
getDigitalPuzzle(1)
--------------------------更新--------------------------- 其实很早就做好了,还是放上来,免得以后丢了,观察到运算速度和符号顺序有很大关系所以增加了调整符号顺序的函数setOptionTypesOrder(),现在的默认顺序是按照符号数量从多到少排列
solution.setOptionTypesOrder('*+-/.')//5个都要