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)。
この課題は、ほぼ2年間、未回答した理由私は今...>理解しています。>この課題は何かを言っているオランダ語、より多くの特殊なケースを持っている...
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エンジンを使用して入力を評価します。入力はRdoubleとして保存されます。
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.010進値がないため)→ (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滞在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.010進数値がないため)→ (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→にrなるため1001.000、r.length()>=m(8>=4)r.contains(".")→→ r.length()>=m(8>=4)→インデックス0からm+1(5)へのサブストリング)
6.9&m=2,k=2stays 6.9(k>=1→soに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→にrなるため1、; r.length()<m(1<3)→インデックス0からr.length()(1)への部分文字列)
25.0&m=4,k=4は25.00(k>=1→にrなるため25.00000、r.length()>=m(8>=4)r.contains(".")→→ r.length()>+m(8>=4)→インデックス0からm+1(5)へのサブストリング)
0&m=1,k=0滞在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+"$","");
最後に、末尾のドットを削除した後、結果を返します。
間違いなく数百バイトでゴルフをすることができますが、それが現在機能していることをうれしく思います。それぞれのケースとチャレンジで何が求められているのかを理解するのには、しばらく時間がかかりました。そして、上記の結果を得るためには、多くの試行錯誤とテストと再テストが必要でした。上記の説明を書いている間に、さらに50バイトの未使用コードを削除することができました。
999 + 2.00。