Java 11, 1325 1379 1356 1336 1290 Bytes
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 Bytes, um den Randfall zu beheben 501*2.0(Ergebnis 1002vorher gegeben, aber jetzt korrekt 1000).
Ich verstehe jetzt, warum diese Herausforderung fast zwei Jahre lang unbeantwortet blieb.>.> Diese Herausforderung hat mehr Sonderfälle als die niederländische Sprache, die etwas aussagt.
Java ist sicherlich nicht die richtige Sprache für diese Art von Herausforderungen (oder einen Codegolf) Herausforderung für diese Angelegenheit ..; p), aber es ist die einzige Sprache, die ich gut genug kenne, um überhaupt eine schwierige Herausforderung wie diese zu versuchen.
Eingabeformat wie Stringohne Leerzeichen (wenn dies nicht zulässig ist, können Sie s=s.replace(" ","")oben in der Methode (+19 Byte) hinzufügen ).
Probieren Sie es online aus.
Erläuterung:
Entschuldigung für den langen Beitrag.
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)));}
Dieser Teil wird für Eingaben in Klammern verwendet. Es werden die getrennten Teile abgerufen und rekursive Aufrufe verwendet.
0.4*(2*6)wird 0.4*A, wo Aist ein rekursiver Aufruf anc(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)wird A+B, wo Aist ein rekursiver Aufruf an c(8.3*0.02)und Bein rekursiver Aufruf an c(1.*(9*4)+2.2)→ was wiederum wird 1.*C+2.2, wo Cist ein rekursiver Aufruf anc(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;
Diese erste Schleife wird verwendet, um die Werte zu füllen Mund kwobei Mdie größte Ganzzahllänge in Bezug auf signifikante Zahlen und kdie größte Dezimallänge ist.
1200+3.0wird M=2, k=1( 12, .0)
999+2.00wird M=3, k=2( 999, .00)
300.+1-300.wird 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];
Diese zweite Schleife wird verwendet, um die Arrays Aund den bWert zu füllen q, wobei Adie Anzahl der signifikanten Zahlen bdie Ganzzahlen mit führenden Nullen übereinstimmen Mund qdie niedrigste Länge ohne Berücksichtigung von Punkten ist.
1200+3.0wird A=[2, 5] (12, 00030), b=[1200, 0003.0]und q=2( 30)
999+2.00wird A=[3, 5] (999, 00200), b=[999, 002.00]und q=3(beide 999und 200)
300.+1-300.wird A=[3, 3, 3] (300, 001, 300), b=[300., 001, 300.]und q=1( 1)
501*2.0wird A=[3, 4] (501, 0020), b=[501, 002.0]und q=2( 20)
double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+"")
Verwendet eine JavaScript-Engine, um die Eingabe auszuwerten, die Rdoppelt gespeichert wird .
1200+3.0 wird R=1203.0
999+2.00 wird R=1001.0
300.+1-300. wird R=1.0
for(int x:A)
m=x<m?x:m;
Dies wird mauf den kleinsten Wert im Array gesetzt A.
A=[2, 5] wird m=2
A=[3, 5] wird m=3
A=[3, 3, 3] wird 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
Dies ändert sich mbasierend auf mehreren Faktoren.
999+2.00 = 1001.0& m=3,q=3wird m=4(weil m==M(beide 3) → R%1==0( 1001.0hat keine Dezimalwerte) → (int)R/10%10<1( (int)1001.0/10wird 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q<=1( 4-3<=1) → wird so mdie Länge des ganzzahligen Teils "1001"( 4))
3.839*4 = 15.356& m=1,q=1bleibt m=1(weil m==M(beide 1) → R%1!=0( 15.356hat Dezimalwerte) → R<=99→ R%10!=0( 15.356%10==5.356) → m!=0→ mbleibt also gleich ( 1))
4*7*3 = 84.0& m=1,q=1bleibt m=1(weil m==M(beide 1) → R%1==0( 84.0hat keine Dezimalwerte) → (int)R/10%10>=1( (int)84/10wird 8→ 8%10>=1) → R<=99→ R%10!=0( 84%10==4) → m!=0→ mbleibt also gleich ( 1))
6.0+4.0 = 10.0& m=2,q=2wird m=3(weil m!=M( m=2, M=1) → R<=99→ R%10==0( 10%10==0) → so mwird die Länge der Summe R(minus dem Punkt) "10.0".length()-1( 3))
0-8.8 = -8.8& m=0,q=1wird m=1(weil m!=M( m=0, M=1) → R<=99→ R%10!=0( -8.8%10==-8.8) → m<1→ so mwird 1)
501*2.0 = 1001.0& m=3,q=2wird m=2(weil m==M(beide 3) → R%1==0( 1001.0hat keine Dezimalwerte) → (int)R/10%10<1( (int)1001.0/10wird 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q>1( 4-2>1) → so mwird q( 2))
R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();
Jetzt Rwird basierend auf gerundet m.
1001.0& m=4wird1001.0
0.258& m=3Wird 0.26(weil abs(R)<1, m-1( 2) statt m=3verwendet innen MathContext)
-8.8& m=1wird-9.0
1002.0& m=2wird1000.0
m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R;
Dies ändert Rbei Bedarf den ganzzahligen Teil von .
300.+1-300. = 1.0& m=3,M=3bleibt 1.0(weil m>=M→ so gleich Rbleibt ( 1.0))
0.4*10 = 4.0& m=1,M=2bleibt 4.0(weil m<M→ (10^(M-m))/10<=R( (10^1)/10<=4.0→ 10/10<=4.0→ 1<=4.0) → so gleich Rbleibt ( 4.0))
300+1-300 = 1.0& m=1,M=3Wird 0.0(weil m<M→ (10^(M-m))/10>R( (10^2)/10>1.0→ 100/10>1.0→ 10>1.0) → so Rwird 0.0wegen 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`
Diese Sätze Rzu rals String und modifiziert es auf mehreren Faktoren.
1203.0& m=4,k=2wird 1203.(weil k>=1→ so rwird 1001.000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>=m( 8>=4) → Teilzeichenfolge von Index 0zu m+1( 5))
6.9& m=2,k=2bleibt 6.9(weil k>=1→ so rwird 6.900; r.length()>=m( 5>=2) → r.contains(".")→ r.length()>=m( 5>=2) → Teilzeichenfolge von Index 0zu m+1( 3))
1.0& m=3,k=0wird 1(weil k<1→ so rwird 1; r.length()<m( 1<3) → Teilzeichenfolge von Index 0zu r.length()( 1))
25.0& m=4,k=4wird 25.00(weil k>=1→ so rwird 25.00000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>+m( 8>=4) → Teilzeichenfolge von Index 0zu m+1( 5))
0& m=1,k=0bleibt 0(weil k<1→ so rbleibt 0; r.length()>=m( 1>=1) → !r.contains(".")→ Teilzeichenfolge von Index 0zu m( 1))
for(i=r.length();i++<l;)
r+=0;
Dadurch werden nachfolgende Nullen bei Bedarf wieder auf den ganzzahligen Teil zurückgesetzt.
r="12"& R=1200.0wirdr="1200"
r="1"& R=10.0wirdr="10"
r="8"& R=80.0wirdr="80"
return r.replaceAll(z+"$","");
Und schließlich geben wir das Ergebnis zurück, nachdem wir alle nachfolgenden Punkte entfernt haben.
1203. wird 1203
5. wird 5
Kann definitiv um ein paar hundert Bytes gespielt werden, aber ich bin nur froh, dass es jetzt funktioniert. Es dauerte bereits eine Weile, um jeden der Fälle und die Fragen der Herausforderung zu verstehen. Und dann war viel Versuch und Irrtum, Testen und erneutes Testen erforderlich, um zum obigen Ergebnis zu gelangen. Und während ich diese Erklärung oben schrieb, konnte ich weitere ± 50 Bytes nicht verwendeten Codes entfernen.
999 + 2.00.