橋樑修復
代碼來臨 2024 年第 7 天
第 1 部分
今年第一次遞迴
至少這就是我今天想要贏得一顆金星的方式:
- 從完整清單開始
- 檢查加法和乘法
- 對於每個結果,繼續列表的其餘部分
- 直到我超過或匹配總數
困難在於細節。
讓我們開始吧!
制定我的演算法
首先,我需要將每一行解析為數字列表:
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 來使遞歸不再是可行的解決方案。
第2部分
完全出乎意料!而且難度更高
我該怎麼做?
...
幾天後...
回顧一下我的思考過程:
- 就像在我的退貨條件中添加第三個條款一樣簡單嗎? 不
- 我的第 1 部分遞歸函數是否配置正確才能成功? 不
- 哦,不,透過先前的操作累積金額是否可行? 不
- 我真的需要用新策略來解決這個問題嗎? 是的
考慮所有新的變化
對於這個方程式:
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) } }
- i 用於沿著數字列表
- 只有當 i 位於倒數第二個索引之前或位於倒數第二個索引時,最後一個子句才會繼續
函數取得四個值:
- 數字清單的副本,減去預期總數
- 下一個索引
- 由三個字串之一連接而成的方程式字串
- 相同的測試號碼
我使用與第 1 部分幾乎相同的簽名來呼叫該函數:
let part1 = eqs.reduce((count, eq) => { if (eqChecker(eq.slice(2), eq[1], eq[0])) { count += eq[0] } return count }, 0)
差別在於我作為參數傳遞的內容:
- 沒有預期總金額的清單
- 從索引 0 開始
- 包含第一個數字的字串
- 預計總金額
好消息:
- 它產生所有方程式變化
壞消息:
- 它使用 PEMDAS 計算所有方程,而不是從左到右
我應該更清楚...內建的 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"
我用空格填充每個運算符,只是將其用作分隔符。
關於這個方程式部分列表的事實:
- 它將始終包含 3 個或更多的奇數項目
如何在迭代每個操作數-運算符-操作數對的循環中利用這一事實?
這是我的想法:
- 刪除前三項
- 將它們作為字串連接,並將其作為數學表達式進行計算
- 將結果重新附加到方程式清單的開頭
- 重複直到方程式列表為空
希望它能起作用!
我在 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中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。
