Java 11, 1325 1379 1356 1336 1290 bayt
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+"$","");}}
Kenar durumunu düzeltmek için +54 bayt 501*2.0(daha 1002önce sonuç verdi , ancak şimdi doğru 1000).
Şimdi bu zorluğun neden neredeyse iki yıldır cevaplanmadığını anlıyorum ..> .Bu zorluğun bir şey söyleyen Hollanda dilinden daha özel vakaları var ..
Java kesinlikle bu tür zorluklar (veya herhangi bir kod golfü için doğru dil değil) bu konu için meydan okuma ..; p), ama böyle zor bir meydan okuma girişiminde bulunmaya yetecek kadar iyi bildiğim tek dil.
StringBoşluksuz giriş biçimi (buna izin verilmiyorsa, s=s.replace(" ","")yöntemin üstüne (+19 bayt) ekleyebilirsiniz ).
Çevrimiçi deneyin.
Açıklama:
Uzun yazı için özür dilerim.
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)));}
Bu bölüm parantez içeren girdi için kullanılır. Ayrılan parçaları alır ve özyinelemeli çağrılar kullanır.
0.4*(2*6)olur 0.4*Anerede, Abir özyinelemeli çağrıdırc(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)olur A+Bnerede, Abir özyinelemeli çağrı c(8.3*0.02)ve Bardışık bir çağrı c(1.*(9*4)+2.2)sırayla olur → 1.*C+2.2nerede Cbir özyinelemeli çağrıdırc(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;
Bu birinci çevrim değerleri doldurmak için kullanılan Mve kburada, Mönemli ölçüde şekiller ile ilgili olarak en büyük tam sayıyı uzunluklu kbüyük ondalık sayı-uzunluk.
1200+3.0olur M=2, k=1( 12, .0)
999+2.00olur M=3, k=2( 999, .00)
300.+1-300.olur 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];
Bu ikinci çevrim diziler doldurmak için kullanılan Ave bayrıca bir değer olarak q, Aönemli rakamların miktarı, beşleştirmek için gelen sıfır ile tamsayılar tutun Mve qnoktalar göz ardı düşük uzunluktadır.
1200+3.0olur A=[2, 5] (12, 00030), b=[1200, 0003.0]ve q=2( 30)
999+2.00olur A=[3, 5] (999, 00200), b=[999, 002.00]ve q=3(hem 999ve 200)
300.+1-300.olur A=[3, 3, 3] (300, 001, 300), b=[300., 001, 300.]ve q=1( 1)
501*2.0olur A=[3, 4] (501, 0020), b=[501, 002.0]ve q=2( 20)
double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+"")
Girişi değerlendirmek için bir JavaScript motoru kullanır ve bu değer Rçift olarak kaydedilir .
1200+3.0 olur R=1203.0
999+2.00 olur R=1001.0
300.+1-300. olur R=1.0
for(int x:A)
m=x<m?x:m;
Bu m, dizideki en küçük değere ayarlanır A.
A=[2, 5] olur m=2
A=[3, 5] olur m=3
A=[3, 3, 3] olur 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
Bu m, birden çok faktöre göre değişiklik gösterir.
999+2.00 = 1001.0& m=3,q=3olur m=4(çünkü m==M(her ikisi de 3) → R%1==0( 1001.0ondalık değeri yoktur) → (int)R/10%10<1( → (int)1001.0/10olur 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q<=1( 4-3<=1) → böylece mtamsayı bölümünün uzunluğu olur "1001"( 4))
3.839*4 = 15.356& m=1,q=1kalır m=1(çünkü m==M(her ikisi de 1) → R%1!=0( 15.356ondalık değerleri vardır) → R<=99→ R%10!=0( 15.356%10==5.356) → m!=0→ maynı kalır ( 1))
4*7*3 = 84.0& m=1,q=1kalır m=1(çünkü m==M(her ikisi de 1) → R%1==0( 84.0ondalık değeri yoktur) → (int)R/10%10>=1( → (int)84/10olur 8→ 8%10>=1) → R<=99→ R%10!=0( 84%10==4) → m!=0→ böylece maynı kalır ( 1))
6.0+4.0 = 10.0& m=2,q=2olur m=3(çünkü m!=M( m=2, M=1) → R<=99→ R%10==0( 10%10==0) → mtoplamın uzunluğu olur R(eksi nokta) "10.0".length()-1( 3))
0-8.8 = -8.8& m=0,q=1olur m=1(çünkü m!=M( m=0, M=1) → R<=99→ R%10!=0( -8.8%10==-8.8) → m<1→ molur 1)
501*2.0 = 1001.0& m=3,q=2olur m=2(çünkü m==M(her ikisi de 3) → R%1==0( 1001.0ondalık değeri yoktur) → (int)R/10%10<1( → (int)1001.0/10olur 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q>1( 4-2>1) → böylece ( ) molurq2
R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();
Şimdi Rdayalı yuvarlanır m.
1001.0& m=4olur1001.0
0.258Ve m=3olur 0.26(nedeniyle abs(R)<1, m-1( 2) yerine m=3iç kullanılır MathContext)
-8.8& m=1olur-9.0
1002.0& m=2olur1000.0
m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R;
Bu, Rgerekirse tam sayı kısmını değiştirir .
300.+1-300. = 1.0& m=3,M=3kalır 1.0(çünkü m>=M→ Raynı kalır ( 1.0))
0.4*10 = 4.0& m=1,M=2kalır 4.0(çünkü m<M→ (10^(M-m))/10<=R( (10^1)/10<=4.0→ 10/10<=4.0→ 1<=4.0) → Raynı kalır ( 4.0))
300+1-300 = 1.0Ve m=1,M=3olur 0.0(nedeniyle m<M→ (10^(M-m))/10>R( (10^2)/10>1.0→ 100/10>1.0→ 10>1.0) → çok Rolur 0.0çünkü 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`
Bu setler Riçin rString olarak ve değiştirir birden çok faktöre dayalı.
1203.0& m=4,k=2Olur 1203.(çünkü k>=1böylece → rolur 1001.000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>=m( 8>=4) → dizinden alt dize 0kadar m+1( 5))
6.9& m=2,k=2Kalır 6.9(çünkü k>=1→ yüzden rolur 6.900; r.length()>=m( 5>=2) → r.contains(".")→ r.length()>=m( 5>=2) → dizinden alt dize 0kadar m+1( 3))
1.0& m=3,k=0Olur 1(çünkü k<1böylece → rolur 1; r.length()<m( 1<3) → dizinden alt dize 0kadar r.length()( 1))
25.0& m=4,k=4Olur 25.00(çünkü k>=1böylece → rolur 25.00000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>+m( 8>=4) → dizinden alt dize 0kadar m+1( 5))
0& m=1,k=0Kalır 0(çünkü k<1böylece → rkalır 0; r.length()>=m( 1>=1) → !r.contains(".")→ dizinden alt dize 0kadar m( 1))
for(i=r.length();i++<l;)
r+=0;
Bu, gerekirse sıfırları tekrar tamsayı kısmına geri koyar.
r="12"& R=1200.0olurr="1200"
r="1"& R=10.0olurr="10"
r="8"& R=80.0olurr="80"
return r.replaceAll(z+"$","");
Sonunda, herhangi bir nokta kaldırıldıktan sonra sonucu döndürüyoruz.
1203. olur 1203
5. olur 5
Kesinlikle birkaç yüz bayt tarafından golf edilebilir, ama şimdi çalıştığı için memnunum. Davaların her birini ve meydan okumada ne sorulduğunu anlamak zaten biraz zaman aldı. Ve sonra yukarıdaki sonuca ulaşmak için birçok deneme yanılma, test etme ve tekrar test etme gerekiyordu. Ve bu açıklamayı yukarıda yazarken kullanılmayan ± 50 baytlık bir kod daha kaldırabiliyordum.
999 + 2.00,.