至少這就是我今天想要贏得一顆金星的方式:
困難在於細節。
讓我們開始吧!
首先,我需要將每一行解析為數字列表:
let eqs = input.split('\n').map(line => { return [...line.matchAll(/\d+/g)].map(el => +el[0]) })
第一個元素是所需的總數。
其餘的是方程式的有序操作數。
我需要在遞歸函數中考慮到這一點。
這是我的遞迴函數:
function eqChecker(operands, amount, test) { if (amount > test) { return false } else if (amount == test && operands.length == 0) { return true } else if (operands.length) { let copy = operands.slice() let first = copy.shift() return eqChecker(copy, amount + first, test) || eqChecker(copy, amount * first, test) } }
這是使用它的reduce:
let part1 = eqs.reduce((count, eq) => { if (eqChecker(eq.slice(2), eq[1], eq[0])) { count += eq[0] } return count }, 0)
正如我所希望但從未預料到的,它為範例輸入產生了正確的答案!
它會完成處理我的拼圖輸入嗎?
如果是這樣,它會產生正確的答案嗎?
老實說我不確定......
確實如此! ! !
哇! ! !
儘管我很興奮,但我擔心下一部分要么會添加更多運算符,要么需要一些高級 CS 來使遞歸不再是可行的解決方案。
我該怎麼做?
...
幾天後...
回顧一下我的思考過程:
對於這個方程式:
292: 11 6 16 20
給定三個運算符,這些都是可能的方程式:
11 11+6 11+6+16 11+6+16+20 11+6+16*20 11+6+1620 11+6*16 11+6*16+20 11+6*16*20 11+6*1620 11+616 11*6 11*6+16 11*6+16+20 11*6+16*20 11*6+1620 11*6*16 11*616 116 116+16 116+16+20 116+16*20 116+1620 116*16 11616
也許我可以建立每個方程式的字串,並在遞歸函數中手動對其求值。
例如:
我在最外層函數呼叫中以空字串開始:
""
從那裡,我使用下一個數字創建三個變體:
"" + "+N" "" + "*N" "" + "N"
嗯,但這對第一個數字不起作用。
我需要用第一個數字開始我的第一個函數調用,而不是空字串:
"N"
同樣的事情:
"N" + "+N" "N" + "*N" "N" + "N"
是的,應該可以。
最後,我將獲得這些範例變體,所有這些都可以評估:
let eqs = input.split('\n').map(line => { return [...line.matchAll(/\d+/g)].map(el => +el[0]) })
我寫的程式碼成功產生了方程式的所有變體。
function eqChecker(operands, amount, test) { if (amount > test) { return false } else if (amount == test && operands.length == 0) { return true } else if (operands.length) { let copy = operands.slice() let first = copy.shift() return eqChecker(copy, amount + first, test) || eqChecker(copy, amount * first, test) } }
函數取得四個值:
我使用與第 1 部分幾乎相同的簽名來呼叫該函數:
let part1 = eqs.reduce((count, eq) => { if (eqChecker(eq.slice(2), eq[1], eq[0])) { count += eq[0] } return count }, 0)
差別在於我作為參數傳遞的內容:
好消息:
壞消息:
我應該更清楚...內建的 JavaScript 求值器會預設使用正確的操作順序,而不是從左到右。
這確實給我的演算法帶來了更大的麻煩:
嗚嗚嗚。
謝天謝地,我想我知道該怎麼做。
我需要 JavaScript 來計算這樣的方程式:
292: 11 6 16 20
依此順序:
11 11+6 11+6+16 11+6+16+20 11+6+16*20 11+6+1620 11+6*16 11+6*16+20 11+6*16*20 11+6*1620 11+616 11*6 11*6+16 11*6+16+20 11*6+16*20 11*6+1620 11*6*16 11*616 116 116+16 116+16+20 116+16*20 116+1620 116*16 11616
我想將方程式分成幾個部分:
""
我了解的唯一方法是使用這個三鏈表達式:
"" + "+N" "" + "*N" "" + "N"
我用空格填充每個運算符,只是將其用作分隔符。
關於這個方程式部分列表的事實:
如何在迭代每個操作數-運算符-操作數對的循環中利用這一事實?
這是我的想法:
希望它能起作用!
我在 JavaScript 工作的數學模擬器:
"N"
好消息:
壞消息:
我不斷產生的答案比預期答案少了大約 7k。
這讓我認為我的演算法沒有辨識出這個方程式是正確的:
let eqs = input.split('\n').map(line => { return [...line.matchAll(/\d+/g)].map(el => +el[0]) })
在範例輸入的解釋中,這是獲勝方程式:
function eqChecker(operands, amount, test) { if (amount > test) { return false } else if (amount == test && operands.length == 0) { return true } else if (operands.length) { let copy = operands.slice() let first = copy.shift() return eqChecker(copy, amount + first, test) || eqChecker(copy, amount * first, test) } }
我的演算法評估該方程式並產生以下結果:
let part1 = eqs.reduce((count, eq) => { if (eqChecker(eq.slice(2), eq[1], eq[0])) { count += eq[0] } return count }, 0)
那是因為我的演算法是這樣運作的:
292: 11 6 16 20
我不明白它怎麼可能是其他數字。
所以...我用谷歌搜尋了。
我找到了我的答案,它一如既往地隱藏在簡單的網站解釋中:
所有運算子仍然從左到右計算。
我在每個遞歸函數呼叫中預先連接值。
相反,我的演算法應該要這樣做:
11 11+6 11+6+16 11+6+16+20 11+6+16*20 11+6+1620 11+6*16 11+6*16+20 11+6*16*20 11+6*1620 11+616 11*6 11*6+16 11*6+16+20 11*6+16*20 11*6+1620 11*6*16 11*616 116 116+16 116+16+20 116+16*20 116+1620 116*16 11616
現在我明白了應該發生什麼,我可以調整我的演算法以匹配該處理行為嗎?
值得慶幸的是,調整我的演算法相對容易。
我新增了一個replaceAll()子句來解釋||。
我處理每三個項目的新 while 迴圈如下:
""
我調整了退貨聲明的||子句包含這些字符,而不是立即連接兩個數字。
我在範例輸入上運行了演算法。
它終於產生了正確的答案! !
多麼輕鬆啊! !
我想知道它是否會完成運行並在我的拼圖輸入上產生正確的答案。
按運行...
...
...
我得到答案了!
它很大,所以這可能是一個好兆頭。
這是正確答案嗎?
...
不。太高了。
真糟糕。
我的獲勝方程式的條件很簡單,就是處理後的數學等於測試量。
但是,如果其中一個變體方程式允許數字子集產生正確答案怎麼辦?
為了捕捉並排除這種情況,我更新了 if 條件以包含另一個子句:
"" + "+N" "" + "*N" "" + "N"
這樣,只有當所有數字都處理完畢且結果數量等於測試數時,方程式才會被計算在內。
大問題:
再按下運作...
...
嗯,看起來確實還是一樣的答案。
哦,等等,末尾附近有兩個數字不同!
我的新答案比以前少了 80。
是否有一個以 80 為預期數量的方程式?
是的!
"N"
有沒有一種方法可以在不使用所有數字的情況下得到 80?
是的!
"N" + "+N" "N" + "*N" "N" + "N"
這是我唯一需要排除的邊緣情況嗎?
正在提交我的新答案...
正確! ! !
嗚呼! ! !
我做到了! ! !
那個。曾是。筋疲力盡。令人興奮。而且真的跑了。並且具有挑戰性。
以及我喜歡做這些謎題的所有原因。
繼續下一篇!
以上是橋樑修復的詳細內容。更多資訊請關注PHP中文網其他相關文章!