Java 11, 1325 1379 1356 1336 1290 byte
import java.math.*;String c(String s)throws Exception{String r="",T=r,a[],b[],z="\\.";int i=0,l,A[],M=0,m=s.length(),j,f=0,q=m;if(s.contains("(")){for(;i<m;){var c=s.charAt(i++);if(f<1){if(c==40){f=1;continue;}r+=c;}else{if(c==41&T.replaceAll("[^(]","").length()==T.replaceAll("[^)]","").length()){r+="x"+s.substring(i);break;}T+=c;}}return c(r.replace("x",c(T)));}else{for(a=s.split("[\\+\\-\\*/]"),A=new int[l=a.length];i<l;f=b.length>1&&(j=b[1].length())>f?j:f)M=(j=(b=a[i++].split(z))[0].length())>M?j:M;for(b=a.clone(),i=0;i<l;A[i]=b[i].contains(".")?j=b[i].length()-1:b[i].replaceAll("0*$","").length(),i++)for(q=(j=b[i].replace(".","").length())<q?j:q,j=a[i].split(z)[0].length();j++<M;)b[i]=0+b[i];double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+""),p;for(int x:A)m=x<m?x:m;m=m==M&R%1==0&(int)R/10%10<1&(j=(r=R+"").split(z)[0].length())>m?j-q>1?q:j:R>99?m:R%10==0?r.length()-1:m<1?1:m;R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();r=(m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R)+"";l=r.length()-2;r=(r=f<1?r.replaceAll(z+"0$",""):r+"0".repeat(f)).substring(0,(j=r.length())<m?j:r.contains(".")?(j=r.replaceAll("^0\\.0+","").length())<m?m-~j:m+1:m);for(i=r.length();i++<l;)r+=0;return r.replaceAll(z+"$","");}}
+54 byte để sửa trường hợp cạnh 501*2.0
(đã cho kết quả 1002
trước đó, nhưng bây giờ đúng 1000
).
Bây giờ tôi đã hiểu tại sao thử thách này không được trả lời trong gần hai năm ..>.> Thử thách này có nhiều trường hợp đặc biệt hơn tiếng Hà Lan, điều đang nói điều gì đó ..
Java chắc chắn không phải là ngôn ngữ phù hợp cho những thách thức này (hoặc bất kỳ loại tiền mã hóa nào thách thức cho vấn đề đó ..; p), nhưng đó là ngôn ngữ duy nhất tôi biết đủ tốt để thậm chí thực hiện một thử thách khó khăn như thế này.
Định dạng đầu vào như String
không có khoảng trắng (nếu điều đó không được phép, bạn có thể thêm s=s.replace(" ","")
(+19 byte) ở đầu phương thức).
Hãy thử trực tuyến.
Giải trình:
Xin lôi vi bai đăng dai.
if(s.contains("(")){
for(;i<m;){
var c=s.charAt(i++);
if(f<1){
if(c==40){
f=1;
continue;}
r+=c;}
else{
if(c==41&T.replaceAll("[^(]","").length()==T.replaceAll("[^)]","").length()){
r+="x"+s.substring(i);
break;}
T+=c;}}
return c(r.replace("x",c(T)));}
Phần này được sử dụng cho đầu vào có chứa dấu ngoặc đơn. Nó sẽ nhận được các phần riêng biệt và sử dụng các cuộc gọi đệ quy.
0.4*(2*6)
trở thành 0.4*A
, nơi A
một cuộc gọi đệ quy đếnc(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)
trở thành A+B
, nơi A
một cuộc gọi đệ quy đến c(8.3*0.02)
và B
một cuộc gọi đệ quy đến c(1.*(9*4)+2.2)
→ lần lượt trở thành 1.*C+2.2
, C
cuộc gọi đệ quy đếnc(9*4)
for(a=s.split("[\\+\\-\\*/]"),A=new int[l=a.length];
i<l;
f=b.length>1&&(j=b[1].length())>f?j:f)
M=(j=(b=a[i++].split(z))[0].length())>M?j:M;
Vòng lặp đầu tiên này được sử dụng để điền vào các giá trị M
và k
, trong đó M
độ dài số nguyên lớn nhất liên quan đến các số liệu có ý nghĩa và k
độ dài số thập phân lớn nhất.
1200+3.0
trở thành M=2, k=1
( 12, .0
)
999+2.00
trở thành M=3, k=2
( 999, .00
)
300.+1-300.
trở thành M=3, k=0
( 300, .
)
for(b=a.clone(),i=0;
i<l;
A[i]=b[i].contains(".")?j=b[i].length()-1:b[i].replaceAll("0*$","").length(),i++)
for(q=(j=b[i].replace(".","").length())<q?j:q,
j=a[i].split(z)[0].length();
j++<M;)
b[i]=0+b[i];
Vòng lặp thứ hai này được sử dụng để điền vào các mảng A
và b
cũng như giá trị q
, trong đó A
số lượng các số liệu có ý nghĩa, b
giữ các số nguyên với các số 0 đứng đầu để khớp M
và q
là các chấm có độ dài thấp nhất.
1200+3.0
trở thành A=[2, 5] (12, 00030)
, b=[1200, 0003.0]
và q=2
( 30
)
999+2.00
trở thành A=[3, 5] (999, 00200)
, b=[999, 002.00]
và q=3
(cả hai 999
và 200
)
300.+1-300.
trở thành A=[3, 3, 3] (300, 001, 300)
, b=[300., 001, 300.]
và q=1
( 1
)
501*2.0
trở thành A=[3, 4] (501, 0020)
, b=[501, 002.0]
và q=2
( 20
)
double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+"")
Sử dụng một công cụ JavaScript để đánh giá đầu vào, sẽ được lưu R
thành hai lần.
1200+3.0
trở thành R=1203.0
999+2.00
trở thành R=1001.0
300.+1-300.
trở thành R=1.0
for(int x:A)
m=x<m?x:m;
Điều này đặt m
thành giá trị nhỏ nhất trong mảng A
.
A=[2, 5]
trở thành m=2
A=[3, 5]
trở thành m=3
A=[3, 3, 3]
trở thành m=3
m=m==M // If `m` equals `M`
&R%1==0 // and `R` has no decimal values (apart from 0)
&(int)R/10%10<1 // and floor(int(R)/10) modulo-10 is 0
&(j=(r=R+"").split(z)[0].length())>m?
// and the integer-length of R is larger than `m`:
j-q>1? // If this integer-length of `R` minus `q` is 2 or larger:
q // Set `m` to `q` instead
: // Else:
j // Set `m` to this integer-length of `R`
:R>99? // Else-if `R` is 100 or larger:
m // Leave `m` the same
:R%10==0? // Else-if `R` modulo-10 is exactly 0:
r.length()-1 // Set `m` to the total length of `R` (minus the dot)
:m<1? // Else-if `m` is 0:
1 // Set `m` to 1
: // Else:
m; // Leave `m` the same
Điều này sửa đổi m
dựa trên nhiều yếu tố.
999+2.00 = 1001.0
& m=3,q=3
trở thành m=4
(vì m==M
(cả hai 3
) → R%1==0
( 1001.0
không có giá trị thập phân) → (int)R/10%10<1
( (int)1001.0/10
trở thành 100
→ 100%10<1
) → "1001".length()>m
( 4>3
) → "1001".length()-q<=1
( 4-3<=1
) → vì vậy m
trở thành độ dài của phần nguyên "1001"
( 4
))
3.839*4 = 15.356
& m=1,q=1
stay m=1
(vì m==M
(cả hai 1
) → R%1!=0
( 15.356
có giá trị thập phân) → R<=99
→ R%10!=0
( 15.356%10==5.356
) → m!=0
→ vì vậy m
giữ nguyên ( 1
))
4*7*3 = 84.0
& m=1,q=1
stay m=1
(vì m==M
(cả hai 1
) → R%1==0
( 84.0
không có giá trị thập phân) → (int)R/10%10>=1
( (int)84/10
trở thành 8
→ 8%10>=1
) → R<=99
→ R%10!=0
( 84%10==4
) → m!=0
→ vì vậy m
giữ nguyên ( 1
))
6.0+4.0 = 10.0
& m=2,q=2
trở thành m=3
(vì m!=M
( m=2, M=1
) → R<=99
→ R%10==0
( 10%10==0
) → vì vậy m
trở thành độ dài của tổng R
(trừ dấu chấm) "10.0".length()-1
( 3
))
0-8.8 = -8.8
& m=0,q=1
trở thành m=1
(vì m!=M
( m=0, M=1
) → R<=99
→ R%10!=0
( -8.8%10==-8.8
) → m<1
→ vì vậy m
trở thành 1
)
501*2.0 = 1001.0
& m=3,q=2
trở thành m=2
(vì m==M
(cả hai 3
) → R%1==0
( 1001.0
không có giá trị thập phân) → (int)R/10%10<1
( (int)1001.0/10
trở thành 100
→ 100%10<1
) → "1001".length()>m
( 4>3
) → "1001".length()-q>1
( 4-2>1
) → vì vậy m
trở thành q
( 2
))
R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();
Bây giờ R
được làm tròn dựa trên m
.
1001.0
& m=4
trở thành1001.0
0.258
& m=3
trở thành 0.26
(bởi vì abs(R)<1
, m-1
( 2
) thay vì m=3
được sử dụng bên trong MathContext
)
-8.8
& m=1
trở thành-9.0
1002.0
& m=2
trở thành1000.0
m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R;
Điều này sửa đổi phần nguyên R
nếu cần thiết.
300.+1-300. = 1.0
& m=3,M=3
stay 1.0
(vì m>=M
→ vì vậy R
giữ nguyên ( 1.0
))
0.4*10 = 4.0
& m=1,M=2
ở lại 4.0
(vì m<M
→ (10^(M-m))/10<=R
( (10^1)/10<=4.0
→ 10/10<=4.0
→ 1<=4.0
) → vì vậy R
giữ nguyên ( 4.0
))
300+1-300 = 1.0
& m=1,M=3
trở thành 0.0
(vì m<M
→ (10^(M-m))/10>R
( (10^2)/10>1.0
→ 100/10>1.0
→ 10>1.0
) → vì vậy R
trở thành 0.0
vì int(R/(10^(M-m)))*(10^(M-m))
( int(1.0/(10^2))*(10^2)
→ int(1.0/100)*100
→ 0*100
→ 0
)
r=(...)+""; // Set `R` to `r` as String (... is the part explained above)
l=r.length()-2; // Set `l` to the length of `R` minus 2
r=(r=k<1? // If `k` is 0 (no decimal values in any of the input-numbers)
r.replaceAll(z+"0$","")
// Remove the `.0` at the end
: // Else:
r+"0".repeat(f)
// Append `k` zeroes after the current `r`
).substring(0, // Then take the substring from index `0` to:
(j=r.length())<m? // If the total length of `r` is below `m`:
j // Leave `r` the same
:r.contains(".")? // Else-if `r` contains a dot
(j=r.replaceAll("^0\\.0+","").length())<m?
// And `R` is a decimal below 1,
// and its rightmost decimal length is smaller than `m`
m-~j // Take the substring from index 0 to `m+j+1`
// where `j` is this rightmost decimal length
: // Else:
m+1 // Take the substring from index 0 to `m+1`
: // Else:
m); // Take the substring from index 0 to `m`
Cái này đặt R
thành r
String và sửa đổi nó dựa trên nhiều yếu tố.
1203.0
& m=4,k=2
trở thành 1203.
(vì k>=1
→ vì vậy r
trở thành 1001.000
; r.length()>=m
( 8>=4
) → r.contains(".")
→ r.length()>=m
( 8>=4
) → chuỗi con từ chỉ mục 0
đến m+1
( 5
))
6.9
& m=2,k=2
stay 6.9
(vì k>=1
→ vì vậy r
trở thành 6.900
; r.length()>=m
( 5>=2
) → r.contains(".")
→ r.length()>=m
( 5>=2
) → chuỗi con từ chỉ mục 0
đến m+1
( 3
))
1.0
& m=3,k=0
trở thành 1
(vì k<1
→ vì vậy r
trở thành 1
; r.length()<m
( 1<3
) → chuỗi con từ chỉ mục 0
đến r.length()
( 1
))
25.0
& m=4,k=4
trở thành 25.00
(vì k>=1
→ vì vậy r
trở thành 25.00000
; r.length()>=m
( 8>=4
) → r.contains(".")
→ r.length()>+m
( 8>=4
) → chuỗi con từ chỉ mục 0
đến m+1
( 5
))
0
& m=1,k=0
stay 0
(vì k<1
→ so r
stay 0
; r.length()>=m
( 1>=1
) → !r.contains(".")
→ chuỗi con từ chỉ mục 0
đến m
( 1
))
for(i=r.length();i++<l;)
r+=0;
Điều này đặt các số 0 ở cuối một lần nữa trở lại phần nguyên nếu cần thiết.
r="12"
& R=1200.0
trở thànhr="1200"
r="1"
& R=10.0
trở thànhr="10"
r="8"
& R=80.0
trở thànhr="80"
return r.replaceAll(z+"$","");
Và cuối cùng chúng tôi trả lại kết quả, sau khi chúng tôi xóa bất kỳ dấu chấm nào.
1203.
trở thành 1203
5.
trở thành 5
Chắc chắn có thể bị đánh gôn bởi vài trăm byte, nhưng tôi rất vui vì giờ nó đã hoạt động. Phải mất một thời gian để hiểu từng trường hợp và những gì được hỏi trong thử thách. Và sau đó phải mất rất nhiều thử và sai, thử nghiệm và kiểm tra lại để có kết quả như trên. Và trong khi viết lời giải thích này ở trên, tôi đã có thể loại bỏ ± 50 byte mã không sử dụng khác ..
999 + 2.00
.