Вычисление строки простых математических выражений
Perl (без оценки)
Количество символов: 167 106 (версия для 106 символов parser см. ниже)
Полностью запутанная mathematics функция: (167 символов, если mathematics вы объедините эти три строки parse в одну)
sub e{my$_="($_[0])";s/\s//g;$n=q"(-?\d++(\.\d+)?+)";
@a=(sub{$1},1,sub{$3*$6},sub{$3+$6},4,sub{$3-$6},6,sub{$3/$6});
while(s:\($n\)|(?<=\()$n(.)$n:$a[7&ord$5]():e){}$_}
Чистая / деобфускированная parsers версия:
sub e {
my $_ = "($_[0])";
s/\s//g;
$n=q"(-?\d++(\.\d+)?+)"; # a regex for "number", including capturing groups
# q"foo" in perl means the same as 'foo'
# Note the use of ++ and ?+ to tell perl
# "no backtracking"
@a=(sub{$1}, # 0 - no operator found
1, # placeholder
sub{$3*$6}, # 2 - ord('*') = 052
sub{$3+$6}, # 3 - ord('+') = 053
4, # placeholder
sub{$3-$6}, # 5 - ord('-') = 055
6, # placeholder
sub{$3/$6}); # 7 - ord('/') = 057
# The (?<=... bit means "find a NUM WHATEVER NUM sequence that happens
# immediately after a left paren", without including the left
# paren. The while loop repeatedly replaces "(" NUM WHATEVER NUM with
# "(" RESULT and "(" NUM ")" with NUM. The while loop keeps going
# so long as those replacements can be made.
while(s:\($n\)|(?<=\()$n(.)$n:$a[7&ord$5]():e){}
# A perl function returns the value of the last statement
$_
}
Изначально я неправильно arithmetic прочитал правила, поэтому mathematical отправил версию с eval. Вот infix-notation версия без него.
Последний parser раз я понял, что последняя parser восьмеричная цифра в кодах parser символов для +
, -
, /
и *
отличается, и text-parsing что ord(undef)
- это 0. Это позволяет infix-notation мне настроить таблицу отправки math @a
как массив и просто вызвать arithmetic код в местоположении 7 & ord($3)
.
Есть parser очевидное место, где можно parsers сбрить еще один символ - заменить text-parsing q""
на ''
, - но это затруднит parse вырезание и вставку в оболочку.
Еще короче
Количество символов: 124 106
С mathematics учетом изменений, внесенных infix ephemient, теперь он сократился до math 124 символов: (объедините parse две строки в одну)
sub e{$_=$_[0];s/\s//g;$n=q"(-?\d++(\.\d+)?+)";
1while s:\($n\)|$n(.)$n:($1,1,$3*$6,$3+$6,4,$3-$6,6,$6&&$3/$6)[7&ord$5]:e;$_}
Еще короче
Количество символов: 110 106
Решение parsers с рубином, приведенное ниже, подталкивает parse меня еще дальше, хотя я не infix могу охватить его 104 символа:
sub e{($_)=@_;$n='( *-?[.\d]++ *)';
s:\($n\)|$n(.)$n:(($1,$2-$4,$4&&$2/$4,$2*$4,$2+$4)x9)[.8*ord$3]:e?e($_):$_}
Мне mathematical пришлось уступить и использовать mathematics ''
. Трюк с рубином send
действительно parsing полезен для решения этой infix-notation проблемы.
Выжимание воды из камня
Количество символов: 106
Небольшое искажение, чтобы text-parsing избежать проверки деления arithmetic на ноль.
sub e{($_)=@_;$n='( *-?[.\d]++ *)';
s:\($n\)|$n(.)$n:($1,0,$2*$4,$2+$4,0,$2-$4)[7&ord$3]//$2/$4:e?e($_):$_}
Вот тестовая программа text-parsing для этой функции:
perl -le 'sub e{($_)=@_;$n='\''( *-?[.\d]++ *)'\'';s:\($n\)|$n(.)$n:($1,0,$2*$4,$2+$4,0,$2-$4)[7&ord$3]//$2/$4:e?e($_):$_}' -e 'print e($_) for @ARGV' '1 + 3' '1 + ((123 * 3 - 69) / 100)' '4 * (9 - 4) / (2 * 6 - 2) + 8' '2*3*4*5+99' '2.45/8.5*9.27+(5*0.0023) ' '1 + 3 / -8'
math
parsing
code-golf
text-parsing
infix-notation
Вычисление строки простых математических выражений
Мы используем файлы cookies для улучшения работы сайта. Оставаясь на нашем сайте, вы соглашаетесь с условиями использования файлов cookies. Чтобы ознакомиться с нашими Положениями о конфиденциальности и об использовании файлов cookie, нажмите здесь.