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`