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 para arreglar el caso de borde 501*2.0(dio resultado 1002antes, pero ahora correcto 1000).
Ahora entiendo por qué este desafío no tuvo respuesta durante casi dos años ...>.> Este desafío tiene casos más especiales que el idioma holandés, que dice algo ...
Java ciertamente no es el idioma adecuado para este tipo de desafíos (o cualquier codegolf desafío para el caso ...; p), pero es el único lenguaje que conozco lo suficientemente bueno como para incluso intentar un desafío difícil como este.
Formato de entrada como Stringsin espacios (si eso no está permitido, puede agregar s=s.replace(" ","")(+19 bytes) en la parte superior del método).
Pruébalo en línea.
Explicación:
Perdón por la larga publicación.
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)));}
Esta parte se usa para entradas que contienen paréntesis. Obtendrá las partes separadas y usará llamadas recursivas.
0.4*(2*6)se convierte 0.4*A, donde Aes una llamada recursiva ac(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)se convierte A+B, donde Aes una llamada recursiva c(8.3*0.02)y Buna llamada recursiva a c(1.*(9*4)+2.2)→ que a su vez se convierte 1.*C+2.2, donde Ces una llamada recursiva 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;
Este primer ciclo se usa para completar los valores My k, donde Mes la mayor longitud entera con respecto a cifras significativas y kla mayor longitud de decimales.
1200+3.0se convierte en M=2, k=1( 12, .0)
999+2.00se convierte en M=3, k=2( 999, .00)
300.+1-300.se convierte en 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];
Este segundo bucle se usa para llenar las matrices Ay btambién el valor q, donde Aes la cantidad de cifras significativas, bmantener los enteros con ceros a la izquierda para coincidir M, y qes la longitud más baja sin tener en cuenta los puntos.
1200+3.0se convierte A=[2, 5] (12, 00030), b=[1200, 0003.0]y q=2( 30)
999+2.00se convierte A=[3, 5] (999, 00200), b=[999, 002.00]y q=3(ambos 999y 200)
300.+1-300.se convierte A=[3, 3, 3] (300, 001, 300), b=[300., 001, 300.]y q=1( 1)
501*2.0se convierte A=[3, 4] (501, 0020), b=[501, 002.0]y q=2( 20)
double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+"")
Utiliza un motor de JavaScript para evaluar la entrada, que se guardará Rcomo doble.
1200+3.0 se convierte R=1203.0
999+2.00 se convierte R=1001.0
300.+1-300. se convierte R=1.0
for(int x:A)
m=x<m?x:m;
Esto establece mel valor más pequeño en la matriz A.
A=[2, 5] se convierte m=2
A=[3, 5] se convierte m=3
A=[3, 3, 3] se convierte 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
Esto se modifica en mfunción de múltiples factores.
999+2.00 = 1001.0& se m=3,q=3convierte en m=4(porque m==M(ambos 3) → R%1==0( 1001.0no tiene valores decimales) → (int)R/10%10<1(se (int)1001.0/10convierte en 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q<=1( 4-3<=1) → entonces se mconvierte en la longitud de la parte entera "1001"( 4))
3.839*4 = 15.356& m=1,q=1permanece m=1(porque m==M(ambos 1) → R%1!=0( 15.356tiene valores decimales) → R<=99→ R%10!=0( 15.356%10==5.356) → m!=0→ así que mpermanece igual ( 1))
4*7*3 = 84.0& m=1,q=1permanece m=1(porque m==M(ambos 1) → R%1==0( 84.0no tiene valores decimales) → (int)R/10%10>=1(se (int)84/10convierte en 8→ 8%10>=1) → R<=99→ R%10!=0( 84%10==4) → m!=0→ así que mpermanece igual ( 1))
6.0+4.0 = 10.0& se m=2,q=2convierte en m=3(porque m!=M( m=2, M=1) → R<=99→ R%10==0( 10%10==0) → se mconvierte en la longitud del total R(menos el punto) "10.0".length()-1( 3))
0-8.8 = -8.8& se m=0,q=1convierte m=1(porque m!=M( m=0, M=1) → R<=99→ R%10!=0( -8.8%10==-8.8) → m<1→ se mconvierte en 1)
501*2.0 = 1001.0& se m=3,q=2convierte en m=2(porque m==M(ambos 3) → R%1==0( 1001.0no tiene valores decimales) → (int)R/10%10<1(se (int)1001.0/10convierte en 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q>1( 4-2>1) → se mconvierte en q( 2)
R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();
Ahora Rse redondea según m.
1001.0y se m=4convierte1001.0
0.258& se m=3convierte en 0.26(porque abs(R)<1, m-1( 2) en lugar de m=3se usa dentro MathContext)
-8.8y se m=1convierte-9.0
1002.0y se m=2convierte1000.0
m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R;
Esto modifica la parte entera de Rsi es necesario.
300.+1-300. = 1.0& m=3,M=3permanece 1.0(porque m>=M→ entonces Rpermanece igual ( 1.0))
0.4*10 = 4.0& m=1,M=2permanece 4.0(porque m<M→ (10^(M-m))/10<=R( (10^1)/10<=4.0→ 10/10<=4.0→ 1<=4.0) → Rpermanece igual ( 4.0))
300+1-300 = 1.0& se m=1,M=3convierte en 0.0(porque m<M→ (10^(M-m))/10>R( (10^2)/10>1.0→ 100/10>1.0→ 10>1.0) → entonces se Rconvierte en 0.0debido a 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`
Este conjuntos Ra rcomo secuencia, y lo modifica basa en varios factores.
1203.0& se m=4,k=2convierte 1203.(porque k>=1→ entonces se rconvierte en 1001.000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>=m( 8>=4) → subcadena del índice 0a m+1( 5))
6.9& m=2,k=2permanece 6.9(porque k>=1→ entonces se rconvierte en 6.900; r.length()>=m( 5>=2) → r.contains(".")→ r.length()>=m( 5>=2) → subcadena del índice 0a m+1( 3))
1.0& se m=3,k=0convierte 1(porque k<1→ se rconvierte en 1; r.length()<m( 1<3) → subcadena del índice 0a r.length()( 1))
25.0& se m=4,k=4convierte 25.00(porque k>=1→ entonces se rconvierte en 25.00000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>+m( 8>=4) → subcadena del índice 0a m+1( 5))
0& se m=1,k=0queda 0(porque k<1→ así se rqueda 0; r.length()>=m( 1>=1) → !r.contains(".")→ subcadena del índice 0a m( 1))
for(i=r.length();i++<l;)
r+=0;
Esto hace que los ceros finales vuelvan a la parte entera si es necesario.
r="12"y se R=1200.0convierter="1200"
r="1"y se R=10.0convierter="10"
r="8"y se R=80.0convierter="80"
return r.replaceAll(z+"$","");
Y finalmente devolvemos el resultado, después de haber eliminado los puntos finales.
1203. se convierte 1203
5. se convierte 5
Definitivamente se puede jugar un par de cientos de bytes, pero me alegra que esté funcionando ahora. Ya tomó un tiempo entender cada uno de los casos y lo que se preguntaba en el desafío. Y luego se necesitaron muchas pruebas y errores, pruebas y pruebas para llegar al resultado anterior. Y mientras escribía esta explicación arriba pude eliminar otros ± 50 bytes de código no utilizado ...
999 + 2.00,.