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 per correggere il caso limite 501*2.0(dato il risultato 1002prima, ma ora corretto 1000).
Adesso capisco perché questa sfida è stata senza risposta per quasi due anni ..>.> Questa sfida ha casi speciali di lingua olandese, che è tutto dire ..
Java non è certamente la lingua giusta per questo tipo di sfide (o qualsiasi codegolf sfida per quella materia ..; p), ma è l'unica lingua che conosco abbastanza bene da tentare anche una sfida difficile come questa.
Formato di input come Stringsenza spazi (se ciò non è consentito, è possibile aggiungere s=s.replace(" ","")(+19 byte) all'inizio del metodo).
Provalo online.
Spiegazione:
Ci scusiamo per il lungo post.
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)));}
Questa parte viene utilizzata per input contenenti parentesi. Otterrà le parti separate e utilizzerà le chiamate ricorsive.
0.4*(2*6)diventa 0.4*A, dove Aè una chiamata ricorsiva ac(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)diventa A+B, dove si Atrova una chiamata ricorsiva c(8.3*0.02)e Buna chiamata ricorsiva a c(1.*(9*4)+2.2)→ che a sua volta diventa 1.*C+2.2, dove si Ctrova una chiamata ricorsiva ac(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;
Questo primo ciclo viene utilizzato per riempire i valori Me k, dove si Mtrova la lunghezza intera più grande rispetto alle cifre significative e kla lunghezza decimale più grande.
1200+3.0diventa M=2, k=1( 12, .0)
999+2.00diventa M=3, k=2( 999, .00)
300.+1-300.diventa 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];
Questo secondo ciclo viene utilizzato per riempire le matrici Ae bil valore q, dove Aè la quantità di cifre significative, bcontenere gli interi con zero iniziali da abbinare Med qè la lunghezza più bassa ignorando i punti.
1200+3.0diventa A=[2, 5] (12, 00030), b=[1200, 0003.0]e q=2( 30)
999+2.00diventa A=[3, 5] (999, 00200), b=[999, 002.00]e q=3(sia 999e 200)
300.+1-300.diventa A=[3, 3, 3] (300, 001, 300), b=[300., 001, 300.]e q=1( 1)
501*2.0diventa A=[3, 4] (501, 0020), b=[501, 002.0]e q=2( 20)
double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+"")
Utilizza un motore JavaScript per valutare l'input, che verrà salvato Rcome doppio.
1200+3.0 diventa R=1203.0
999+2.00 diventa R=1001.0
300.+1-300. diventa R=1.0
for(int x:A)
m=x<m?x:m;
Questo imposta msul valore più piccolo nell'array A.
A=[2, 5] diventa m=2
A=[3, 5] diventa m=3
A=[3, 3, 3] diventa 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
Questo si modifica in mbase a più fattori.
999+2.00 = 1001.0& m=3,q=3diventa m=4(perché m==M(entrambi 3) → R%1==0( 1001.0non ha valori decimali) → (int)R/10%10<1( (int)1001.0/10diventa 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q<=1( 4-3<=1) → quindi mdiventa la lunghezza dell'intero-parte "1001"( 4))
3.839*4 = 15.356e m=1,q=1rimane m=1(perché m==M(entrambi 1) → R%1!=0( 15.356ha valori decimali) → R<=99→ R%10!=0( 15.356%10==5.356) → m!=0→ quindi mrimane lo stesso ( 1))
4*7*3 = 84.0e m=1,q=1rimane m=1(perché m==M(entrambi 1) → R%1==0( 84.0non ha valori decimali) → (int)R/10%10>=1( (int)84/10diventa 8→ 8%10>=1) → R<=99→ R%10!=0( 84%10==4) → m!=0→ quindi mrimane lo stesso ( 1))
6.0+4.0 = 10.0& m=2,q=2diventa m=3(perché m!=M( m=2, M=1) → R<=99→ R%10==0( 10%10==0) → così mdiventa la lunghezza del totale R(meno il punto) "10.0".length()-1( 3))
0-8.8 = -8.8& m=0,q=1diventa m=1(perché m!=M( m=0, M=1) → R<=99→ R%10!=0( -8.8%10==-8.8) → m<1→ così mdiventa 1)
501*2.0 = 1001.0& m=3,q=2diventa m=2(perché m==M(entrambi 3) → R%1==0( 1001.0non ha valori decimali) → (int)R/10%10<1( (int)1001.0/10diventa 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q>1( 4-2>1) → così mdiventa q( 2))
R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();
Ora Rè arrotondato in base a m.
1001.0e m=4diventa1001.0
0.258& m=3diventa 0.26(perché abs(R)<1, m-1( 2) invece di m=3essere utilizzato all'interno MathContext)
-8.8e m=1diventa-9.0
1002.0e m=2diventa1000.0
m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R;
Questo modifica la parte intera di Rse necessario.
300.+1-300. = 1.0e m=3,M=3rimane 1.0(perché m>=M→ quindi Rrimane lo stesso ( 1.0))
0.4*10 = 4.0e m=1,M=2rimane 4.0(perché m<M→ (10^(M-m))/10<=R( (10^1)/10<=4.0→ 10/10<=4.0→ 1<=4.0) → quindi Rrimane uguale ( 4.0))
300+1-300 = 1.0& m=1,M=3diventa 0.0(perché m<M→ (10^(M-m))/10>R( (10^2)/10>1.0→ 100/10>1.0→ 10>1.0) → così Rdiventa a 0.0causa di 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`
Questo imposta Ra rcome stringa, e lo modifica basa su molteplici fattori.
1203.0& m=4,k=2diventa 1203.(perché k>=1→ così rdiventa 1001.000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>=m( 8>=4) → sottostringa dall'indice 0a m+1( 5))
6.9& m=2,k=2resta 6.9(perché k>=1→ così rdiventa 6.900; r.length()>=m( 5>=2) → r.contains(".")→ r.length()>=m( 5>=2) → sottostringa dall'indice 0a m+1( 3))
1.0& m=3,k=0diventa 1(perché k<1→ così rdiventa 1; r.length()<m( 1<3) → sottostringa dall'indice 0a r.length()( 1))
25.0& m=4,k=4diventa 25.00(perché k>=1→ così rdiventa 25.00000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>+m( 8>=4) → sottostringa dall'indice 0a m+1( 5))
0& m=1,k=0rimane 0(perché k<1→ così rrimane 0; r.length()>=m( 1>=1) → !r.contains(".")→ sottostringa dall'indice 0a m( 1))
for(i=r.length();i++<l;)
r+=0;
In questo modo, se necessario, vengono ripristinati nuovamente gli zero finali nella parte intera.
r="12"e R=1200.0diventar="1200"
r="1"e R=10.0diventar="10"
r="8"e R=80.0diventar="80"
return r.replaceAll(z+"$","");
E infine restituiamo il risultato, dopo aver rimosso tutti i punti finali.
1203. diventa 1203
5. diventa 5
Può sicuramente essere giocato a golf di circa duecento byte, ma sono contento che funzioni ora. Ci è voluto un po 'di tempo per capire ciascuno dei casi e ciò che era stato chiesto nella sfida. E poi ci sono voluti molti tentativi, test e test per ottenere il risultato sopra. E mentre scrivevo questa spiegazione sopra sono stato in grado di rimuovere altri ± 50 byte di codice inutilizzato.
999 + 2.00,.