java&python-APCS-2023/1/8實作第三題:先加後乘與函數 === ### ZeroJudge:j607先加後乘與函數-最簡易的暴力解 #### (java在最後面,寫法稍微和python不同,不過操作概念是相同的,可以搭配著看) --- \ \ \ \ \ <font color="#FFEE99">**1先加後乘**</font> --- :::info 範例: 5+3\*2+4\*8 二階段處理:先加,後乘 當加號先算的時候可以將一個運算式分成三部分,算完加號再乘在一起 5+3\*2+4\*8 (1) 5+3 (2) 2+4 (3) 8 這個時候我們可以使用split()的方法分割 (str)5+3\*2+4\*8-->(list)[5+3, 2+4, 8] 使用eval運算每一個元素 [5+3, 2+4, 8]-->[8, 6, 8] 然後全部乘在一起-->384 ::: ```python= def cou(num): num = num.split("*") result = 1 for i in num: result *= eval(i) return result ``` \ \ \ <font color="#FFEE99">**2取出f函數**</font> --- 取出一個f()的時候都發現他是多層的函數,這個時候就會有很大的困擾,但是我們可以反向來想,如果一次只拿一個單層的f()函數,那就沒有這個困擾了 :::info 核心: 當從前往後搜尋字串的時候,第一個遇到的右括號,可以決定一個f(),也就是說,我們遇到第一個右括號包成的是單層 ex:XXX(XX(XXX(XX<font color="#FFKE99">**)**</font>XXXX)) 我們發現這個右括號往前推的左括號所包的範圍是單層函數 ::: \ (回到程式碼) cou2負責計算單層的f() ser負責搜尋一個單層得f()並且用cou和cou2計算出這個單層f()的結果,並且把原本的f()替代成算好的結果 ```python= def cou2(num): num = num.split(",") for i in range(len(num)): num[i] = cou(num[i]) return max(num)-min(num) def ser(x): x = x.replace("f", "") left = right = 0 for i in range(len(x)): if x[i] == "(": left = i if x[i] == ")": right = i break ans = cou2(x[left+1:right]) return x.replace(x[left:right+1], str(ans)) ``` \ \ \ <font color="#FFEE99">**3主程式**</font> --- 1.if所執行的是70分測資 當")"還-->還有函數在裡面,就不斷取代掉 最後再用cou重新運算一次 2.else執行的是30分測資 ```python= x = input() if ")" in x: while ")" in x: x = ser(x) x = cou(x) print(x) else: print(cou(x)) ``` \ \ \ <font color="#FFEE99">**完整程式碼**</font> --- ```python= def cou(num): num = num.split("*") result = 1 for i in num: result *= eval(i) return result def cou2(num): num = num.split(",") for i in range(len(num)): num[i] = cou(num[i]) return max(num)-min(num) def ser(x): x = x.replace("f", "") left = right = 0 for i in range(len(x)): if x[i] == "(": left = i if x[i] == ")": right = i break ans = cou2(x[left+1:right]) return x.replace(x[left:right+1], str(ans)) x = input() if ")" in x: while ")" in x: x = ser(x) x = cou(x) print(x) else: print(cou(x)) ``` <font color="#FFEE99">**JAVA完整程式碼**</font> --- (java寫得比較漂亮一點) :::info **註:因為運算中數字可能超出int的限制,記得使用long** ::: ```java= package for_test; import java.util.*; public class apcs2023_01_3 { static String calculate(String x) { // method1 (score30) long timesSum = 1, plusSum = 0; String[] xArray = x.split("\\*"); for (String i : xArray) { plusSum = 0; for (String j : i.split("\\+")) { plusSum += Long.parseLong(j); } timesSum *= plusSum; } return Long.toString(timesSum); } static String calculateR(String[] x) { // method2 max-min for (int i = 0; i < x.length; i++) { x[i] = calculate(x[i]); } long max = Long.parseLong(x[0]), min = Long.parseLong(x[0]); for (String i : x) { if (max < Long.parseLong(i)) { max = Long.parseLong(i); } if (min > Long.parseLong(i)) { min = Long.parseLong(i); } } return Long.toString(max - min); } static String popAFunction(String x) { // method3 replace single f() with number calculated int left = 0,right = 0; for (int i = 0; i < x.length(); i++) { if (x.charAt(i) == '(') { left = i; } else if (x.charAt(i) == ')') { right = i; break; } } String ans = calculateR(x.substring(left+1, right).split("\\,")); return x.replace(x.substring(left, right+1), ans); } public static void main(String[] argv) { // main Scanner sc = new Scanner(System.in); String s = sc.nextLine(); sc.close(); s = s.replace("f", ""); while (s.contains(")")) { s = popAFunction(s); } s = calculate(s); System.out.println(s); } } ``` ###### tags: `題解` ###### tags: `APCS` ###### tags: `python` ###### tags: `java`