Java 11, 1325 1379 1356 1336 1290 bajtów
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 bajtów, aby naprawić wielkość liter 501*2.0(dawał wynik 1002wcześniej, ale teraz jest poprawny 1000).
Rozumiem teraz, dlaczego na to wyzwanie nie udzielono odpowiedzi przez prawie dwa lata ..>.> To wyzwanie ma więcej specjalnych przypadków niż język holenderski, który mówi coś ..
Java z pewnością nie jest odpowiednim językiem dla tego rodzaju wyzwań (lub jakiegokolwiek dorosłego golfa wyzwanie w tej sprawie ...; p), ale jest to jedyny język, który znam wystarczająco dobrze, aby nawet podjąć takie trudne wyzwanie.
Format wejściowy Stringbez spacji (jeśli nie jest to dozwolone, możesz dodać s=s.replace(" ","")(+19 bajtów) na górze metody).
Wypróbuj online.
Wyjaśnienie:
Przepraszam za długi 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)));}
Ta część służy do wprowadzania danych zawierających nawiasy. Otrzyma oddzielne części i użyje wywołań rekurencyjnych.
0.4*(2*6)staje się 0.4*A, gdzie Ajest rekurencyjne połączenie zc(2*6)
(8.3*0.02)+(1.*(9*4)+2.2)staje się A+B, gdzie Ajest rekurencyjne połączenie z c(8.3*0.02)i Brekurencyjne połączenie z c(1.*(9*4)+2.2)→ które z kolei staje się 1.*C+2.2, gdzie Cjest połączenie rekurencyjne zc(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;
Ta pierwsza pętla służy do wypełnienia wartości Moraz k, gdzie Mjest największą długością całkowitą w odniesieniu do liczb znaczących i knajwiększą długością dziesiętną.
1200+3.0staje się M=2, k=1( 12, .0)
999+2.00staje się M=3, k=2( 999, .00)
300.+1-300.staje się 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];
Ta druga pętla służy do wypełniania tablic, Aa btakże wartości q, gdzie Ajest liczba znaczących cyfr, zawiera bliczby całkowite z zerami wiodącymi, aby je dopasować M, i qjest najmniejszą kropką bez uwzględnienia kropek.
1200+3.0staje się A=[2, 5] (12, 00030), b=[1200, 0003.0]i q=2( 30)
999+2.00staje się A=[3, 5] (999, 00200), b=[999, 002.00]i q=3(zarówno 999i 200)
300.+1-300.staje się A=[3, 3, 3] (300, 001, 300), b=[300., 001, 300.]i q=1( 1)
501*2.0staje się A=[3, 4] (501, 0020), b=[501, 002.0]i q=2( 20)
double R=new Double(new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s)+"")
Używa silnika JavaScript do oceny danych wejściowych, które zostaną zapisane Rjako podwójne.
1200+3.0 staje się R=1203.0
999+2.00 staje się R=1001.0
300.+1-300. staje się R=1.0
for(int x:A)
m=x<m?x:m;
Ustawia msię na najmniejszą wartość w tablicy A.
A=[2, 5] staje się m=2
A=[3, 5] staje się m=3
A=[3, 3, 3] staje się 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
To zmienia się w moparciu o wiele czynników.
999+2.00 = 1001.0& m=3,q=3staje się m=4(ponieważ m==M(oba 3) → R%1==0( 1001.0nie ma wartości dziesiętnych) → (int)R/10%10<1( (int)1001.0/10staje się 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q<=1( 4-3<=1) → więc mstaje się długością części całkowitej "1001"( 4))
3.839*4 = 15.356& m=1,q=1pozostaje m=1(ponieważ m==M(oba 1) → R%1!=0( 15.356ma wartości dziesiętne) → R<=99→ R%10!=0( 15.356%10==5.356) → m!=0→ więc mpozostaje ten sam ( 1))
4*7*3 = 84.0& m=1,q=1pozostaje m=1(ponieważ m==M(oba 1) → R%1==0( 84.0nie ma wartości dziesiętnych) → (int)R/10%10>=1( (int)84/10staje się 8→ 8%10>=1) → R<=99→ R%10!=0( 84%10==4) → m!=0→ więc mpozostaje taki sam ( 1))
6.0+4.0 = 10.0& m=2,q=2staje się m=3(ponieważ m!=M( m=2, M=1) → R<=99→ R%10==0( 10%10==0) → więc mstaje się długością sumy R(minus kropka) "10.0".length()-1( 3))
0-8.8 = -8.8i m=0,q=1staje się m=1(ponieważ m!=M( m=0, M=1) → R<=99→ R%10!=0( -8.8%10==-8.8) → m<1→ mstaje się 1)
501*2.0 = 1001.0& m=3,q=2staje się m=2(ponieważ m==M(oba 3) → R%1==0( 1001.0nie ma wartości dziesiętnych) → (int)R/10%10<1( (int)1001.0/10staje się 100→ 100%10<1) → "1001".length()>m( 4>3) → "1001".length()-q>1( 4-2>1) → więc mstaje się q( 2))
R=new BigDecimal(R).round(new MathContext((R<0?-R:R)<1?m-1:m)).doubleValue();
Teraz Rjest zaokrąglany na podstawie m.
1001.0i m=4staje się1001.0
0.258I m=3staje się 0.26(ze względu abs(R)<1, m-1( 2), a nie m=3są stosowane wewnątrz MathContext)
-8.8i m=1staje się-9.0
1002.0i m=2staje się1000.0
m<M&(p=Math.pow(10,M-m))/10>R?(int)(R/p)*p:R;
W Rrazie potrzeby modyfikuje to część całkowitą .
300.+1-300. = 1.0i m=3,M=3zostaje 1.0(ponieważ m>=M→ więc Rpozostaje taki sam ( 1.0))
0.4*10 = 4.0i m=1,M=2zostaje 4.0(ponieważ m<M→ (10^(M-m))/10<=R( (10^1)/10<=4.0→ 10/10<=4.0→ 1<=4.0) → więc Rpozostaje ten sam ( 4.0))
300+1-300 = 1.0& m=1,M=3staje się 0.0(ponieważ m<M→ (10^(M-m))/10>R( (10^2)/10>1.0→ 100/10>1.0→ 10>1.0) → Rstaje się z 0.0powodu 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`
Ustawia Rsię rna String i modyfikuje go na podstawie wielu czynników.
1203.0& m=4,k=2staje się 1203.(ponieważ k>=1→ tak rstaje się 1001.000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>=m( 8>=4) → podciąg z indeksu 0do m+1( 5))
6.9& m=2,k=2pozostaje 6.9(ponieważ k>=1→ tak rstaje się 6.900; r.length()>=m( 5>=2) → r.contains(".")→ r.length()>=m( 5>=2) → podciąg z indeksu 0do m+1( 3))
1.0& m=3,k=0staje się 1(ponieważ k<1→ tak rstaje się 1; r.length()<m( 1<3) → podciąg od indeksu 0do r.length()( 1))
25.0& m=4,k=4staje się 25.00(ponieważ k>=1→ tak rstaje się 25.00000; r.length()>=m( 8>=4) → r.contains(".")→ r.length()>+m( 8>=4) → podciąg z indeksu 0do m+1( 5))
0& m=1,k=0pozostaje 0(ponieważ k<1→ tak rzostaje 0; r.length()>=m( 1>=1) → !r.contains(".")→ podciąg z indeksu 0do m( 1))
for(i=r.length();i++<l;)
r+=0;
Powoduje to, że w razie potrzeby końcowe zera są ponownie częścią liczby całkowitej.
r="12"i R=1200.0staje sięr="1200"
r="1"i R=10.0staje sięr="10"
r="8"i R=80.0staje sięr="80"
return r.replaceAll(z+"$","");
I w końcu zwracamy wynik, po usunięciu kropek końcowych.
1203. staje się 1203
5. staje się 5
Zdecydowanie można go pograć w golfa o kilkaset bajtów, ale cieszę się, że teraz działa. Zrozumienie każdego z przypadków i tego, o co pytano w wyzwaniu, zajęło już trochę czasu. A potem zajęło dużo prób i błędów, testów i ponownych testów, aby uzyskać powyższy wynik. Podczas pisania powyższego wyjaśnienia udało mi się usunąć kolejne ± 50 bajtów nieużywanego kodu.
999 + 2.00.