Java 11, 1325 1379 1356 1336 1290 octets
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 octets pour corriger le cas de bord 501*2.0(a donné le résultat 1002avant, mais maintenant correct 1000).
Je comprends maintenant pourquoi ce défi était sans réponse depuis presque deux ans ..>.> Ce défi a des cas plus particuliers que la langue néerlandaise, ce qui veut dire quelque chose ..
Java est certainement pas la bonne langue pour ce genre de défis (ou tout codegolf défi d'ailleurs ..; p), mais c'est la seule langue que je connais assez bien pour même tenter un défi difficile comme celui-ci.
Format d'entrée Stringsans espaces (si cela n'est pas autorisé, vous pouvez ajouter s=s.replace(" ","")(+19 octets) en haut de la méthode).
Essayez-le en ligne.
Explication:
Désolé pour le long 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)));}
Cette partie est utilisée pour les entrées contenant des parenthèses. Il récupérera les parties séparées et utilisera les appels récursifs.
0.4*(2*6)devient 0.4*A, où Aest un appel récursif àc(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)devient A+B, où Aest un appel récursif à c(8.3*0.02)et Bun appel récursif à c(1.*(9*4)+2.2)→ qui devient à son tour 1.*C+2.2, où Cest un appel récursif à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;
Cette première boucle est utilisée pour remplir les valeurs Met k, où Mest la plus grande longueur entière concernant les chiffres significatifs et kla plus grande longueur décimale.
1200+3.0devient M=2, k=1( 12, .0)
999+2.00devient M=3, k=2( 999, .00)
300.+1-300.devient 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];
Cette deuxième boucle est utilisée pour remplir les tableaux Aet bainsi que la valeur q, où Aest le nombre de chiffres significatifs, btenir les entiers avec des zéros en tête pour correspondre M, et qest la plus petite longueur sans tenir compte des points.
1200+3.0devient A=[2, 5] (12, 00030), b=[1200, 0003.0]et q=2( 30)
999+2.00devient A=[3, 5] (999, 00200), b=[999, 002.00]et q=3( à la fois 999et 200)
300.+1-300.devient A=[3, 3, 3] (300, 001, 300), b=[300., 001, 300.]et q=1( 1)
501*2.0devient A=[3, 4] (501, 0020), b=[501, 002.0]et q=2( 20)
double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+"")
Utilise un moteur JavaScript pour évaluer l'entrée, qui sera enregistrée en Rdouble.
1200+3.0 devient R=1203.0
999+2.00 devient R=1001.0
300.+1-300. devient R=1.0
for(int x:A)
m=x<m?x:m;
Cela définit mla plus petite valeur du tableau A.
A=[2, 5] devient m=2
A=[3, 5] devient m=3
A=[3, 3, 3] devient 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
Cela modifie en mfonction de plusieurs facteurs.
999+2.00 = 1001.0& m=3,q=3devient m=4(parce que m==M(les deux 3) → R%1==0( 1001.0n'a pas de valeurs décimales) → (int)R/10%10<1( (int)1001.0/10devient 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q<=1( 4-3<=1) → mdevient ainsi la longueur de la partie entière "1001"( 4))
3.839*4 = 15.356& m=1,q=1reste m=1(parce que m==M(les deux 1) → R%1!=0( 15.356a des valeurs décimales) → R<=99→ R%10!=0( 15.356%10==5.356) → m!=0→ mreste donc le même ( 1))
4*7*3 = 84.0& m=1,q=1reste m=1(parce que m==M(les deux 1) → R%1==0( 84.0n'a pas de valeurs décimales) → (int)R/10%10>=1( (int)84/10devient 8→ 8%10>=1) → R<=99→ R%10!=0( 84%10==4) → m!=0→ mreste donc le même ( 1))
6.0+4.0 = 10.0& m=2,q=2devient m=3(car m!=M( m=2, M=1) → R<=99→ R%10==0( 10%10==0) → mdevient ainsi la longueur du total R(moins le point) "10.0".length()-1( 3))
0-8.8 = -8.8& m=0,q=1devient m=1(parce que m!=M( m=0, M=1) → R<=99→ R%10!=0( -8.8%10==-8.8) → m<1→ mdevient ainsi 1)
501*2.0 = 1001.0& m=3,q=2devient m=2(parce que m==M(les deux 3) → R%1==0( 1001.0n'a pas de valeurs décimales) → (int)R/10%10<1( (int)1001.0/10devient 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q>1( 4-2>1) → mdevient ainsi q( 2))
R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();
Maintenant Rest arrondi en fonction de m.
1001.0& m=4devient1001.0
0.258& m=3devient 0.26(car abs(R)<1, m-1( 2) au lieu de m=3est utilisé à l'intérieur MathContext)
-8.8& m=1devient-9.0
1002.0& m=2devient1000.0
m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R;
Cela modifie la partie entière de Rsi nécessaire.
300.+1-300. = 1.0& m=3,M=3reste 1.0(parce que m>=M→ Rreste donc le même ( 1.0))
0.4*10 = 4.0& m=1,M=2reste 4.0(parce que m<M→ (10^(M-m))/10<=R( (10^1)/10<=4.0→ 10/10<=4.0→ 1<=4.0) → Rreste donc le même ( 4.0))
300+1-300 = 1.0& m=1,M=3devient 0.0(parce que m<M→ (10^(M-m))/10>R( (10^2)/10>1.0→ 100/10>1.0→ 10>1.0) → Rdevient ainsi à 0.0cause de 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`
Il est défini Rsur rString et le modifie en fonction de plusieurs facteurs.
1203.0& m=4,k=2devient 1203.(car k>=1→ rdevient ainsi 1001.000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>=m( 8>=4) → sous-chaîne de l'index 0à m+1( 5))
6.9& m=2,k=2reste 6.9(car k>=1→ rdevient ainsi 6.900; r.length()>=m( 5>=2) → r.contains(".")→ r.length()>=m( 5>=2) → sous-chaîne de l'index 0à m+1( 3))
1.0& m=3,k=0devient 1(car k<1→ rdevient ainsi 1; r.length()<m( 1<3) → sous-chaîne de l'index 0à r.length()( 1))
25.0& m=4,k=4devient 25.00(car k>=1→ rdevient ainsi 25.00000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>+m( 8>=4) → sous-chaîne de l'index 0à m+1( 5))
0& m=1,k=0séjours 0(parce que k<1→ rreste donc 0; r.length()>=m( 1>=1) → !r.contains(".")→ sous-chaîne de l'index 0à m( 1))
for(i=r.length();i++<l;)
r+=0;
Cela ramène les zéros de fin à la partie entière si nécessaire.
r="12"& R=1200.0devientr="1200"
r="1"& R=10.0devientr="10"
r="8"& R=80.0devientr="80"
return r.replaceAll(z+"$","");
Et enfin, nous retournons le résultat, après avoir supprimé tous les points de fin.
1203. devient 1203
5. devient 5
Peut certainement être joué par quelques centaines d'octets, mais je suis juste content que cela fonctionne maintenant. Il a déjà fallu un certain temps pour comprendre chacun des cas et ce qui était demandé dans le défi. Et puis il a fallu beaucoup d'essais et d'erreurs, de tests et de retests pour arriver au résultat ci-dessus. Et en écrivant cette explication ci-dessus, j'ai pu supprimer encore ± 50 octets de code inutilisé.
999 + 2.00.