Это должно сработать, убедитесь, что вы не забыли $(document).ready(function() {
$(document).ready(function() {
$('#won').change(function(){
alert( $(this).find("option:selected").attr('value') );
});
});
Количество символов: 492
Слегка обфусцированная функция (короткие имена переменных, без пробелов вокруг операторов):
def e(s):
q=[]
b=1
v=[]
for c in s.replace(' ','')+'$':
if c in '.0123456789' or c in '+-' and b and not v:
v+=[c]
else:
if v:
q+=[float(''.join(v))]
v=[]
while len(q)>=3:
x,y,z=q[-3:]
if type(x)==type(z)==float:
if y=='+':q[-3:]=[x+z]
elif y=='-':q[-3:]=[x-z]
elif y=='*':q[-3:]=[x*z]
elif y=='/':q[-3:]=[x/z]
elif (x,z)==('(',')'):q[-3:]=[y]
else:break
if c=='$':break
q+=[c]
b=c!=')'
return q[0]
Я думаю, это относительно легко понять. Это довольно простой и наивный подход. Он ничего не импортирует, не использует регулярное выражение, полностью самодостаточен (одна функция, без глобальных переменных, без побочных эффектов) и должен обрабатывать подписанные литералы (положительные или отрицательные). Использование более разумных имен переменных и соблюдение рекомендованного форматирования Python увеличивает количество символов до 850-900, большая часть этого показателя заключается в использовании четырех пробелов вместо одной табуляции для отступа.
(его 3K, потому что / преобразует результат в число с плавающей запятой)
Число символов: 808
Очистить (я не могу писать запутанный код в Python XD ):
def parse(line):
ops = {"+": lambda x,y:x+y,
"-": lambda x,y:x-y,
"*": lambda x,y:x*y,
"/": lambda x,y:x/y}
def tpp(s, t):
if len(s) > 0 and s[-1] in ops:
f = ops[s.pop()]
t = f(s.pop(), t)
return t
line = line + " "
s = []
t = 0
m = None
for c in line:
if c in "0123456789":
if not m:
m = "i"
if m == "i":
t = t*10 + ord(c)-ord("0")
elif m =="d":
t = t + e*(ord(c)-ord("0"))
e*=0.1
elif c == ".":
m = "d"
e = 0.1
elif m:
t = tpp(s,t)
s.append(t)
m = None
t = 0
if c in ops or c == "(":
s.append(c)
elif c == ")":
t = s.pop()
s.pop()
s.append(tpp(s,t))
t = 0
t = s.pop()
if int(t) == t:
t = int(t)
return t
Я не использую никаких регулярных выражений, даже разбор чисел производится вручную; -)
Довольно просто, сканирует строку, может быть в 3 разных режимах (m), Ни один означает, что число не анализируется, «i» означает, что анализируется целая часть, а «d» означает, что анализируется десятичная часть.
Он использует стек для хранения временных вычислений, когда они завершены анализ числа определяет, был ли оператор в стеке, в этом случае вычисляет и выталкивает. Открывающие скобки просто нажимаются, а закрывающие скобки удаляют открывающую скобку и повторно вставляют текущий eval.
Количество символов: 302
Полу-запутанный:
def e(l)
t=0.0;o=nil
while l!=''
l.sub!(/^\s+/,'')
l.sub!(/^(-?\d+|-?\d+\.\d+)/,'')
t=o ? t.send(o, $1.to_f) : $1.to_f if $~
l.sub!(/^(\+|-|\*|\/)/,'')
o=$1 if $~
l.sub!(/^\(/,'')
t=o ? t.send(o, e(l)) : e(l) if $~
l.sub!(/^\)/,'')
return t if $~
end
t
end
Уничтожает исходную строку, также предполагает, что выражение правильно сформировано (только допустимые символы и соответствующие скобки).
Не запутывается:
def evaluate_expression(expression)
result_so_far = 0.0
last_operator = nil
while (expression != '')
# remove any leading whitespace
expression.sub!(/^\s+/, '')
# extract and remove leading integer or decimal number
expression.sub!(/^(-?\d+|-?\d+\.\d+)/, '')
if $~
# match was successful
number = $1.to_f
if last_operator.nil?
# first number, just store it
result_so_far = number
else
# we have an operator, use it!
# last_operator is a string matching '+', '-', '*' or '/'
# just invoke the method of that name on our result_so_far
# since these operators are just method calls in Ruby
result_so_far = result_so_far.send(last_operator, number)
end
end
# extract and remove leading operator +-*/
expression.sub!(/^(\+|-|\*|\/)/, '')
if $~
# match was successful
last_operator = $1
end
# extract and remove leading open bracket
l.sub!(/^\(/, '')
if $~
# match successful
if last_operator.nil?
# first element in the expression is an open bracket
# so just evaluate its contents recursively
result_so_far = evaluate_expression(expression)
else
# combine the content of the bracketing with the
# result so far using the last_operator
result_so_far.send(last_operator, evaluate_expression(expression))
end
end
# extract and remove leading close bracket
l.sub!(/^\)/, '')
if $~
# match successful
# this must be the end of a recursive call so
# return the result so far without consuming the rest
# of the expression
return result_so_far
end
end
t
end
Рекурсивный вызов управляется модификацией строки выражения, что немного неприятно, но, похоже, работает.
Я удивлен, что никто этого не сделал в Lex / Yacc или его эквиваленте.
Похоже, это дает самый короткий исходный код, который также можно было читать / поддерживать.
Количество символов: 461
Вот решение Марка Гравелла (по сути) преобразованное из C # в F #. Счетчик символов немного лучше, но я решил опубликовать его из интереса.
Обфусцированный код:
let e x=
let rec f(s:string)=
let i=s.IndexOf(')')
if i>0 then
let j=s.LastIndexOf('(',i)
f(s.Substring(0,j)+f(s.Substring(j+1,i-j-1))+s.Substring(i+1))
else
let o=[|'+';'-';'*';'/'|]
let i=s.LastIndexOfAny(o)
let j=s.IndexOfAny(o,max(i-2)0,2)
let k=if j<0 then i else j
if k<0 then s else
let o=s.[k]
string((if o='+'then(+)else if o='-'then(-)else if o='*'then(*)else(/))(float(f(s.Substring(0,k))))(float(s.Substring(k+1))))
float(f x)
Количество символов: 376
Обновленная версия, теперь ее больше? злоупотребление оператором!
Полностью обфусцированное решение:
static double e(String t){t="("+t+")";for(String s:new String[]{"+","-","*","/","(",")"})t=t.replace(s," "+s+" ");return f(new Scanner(t));}static double f(Scanner s){s.next();double a,v=s.hasNextDouble()?s.nextDouble():f(s);while(s.hasNext("[^)]")){char o=s.next().charAt(0);a=s.hasNextDouble()?s.nextDouble():f(s);v=o=='+'?v+a:o=='-'?v-a:o=='*'?v*a:v/a;}s.next();return v;}
Очистить / полуобфусцированную функцию:
static double evaluate(String text) {
text = "(" + text + ")";
for (String s : new String[] {"+", "-", "*", "/", "(", ")" }) {
text = text.replace(s, " " + s + " ");
}
return innerEval(new Scanner(text));
}
static double innerEval(Scanner s) {
s.next();
double arg, val = s.hasNextDouble() ? s.nextDouble() : innerEval(s);
while (s.hasNext("[^)]")) {
char op = s.next().charAt(0);
arg = s.hasNextDouble() ? s.nextDouble() : innerEval(s);
val =
op == '+' ? val + arg :
op == '-' ? val - arg :
op == '*' ? val * arg :
val / arg;
}
s.next();
return val;
}
Количество символов: 93
Полностью скрытая функция: (93 символа, если вы объедините эти три строки в одну)
$_="(@ARGV)";s/\s//g;$n=qr/(-?\d+(\.\d+)?)/;
while(s.\($n\)|(?<=\()$n[-+*/]$n.eval$&.e){}
print
Очистить / semi-obfuscated function:
$_="(@ARGV)"; # Set the default var to "(" argument ")"
s/\s//g; # Strip all spaces from $_
$n=qr/(-?\d+(\.\d+)?)/; # Compile a regex for "number"
# repeatedly replace the sequence "(" NUM ")" with NUM, or if there aren't
# any of those, replace "(" NUM OP NUM with the result
# of doing an eval on just the NUM OP NUM bit.
while(s{\($n\)|(?<=\()$n[-+*/]$n}{eval$&}e){}
# print $_
print
Я думаю, что это довольно хорошо объяснено в "чистой" версии. Две основные идеи заключаются в том, что вы можете сделать код единообразным, заключив аргумент в круглые скобки в начале (специальные символы стоимости), и что достаточно, хотя и в значительной степени неэффективно, обрабатывать данные только рядом с открытой круглой скобкой, заменяя это с его результатом.
Вероятно, проще всего запустить этот код как:
perl -le '$_="(@ARGV)";s/\s//g;$n=qr/(-?\d+(\.\d+)?)/;while(s.\($n\)|(?<=\()$n[-+*/]$n.eval$&.e){}print' '4 * (9 - 4) / (2 * 6 - 2) + 8'
Количество символов: 294
Это частично основан на ответе Джеффа Мозера, но со значительно упрощенной техникой оценки. Могут быть даже другие способы уменьшить количество символов, но теперь я очень рад, что есть решение C # до 300 символов!
Полностью запутанный код:
float e(string x){while(x.Contains("("))x=Regex.Replace(x,@"\(([^\(]*?)\)",m=>e(m.Groups[1].Value).ToString());float r=0;foreach(Match m in Regex.Matches("+"+x,@"\D ?-?[\d.]+")){var o=m.Value[0];var v=float.Parse(m.Value.Substring(1));r=o=='+'?r+v:o=='-'?r-v:o=='*'?r*v:r/v;}return r;}
Более четкий код:
float e(string x)
{
while (x.Contains("("))
x = Regex.Replace(x, @"\(([^\(]*?)\)", m => e(m.Groups[1].Value).ToString());
float r = 0;
foreach (Match m in Regex.Matches("+" + x, @"\D ?-?[\d.]+"))
{
var o = m.Value[0];
var v = float.Parse(m.Value.Substring(1));
r = o == '+' ? r + v : o == '-' ? r - v : o == '*' ? r * v : r / v;
}
return r;
}
Символы: 1670
// not trying to be terse here
#define DIGIT(c)((c)>='0' && (c) <= '9')
#define WHITE(pc) while(*pc == ' ') pc++
#define LP '('
#define RP ')'
bool SeeNum(const char* &pc, float& fNum){
WHITE(pc);
if (!(DIGIT(*pc) || (*pc=='.'&& DIGIT(pc[1])))) return false;
const char* pc0 = pc;
while(DIGIT(*pc)) pc++;
if (*pc == '.'){
pc++;
while(DIGIT(*pc)) pc++;
}
char buf[200];
int len = pc - pc0;
strncpy(buf, pc0, len); buf[len] = 0;
fNum = atof(buf);
return true;
}
bool SeeChar(const char* &pc, char c){
WHITE(pc);
if (*pc != c) return false;
pc++;
return true;
}
void ParsExpr(const char* &pc, float &fNum);
void ParsPrim(const char* &pc, float &fNum){
if (SeeNum(pc, fNum));
else if (SeeChar(pc, LP)){
ParsExpr(pc, fNum);
if (!SeeChar(pc, RP)) exit(0);
}
else exit(0); // you can abort better than this
}
void ParsUnary(const char* &pc, float &fNum){
if (SeeChar(pc, '-')){
pc+;
ParsUnary(pc, fNum);
fNum = -fNum;
}
else {
ParsPrim(pc, fNum);
}
}
void ParsExpr(const char* &pc, float &fNum){
ParsUnary(pc, fNum);
float f1 = 0;
while(true){
if (SeeChar(pc, '+')){
ParsUnary(pc, f1);
fNum += f1;
}
else if (SeeChar(pc, '-')){
ParsUnary(pc, f1);
fNum -= f1;
}
else if (SeeChar(pc, '*')){
ParsUnary(pc, f1);
fNum *= f1;
}
else if (SeeChar(pc, '/')){
ParsUnary(pc, f1);
fNum /= f1;
}
else break;
}
}
Это просто LL1 (рекурсивный спуск). Мне нравится делать это таким образом (хотя я использую двойные), потому что это достаточно быстро и легко вставлять подпрограммы для обработки уровней приоритета.
Number of characters: ~400
A bit ugly, but it works. :) I'm sure regexp would have made it even smaller.
DEFDBL E,f,i,z,q,a,v,o
DEFSTR s,c,k,p
FUNCTION E(s)
i=LEN(s)
DO
IF MID$(s,i,1)="("THEN
q=INSTR(i,s,")")
s=LEFT$(s,i-1)+STR$(E(MID$(s,i+1,q-i-1)))+MID$(s,q+1)
END IF
i-=1
LOOP UNTIL i=0
k="+-*/"
DIM p(PARSECOUNT(s,ANY k))
PARSE s,p(),ANY k
a=VAL(p(0))
FOR i=1TO LEN(s)
c=MID$(s,i,1)
q=INSTR(k,c)
IF q THEN
z+=1
IF o=0 THEN o=q ELSE p(z)=c+p(z)
IF TRIM$(p(z))<>"" THEN
v=VAL(p(z))
a=CHOOSE(o,a+v,a-v,a*v,a/v)
o=0
END IF
END IF
NEXT
E=a
END FUNCTION
Стратегия: первые 2 строки избавляются от скобок по индукции. Затем я разделил на \ -? [\ D.] +
, чтобы получить числа и операторы. затем с помощью агрегата уменьшить массив строк до двойного значения.
Объяснения переменных
m - это выражение в скобках без вложенных скобок.
d - это неуклюжий синтаксис TryParse.
v - аккумулятор для окончательного значения
t - текущий токен.
float E (string s) {var d = 999f; while (d -> 1) s = Regex.Replace (s, @ "(([^ (] ?) ) ", m => E (m.Groups [1] .Value) +" "); return Regex.Split (s, @" (-? [\ d.] +) "). Aggregate (d, (v , t) => (t = t.Trim ()). Length == 0? v:! float.TryParse (t, out d)? (s = t) == ""? 0: v: s == "/"? v / d: s == "-"? vd: s == ""? v * d: v + d);}
float F(string s) {
var d=999f;
while(d-->1)
s=Regex.Replace(s,@"\(([^\(]*?)\)",m=>F(m.Groups[1].Value)+"");
return Regex.Split(s, @"(\-?[\d\.]+)")
.Aggregate(d, (v, t) =>
(t=t.Trim()).Length == 0 ? v :
!float.TryParse(t, out d) ? (s=t) == "" ? 0 : v :
s == "/" ? v / d :
s == "-" ? v - d :
s == "*" ? v * d :
v + d);
}
EDIT: бессовестно украл части из ответа noldorin, повторно использовал s в качестве переменной оператора.
EDIT: 999 вложенных скобок должно хватить для всех.
Количество символов: 170
Полностью запутанная функция:
function a($a,$c='#\(([^()]*)\)#e',$d='a("$1","#^ *-?[\d.]+ *\S *-?[\d.]+ *#e","\$0")'){$e='preg_replace';while($a!=$b=$e($c,$d,$a))$a = $b;return$e('#^(.*)$#e',$d,$a);}
Более четкая функция:
function a($a, $c = '#\(([^()]*)\)#e', $d = 'a("$1", "#^ *-?[\d.]+ *\S *-?[\d.]+ *#e", "\$0")') {
$e = 'preg_replace';
while ($a != $b = $e($c, $d, $a)) {
$a = $b;
}
return $e('#^(.*)$#e', $d, $a);
}
Тесты:
assert(a('1 + 3 / -8') === '-0.5');
assert(a('2*3*4*5+99') === '219');
assert(a('4 * (9 - 4) / (2 * 6 - 2) + 8') === '10');
assert(a('1 + ((123 * 3 - 69) / 100)') === '4');
assert(a('2.45/8.5*9.27+(5*0.0023)') === '2.68344117647');
assert(a(' 2 * 3 * 4 * 5 + 99 ') === '219');
OCaml , используя Camlp4 напрямую :
open Camlp4.PreCast
let expr = Gram.Entry.mk "expr"
EXTEND Gram
expr:
[ [ e1 = expr; "+"; e2 = expr -> e1 + e2
| e1 = expr; "-"; e2 = expr -> e1 - e2 ]
| [ e1 = expr; "*"; e2 = expr -> e1 * e2
| e1 = expr; "/"; e2 = expr -> e1 / e2 ]
| [ n = INT -> int_of_string n
| "("; e = expr; ")" -> e ] ];
END
let () = Gram.parse expr Loc.ghost (Stream.of_string "1-2+3*4")
OCaml с использованием расширения парсера потока Camlp4 :
open Genlex
let lex = make_lexer ["+"; "-"; "*"; "/"; "("; ")"]
let rec parse_atom = parser
| [< 'Int n >] -> n
| [< 'Kwd "("; e=parse_expr; 'Kwd ")" >] -> e
and parse_factor = parser
| [< e1=parse_atom; stream >] ->
(parser
| [< 'Kwd "*"; e2=parse_factor >] -> e1 * e2
| [< 'Kwd "/"; e2=parse_factor >] -> e1 / e2
| [< >] -> e1) stream
and parse_expr = parser
| [< e1=parse_factor; stream >] ->
(parser
| [< 'Kwd "+"; e2=parse_expr >] -> e1 + e2
| [< 'Kwd "-"; e2=parse_expr >] -> e1 - e2
| [< >] -> e1) stream
let () =
Printf.printf "%d\n" (parse_expr(lex(Stream.of_string "1 + 2 * (3 + 4)")));;