挑战
这是一个挑战(关于我自己的发明,但如果它以前出现在网络的其他地方,我也不会感到惊讶)。
编写一个函数,该函数接受一个参数,该参数是一个简单数学表达式的字符串表示,并将其计算为一个浮点值。“简单表达式”可以包括以下任一项:正负十进制数、+、-、*、/、(
E 210、E 111)E 212。表达式使用(正常) 不确定符号。运算符的计算应该按照它们出现的顺序进行,即不像在BODMAS中那样,当然,方括号应该是正确的。该函数应返回此表单的任何可能表达式的正确结果。但是,函数不必处理格式错误的表达式(即语法错误的表达式)。 表达的例子: 1+3/ -8 = -0.5 (无BODMAS) 2*3*4*5+99 =2194*(9-4)/ (2 *6-2)+8=101+ ((123 *3-69)/ 100) =4 2.45/8.5*9.27+(5*0.0023)=2.68.
规则
我期待一些形式的“欺骗”/craftiness在这里,所以请让我预先警告它!通过欺骗,我指的是在动态语言(如eval或PHP )中使用JavaScript或等效函数,或者在动态语言中同时编译和执行代码。(我认为我的“没有BODMAS”的规范基本上保证了这一点。)除此之外,没有任何限制。我希望这里有一些Regex解决方案,但是看到的不仅仅是这些。
现在,我主要对这里的C#/.NET解决方案感兴趣,但是任何其他语言也是完全可以接受的(特别是函数/混合方法的F#和Python )。我还没有决定是否接受最短或最巧妙的解决方案(至少对于语言而言)作为答案,但我欢迎任何形式的解决方案在任何语言,除了我刚才禁止的!
我的解决方案
我现在已经发布了我的C#解决方案这里 (403个字符)。更新:在294 chars上, 我的新解决方案在一些可爱的正则表达式的帮助下大大击败了旧的!我怀疑一些语言会轻易地用更轻的语法(尤其是funcional/dynamic )来击败它,而且已经被证明是正确的,但我很好奇是否有人还能在C#中击败它。
更新
我已经看到了一些非常狡猾的解决方案。感谢每一个发了一篇文章的人。虽然我还没有测试过其中的任何一个,但我将相信人们,并假设他们至少可以使用所有给定的示例。
只是为了说明,重新进入(即线程安全)并不是函数的必要条件,尽管它是一种奖励。
格式化
为便于比较,请以下列格式张贴所有答案:
语言 字符数:? 完全模糊的功能: (代码在这里) 清晰/半模糊功能: (代码在这里) 任何关于算法的注释/聪明的快捷键。
发布于 2009-06-02 09:19:21
汇编程序
427字节
混淆,与优秀的A86组装成一个.com可执行文件:
dd 0db9b1f89h, 081bee3h, 0e8af789h, 0d9080080h, 0bdac7674h, 013b40286h
dd 07400463ah, 0ccfe4508h, 08ce9f675h, 02fc8000h, 013b0057eh, 0feaac42ah
dd 0bedf75c9h, 0ba680081h, 04de801h, 04874f73bh, 04474103ch, 0e8e8b60fh
dd 08e8a003fh, 0e880290h, 0de0153h, 08b57e6ebh, 0d902a93eh, 046d891dh
dd 08906c783h, 05f02a93eh, 03cffcee8h, 057197510h, 02a93e8bh, 08b06ef83h
dd 05d9046dh, 02a93e89h, 03bc9d95fh, 0ac0174f7h, 074f73bc3h, 0f3cac24h
dd 0eed9c474h, 0197f0b3ch, 07cc4940fh, 074f73b09h, 0103cac09h, 0a3ce274h
dd 0e40a537eh, 0e0d90274h, 02a3bac3h, 021cd09b4h, 03e8b20cdh, 0ff8102a9h
dd 0ed7502abh, 0474103ch, 0e57d0b3ch, 0be02a3bfh, 014d903a3h, 0800344f6h
dd 02db00574h, 0d9e0d9aah, 0d9029f2eh, 0bb34dfc0h, 08a0009h, 01c75f0a8h
dd 020750fa8h, 0b0f3794bh, 021e9aa30h, 0de607400h, 08802990eh, 0de07df07h
dd 0c392ebc1h, 0e8c0008ah, 0aa300404h, 0f24008ah, 04baa3004h, 02eb0ee79h
dd 03005c6aah, 0c0d90ab1h, 0e9defcd9h, 02a116deh, 0e480e0dfh, 040fc8045h
dd 0ede1274h, 0c0d90299h, 015dffcd9h, 047300580h, 0de75c9feh, 0303d804fh
dd 03d80fa74h, 04f01752eh, 0240145c6h, 0dfff52e9h, 0d9029906h, 0f73b025fh
dd 03caca174h, 07fed740ah, 0df07889ah, 0277d807h, 047d9c1deh, 0990ede02h
dd 025fd902h, 03130e0ebh, 035343332h, 039383736h, 02f2b2d2eh, 02029282ah
dd 0e9000a09h, 07fc9f9c1h, 04500000fh, 0726f7272h
db 024h, 0abh, 02h编辑:非混淆源:
mov [bx],bx
finit
mov si,81h
mov di,si
mov cl,[80h]
or cl,bl
jz ret
l1:
lodsb
mov bp,d1
mov ah,19
l2:
cmp al,[bp]
je l3
inc bp
dec ah
jne l2
jmp exit
l3:
cmp ah,2
jle l4
mov al,19
sub al,ah
stosb
l4:
dec cl
jnz l1
mov si,81h
push done
decode:
l5:
call l7
l50:
cmp si,di
je ret
cmp al,16
je ret
db 0fh, 0b6h, 0e8h ; movzx bp,al
call l7
mov cl,[bp+op-11]
mov byte ptr [sm1],cl
db 0deh
sm1:db ?
jmp l50
open:
push di
mov di,word ptr [s]
fstp dword ptr [di]
mov [di+4],bp
add di,6
mov word ptr [s],di
pop di
call decode
cmp al,16
jne ret
push di
mov di,word ptr [s]
sub di,6
mov bp,[di+4]
fld dword ptr [di]
mov word ptr [s],di
pop di
fxch st(1)
cmp si,di
je ret
lodsb
ret
l7: cmp si,di
je exit
lodsb
cmp al,15
je open
fldz
cmp al,11
jg exit
db 0fh, 94h, 0c4h ; sete ah
jl l10
l9:
cmp si,di
je l12
lodsb
cmp al,16
je ret
l10:
cmp al,10
jle l12i
l12:
or ah,ah
je l13
fchs
l13:
ret
exit:
mov dx,offset res
mov ah,9
int 21h
int 20h
done:
mov di,word ptr [s]
cmp di,(offset s)+2
jne exit
cmp al,16
je ok
cmp al,11
jge exit
ok:
mov di,res
mov si,res+100h
fst dword ptr [si]
test byte ptr [si+3],80h
jz pos
mov al,'-'
stosb
fchs
pos:
fldcw word ptr [cw]
fld st(0)
fbstp [si]
mov bx,9
l1000:
mov al,[si+bx]
test al,0f0h
jne startu
test al,0fh
jne startl
dec bx
jns l1000
mov al,'0'
stosb
jmp frac
l12i:
je l11
fimul word ptr [d3]
mov [bx],al
fild word ptr [bx]
faddp
jmp l9
ret
startu:
mov al,[si+bx]
shr al,4
add al,'0'
stosb
startl:
mov al,[si+bx]
and al,0fh
add al,'0'
stosb
dec bx
jns startu
frac:
mov al,'.'
stosb
mov byte ptr [di],'0'
mov cl,10
fld st(0)
frndint
frac1:
fsubp st(1)
ficom word ptr [zero]
fstsw ax
and ah,045h
cmp ah,040h
je finished
fimul word ptr [d3]
fld st(0)
frndint
fist word ptr [di]
add byte ptr [di],'0'
inc di
dec cl
jnz frac1
finished:
dec di
cmp byte ptr [di],'0'
je finished
cmp byte ptr [di],'.'
jne f2
dec di
f2:
mov byte ptr [di+1],'$'
exit2:
jmp exit
l11:
fild word ptr [d3]
fstp dword ptr [bx+2]
l111:
cmp si,di
je ret
lodsb
cmp al,10
je exit2
jg ret
mov [bx],al
fild word ptr [bx]
fdiv dword ptr [bx+2]
faddp
fld dword ptr [bx+2]
fimul word ptr [d3]
fstp dword ptr [bx+2]
jmp l111
d1: db '0123456789.-+/*()', 32, 9
d3: dw 10
op: db 0e9h, 0c1h, 0f9h, 0c9h
cw: dw 0f7fh
zero: dw 0
res:db 'Error$'
s: dw (offset s)+2发布于 2009-06-03 14:23:30
C (VS2005)
字符数: 1360
滥用预处理器和警告以获得有趣的代码布局(向下滚动以查看):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define b main
#define c(a) b(a,0)
#define d -1
#define e -2
#define g break
#define h case
#define hh h
#define hhh h
#define w(i) case i
#define i return
#define j switch
#define k float
#define l realloc
#define m sscanf
#define n int _
#define o char
#define t(u) #u
#define q(r) "%f" t(r) "n"
#define s while
#define v default
#define ex exit
#define W printf
#define x fn()
#define y strcat
#define z strcpy
#define Z strlen
char*p =0 ;k *b (n,o** a){k*f
;j(_){ hh e: i* p==40? (++p,c
(d )) :( f= l( 0,
4) ,m (p ,q (% ),
f,&_), p+=_ ,f ); hh
d:f=c( e);s (1 ){ j(
*p ++ ){ hh 0: hh
41 :i f; hh 43 :*
f+=*c( e) ;g ;h 45:*f= *f-*c(
e);g;h 42 :* f= *f**c( e);g;h
47:*f /=*c (e); g; v: c(0);}
}w(1): if(p&& printf (q (( "\\"))
,* c( d) )) g; hh 0: ex (W
(x )) ;v :p =( p?y: z)(l(p
,Z(1[ a] )+ (p ?Z(p )+
1:1)) ,1 [a ]) ;b (_ -1 ,a
+1 ); g; }i 0;};fn () {n =42,p=
43 ;i "Er" "ro" t( r) "\n";}发布于 2009-05-30 05:07:29
Haskell
字符数:182个
没有尝试聪明,只是一些压缩:4行,312字节。
import Data.Char;import Text.ParserCombinators.Parsec
q=either(error.show)id.runParser t id"".filter(' '/=);t=do
s<-getState;a<-fmap read(many1$oneOf".-"<|>digit)<|>between(char '('>>setState id)(char ')'>>setState s)t
option(s a)$choice(zipWith(\c o->char c>>return(o$s a))"+-*/"[(+),(-),(*),(/)])>>=setState>>t现在,真正进入高尔夫精神,3行182字节:
q=snd.(`e`id).filter(' '/=)
e s c|[(f,h)]<-readsPrec 0 s=g h(c f);e('(':s)c=g h(c f)where(')':h,f)=e s id
g('+':h)=e h.(+);g('-':h)=e h.(-);g('*':h)=e h.(*);g('/':h)=e h.(/);g h=(,)h爆炸:
-- Strip spaces from the input, evaluate with empty accumulator,
-- and output the second field of the result.
q :: String -> Double
q = snd . flip eval id . filter (not . isSpace)
-- eval takes a string and an accumulator, and returns
-- the final value and what’s left unused from the string.
eval :: (Fractional a, Read a) => String -> (a -> a) -> (String, a)
-- If the beginning of the string parses as a number, add it to the accumulator,
-- then try to read an operator and further.
eval str accum | [(num, rest)] <- readsPrec 0 str = oper rest (accum num)
-- If the string starts parentheses, evaluate the inside with a fresh
-- accumulator, and continue after the closing paren.
eval ('(':str) accum = oper rest (accum num) where (')':rest, num) = eval str id
-- oper takes a string and current value, and tries to read an operator
-- to apply to the value. If there is none, it’s okay.
oper :: (Fractional a, Read a) => String -> a -> (String, a)
-- Handle operations by giving eval a pre-seeded accumulator.
oper ('+':str) num = eval str (num +)
oper ('-':str) num = eval str (num -)
oper ('*':str) num = eval str (num *)
oper ('/':str) num = eval str (num /)
-- If there’s no operation parsable, just return.
oper str num = (str, num)https://stackoverflow.com/questions/928563
复制相似问题