Java 11, 1325 1379 1356 1336 1290 ไบต์
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 ไบต์เพื่อแก้ไขปัญหาตัวเรือนขอบ501*2.0
(ให้ผลลัพธ์มา1002
ก่อน แต่ตอนนี้ถูกต้อง1000
)
ตอนนี้ฉันเข้าใจแล้วว่าทำไมความท้าทายนี้ถึงไม่ได้ตอบมาเป็นเวลาเกือบสองปี .. >> ความท้าทายนี้มีกรณีพิเศษมากกว่าภาษาดัตช์ซึ่งพูดอะไรบางอย่าง ..
Java ไม่ได้เป็นภาษาที่เหมาะสมสำหรับความท้าทายประเภทนี้ (หรือ codegolf ใด ๆ ) ความท้าทายสำหรับเรื่องนั้น .. ; p) แต่มันเป็นภาษาเดียวที่ฉันรู้ดีพอที่จะลองใช้ความท้าทายที่ยากเช่นนี้
รูปแบบการป้อนข้อมูลString
โดยไม่มีช่องว่าง (หากไม่ได้รับอนุญาตคุณสามารถเพิ่มs=s.replace(" ","")
(+19 ไบต์) ที่ด้านบนของวิธีการ)
ลองออนไลน์
คำอธิบาย:
ขออภัยสำหรับการโพสต์ยาว
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)));}
ส่วนนี้ใช้สำหรับอินพุตที่มีวงเล็บ มันจะได้รับชิ้นส่วนที่แยกจากกันและใช้การโทรซ้ำ
0.4*(2*6)
จะกลายเป็น0.4*A
ที่A
เรียกซ้ำไปc(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)
จะกลายเป็นA+B
ที่A
มีการโทรซ้ำไปที่c(8.3*0.02)
และB
การโทรซ้ำไปที่c(1.*(9*4)+2.2)
→ซึ่งจะกลายเป็น1.*C+2.2
ที่ซึ่งC
การโทรซ้ำไปที่c(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;
วงแรกนี้จะใช้ในการกรอกค่าM
และk
ที่M
มีความยาวจำนวนเต็มที่ใหญ่ที่สุดเกี่ยวกับตัวเลขที่สำคัญและk
ความยาวทศนิยมที่ใหญ่ที่สุด
1200+3.0
กลายเป็นM=2, k=1
( 12, .0
)
999+2.00
กลายเป็นM=3, k=2
( 999, .00
)
300.+1-300.
กลายเป็น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];
ลูปที่สองนี้ใช้เพื่อเติมอาร์เรย์A
และb
ค่าq
ซึ่งA
เป็นจำนวนตัวเลขที่สำคัญb
เก็บจำนวนเต็มด้วยเลขศูนย์นำหน้าเพื่อจับคู่M
และq
เป็นความยาวต่ำสุดโดยไม่คำนึงถึงจุด
1200+3.0
กลายเป็นA=[2, 5] (12, 00030)
, b=[1200, 0003.0]
และq=2
( 30
)
999+2.00
กลายเป็นA=[3, 5] (999, 00200)
, b=[999, 002.00]
และq=3
(ทั้งสอง999
และ200
)
300.+1-300.
กลายเป็นA=[3, 3, 3] (300, 001, 300)
, b=[300., 001, 300.]
และq=1
( 1
)
501*2.0
กลายเป็นA=[3, 4] (501, 0020)
, b=[501, 002.0]
และq=2
( 20
)
double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+"")
ใช้เอนจิ้น JavaScript เพื่อประเมินการป้อนข้อมูลซึ่งจะบันทึกR
เป็นสองเท่า
1200+3.0
กลายเป็น R=1203.0
999+2.00
กลายเป็น R=1001.0
300.+1-300.
กลายเป็น R=1.0
for(int x:A)
m=x<m?x:m;
ชุดนี้จะคุ้มค่าที่เล็กที่สุดในอาร์เรย์m
A
A=[2, 5]
กลายเป็น m=2
A=[3, 5]
กลายเป็น m=3
A=[3, 3, 3]
กลายเป็น 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
การปรับเปลี่ยนนี้m
ขึ้นอยู่กับหลายปัจจัย
999+2.00 = 1001.0
& m=3,q=3
กลายเป็นm=4
(เพราะm==M
(ทั้งสอง3
) → R%1==0
( 1001.0
ไม่มีค่าทศนิยม) → (int)R/10%10<1
( (int)1001.0/10
กลายเป็น100
→ 100%10<1
) → "1001".length()>m
( 4>3
) → "1001".length()-q<=1
( 4-3<=1
) →ดังนั้นจึงm
กลายเป็นความยาวของจำนวนเต็มส่วน"1001"
( 4
)
3.839*4 = 15.356
& m=1,q=1
พักm=1
(เพราะm==M
(ทั้งสอง1
) → R%1!=0
( 15.356
มีค่าทศนิยม) R<=99
→→ R%10!=0
( 15.356%10==5.356
) m!=0
→ดังนั้นจึงm
ยังคงเหมือนเดิม ( 1
)
4*7*3 = 84.0
& m=1,q=1
stay m=1
(เพราะm==M
(ทั้ง ( 1
)) → R%1==0
( 84.0
ไม่มีค่าทศนิยม) → (int)R/10%10>=1
( (int)84/10
กลายเป็น8
→ 8%10>=1
) R<=99
→→ R%10!=0
( 84%10==4
) m!=0
→ดังนั้นm
ยังคงเหมือนเดิม ( 1
)
6.0+4.0 = 10.0
และm=2,q=2
จะกลายเป็นm=3
(เพราะm!=M
( m=2, M=1
) → R<=99
→ R%10==0
( 10%10==0
) →จึงm
กลายเป็นความยาวของทั้งหมดที่R
(ลบจุด) "10.0".length()-1
( 3
))
0-8.8 = -8.8
และm=0,q=1
จะกลายเป็นm=1
(เพราะm!=M
( m=0, M=1
) →การR<=99
→การR%10!=0
( -8.8%10==-8.8
) →การm<1
→การเพื่อให้m
กลายเป็น1
)
501*2.0 = 1001.0
& m=3,q=2
กลายเป็นm=2
(เพราะm==M
(ทั้งคู่3
) → R%1==0
( 1001.0
ไม่มีค่าทศนิยม) → (int)R/10%10<1
( (int)1001.0/10
กลายเป็น100
→ 100%10<1
) → "1001".length()>m
( 4>3
) → "1001".length()-q>1
( 4-2>1
) →ดังนั้นm
กลายเป็นq
( 2
)
R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();
ตอนนี้เป็นโค้งมนขึ้นอยู่กับR
m
1001.0
& m=4
กลายเป็น1001.0
0.258
& m=3
กลายเป็น0.26
(เพราะabs(R)<1
, m-1
( 2
) แทนที่จะm=3
ใช้ภายในMathContext
)
-8.8
& m=1
กลายเป็น-9.0
1002.0
& m=2
กลายเป็น1000.0
m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R;
วิธีนี้จะแก้ไขส่วนจำนวนเต็มของR
หากจำเป็น
300.+1-300. = 1.0
& m=3,M=3
พัก1.0
(เพราะm>=M
→ R
อยู่เหมือนเดิม ( 1.0
))
0.4*10 = 4.0
และm=1,M=2
การเข้าพัก4.0
(เพราะm<M
→ (10^(M-m))/10<=R
( (10^1)/10<=4.0
→ 10/10<=4.0
→ 1<=4.0
) →เพื่อให้R
การเข้าพักเดียวกัน ( 4.0
))
300+1-300 = 1.0
และm=1,M=3
จะกลายเป็น0.0
(เพราะm<M
→ (10^(M-m))/10>R
( (10^2)/10>1.0
→ 100/10>1.0
→ 10>1.0
) →จึงR
กลายเป็น0.0
เพราะ 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`
ชุดนี้R
จะr
เป็นสตริงและปรับเปลี่ยนมันขึ้นอยู่กับหลายปัจจัย
1203.0
& m=4,k=2
กลายเป็น1203.
(เพราะk>=1
→ so r
กลายเป็น1001.000
; r.length()>=m
( 8>=4
) r.contains(".")
→→ r.length()>=m
( 8>=4
) →สตริงย่อยจากดัชนี0
ถึงm+1
( 5
)
6.9
& m=2,k=2
stay 6.9
(เพราะk>=1
→ r
กลายเป็น6.900
; r.length()>=m
( 5>=2
) r.contains(".")
→→ r.length()>=m
( 5>=2
) →สตริงย่อยจากดัชนี0
ถึงm+1
( 3
)
1.0
& m=3,k=0
กลายเป็น1
(เพราะk<1
→ so r
กลายเป็น1
; r.length()<m
( 1<3
) →สตริงย่อยจากดัชนี0
ถึงr.length()
( 1
))
25.0
& m=4,k=4
กลายเป็น25.00
(เพราะk>=1
→ so r
กลายเป็น25.00000
; r.length()>=m
( 8>=4
) r.contains(".")
→→ r.length()>+m
( 8>=4
) →สตริงย่อยจากดัชนี0
ถึงm+1
( 5
)
0
& m=1,k=0
stay 0
(เพราะk<1
→ดังนั้นr
อยู่0
; r.length()>=m
( 1>=1
) !r.contains(".")
→→สตริงย่อยจากดัชนี0
ถึงm
( 1
))
for(i=r.length();i++<l;)
r+=0;
ซึ่งจะทำให้ศูนย์ต่อท้ายกลับไปที่ส่วนจำนวนเต็มถ้าจำเป็น
r="12"
& R=1200.0
กลายเป็นr="1200"
r="1"
& R=10.0
กลายเป็นr="10"
r="8"
& R=80.0
กลายเป็นr="80"
return r.replaceAll(z+"$","");
และในที่สุดเราก็กลับผลลัพธ์หลังจากเราลบจุดใด ๆ ที่ตามมา
1203.
กลายเป็น 1203
5.
กลายเป็น 5
สามารถเล่นกอล์ฟได้สองร้อยไบต์แน่นอน แต่ฉันแค่ดีใจที่มันใช้งานได้ ใช้เวลาสักครู่เพื่อทำความเข้าใจแต่ละกรณีและสิ่งที่ถูกถามในการท้าทาย และจากนั้นก็ใช้การทดลองและข้อผิดพลาดมากมายทดสอบและทดสอบซ้ำเพื่อให้ได้ผลลัพธ์ดังกล่าว และในขณะที่เขียนคำอธิบายนี้ด้านบนฉันสามารถลบอีก± 50 ไบต์ของรหัสที่ไม่ได้ใช้ ..
999 + 2.00
หากคุณต้องการกรณีขอบสำหรับนอกจากนี้