تقييم سلسلة بسيطة التعبيرات الرياضية [مغلقة]
-
06-09-2019 - |
سؤال
التحدي
هنا هو التحدي (من اختراعي, على الرغم من أنني لن يفاجأ إذا كانت قد ظهرت سابقا في مكان آخر على شبكة الإنترنت).
كتابة دالة التي تأخذ واحدة الحجة التي هي سلسلة تمثيل بسيط التعبير الرياضي وتقييم على أنها قيمة النقطة العائمة.A "تعبير بسيط" قد تتضمن أي من التالية:إيجابية أو سلبية الأرقام العشرية ، +, -, *, /, (, ).تستخدم التعبيرات (عادي) أقحم التدوين.يجب على المشغلين أن يقيم في لكي تظهر أي لا كما في BODMAS, على الرغم من الأقواس يجب أن يكون بشكل صحيح لاحظ بالطبع.وظيفة يجب أن تعود النتيجة الصحيحة عن أي ممكن التعبير من هذا النموذج.ومع ذلك ، فإن وظيفة لا التعامل مع تالف التعبير (أيتلك مع سوء الجملة).
أمثلة على التعبيرات:
1 + 3 / -8 = -0.5 (No BODMAS) 2*3*4*5+99 = 219 4 * (9 - 4) / (2 * 6 - 2) + 8 = 10 1 + ((123 * 3 - 69) / 100) = 4 2.45/8.5*9.27+(5*0.0023) = 2.68...
القواعد
وأتوقع بعض شكل من "الغش"/مكر هنا, لذا يرجى اسمحوا لي تحذير ضد ذلك!عن طريق الغش ، أود أن أشير إلى استخدام eval
أو ما يعادل وظيفة في ديناميكية لغات مثل جافا سكريبت أو PHP أو قدم المساواة إعداد و تنفيذ التعليمات البرمجية على الطاير.(أعتقد أن مواصفات "لا BODMAS" وقد مضمونة هذا ولكن.) وبصرف النظر عن أنه لا توجد أية قيود.وأتوقع بعض التعابير المنطقية الحلول هنا ، ولكن سيكون من الجميل أن نرى أكثر من ذلك.
الآن, أنا مهتمة أساسا في C#/.صافي الحل هنا لكن أي لغة أخرى تكون مقبولة تماما أيضا (على وجه الخصوص ، و# و الثعبان الوظيفي/مختلطة النهج).لم أقرر بعد ما إذا كنت سوف تقبل أقصر أو الأكثر عبقرية الحل (على الأقل في اللغة) والجواب ، ولكن أود أن أرحب أي شكل من أشكال الحل في أي لغة, إلا ما لقد يحظر أعلاه!
الحل
لقد شارك الآن بلدي C# الحل هنا (403 حرف). تحديث: بلدي الحل الجديد وقد ضرب القديم بشكل كبير في 294 حرف, مع مساعدة من قليلا من جميل regex!كنت أظن أن هذا سوف تحصل بسهولة للضرب من قبل بعض اللغات هناك مع أخف جملة (لا سيما funcional/ديناميكية منها) ، وقد ثبت الحق ، ولكن سأكون غريبة إذا كان شخص ما يمكن أن يضرب هذا في C# لا يزال.
التحديث
لقد رأيت بعض ماكرة جدا الحلول بالفعل.شكرا لكل من شارك واحدة.على الرغم من أنني لم تختبر أي منهم حتى الآن أنا ذاهب إلى ثقة الناس تفترض أنها على الأقل مع إعطاء أمثلة.
فقط ملاحظة إعادة entrancy (أيموضوع السلامة) ، لا شرط الوظيفة ، على الرغم من أنه هو مكافأة.
شكل
الرجاء الرد على جميع الإجابات على الشكل التالي لغرض المقارنة سهلة:
اللغة
عدد الأحرف:???
تماما غموض وظيفة:
(code here)
واضح/شبه غموض وظيفة:
(code here)
أي ملاحظات على خوارزمية/اختصارات ذكية يلزم.
المحلول
بيرل (لا eval)
عدد الأحرف: 167 106 (انظر أدناه للحصول على 106 حرف الإصدار)
تماما غموض وظيفة:(167 الأحرف إذا كان يمكنك الانضمام إلى هذه الخطوط الثلاثة في واحد)
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){}$_}
واضح/deobfuscated الإصدار:
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
$_
}
كنت قد أساء القواعد في البداية, لذا يجب أن تقدم نسخة مع "ايفال".وهنا نسخة دون ذلك.
أحدث نوعا من البصيرة عندما أدركت أن آخر ثماني أرقام في شخصية رموز +
, -
, /
, ، *
هو مختلف ، ord(undef)
0.هذا يتيح لي انشاء الجدول الإرسال @a
كما صفيف ، و استدعاء التعليمات البرمجية في الموقع 7 & ord($3)
.
هناك بقعة واضحة أن يحلق شخصية اخرى - تغيير q""
في ''
- ولكن هذا من شأنه أن يجعل من الصعب قص ولصق في وعاء.
حتى أقصر
عدد الأحرف: 124 106
أخذ التعديلات من قبل ephemient في الاعتبار, أنه الآن وصولا إلى 124 الشخصيات:(الانضمام إلى خطين في واحد)
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
روبي الحل في الأسفل تضغط علي كذلك ، على الرغم من أنني لا يمكن أن تصل إلى 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($_):$_}
كان علي أن تعطي في استخدام ''
.أن روبي send
خدعة مفيدة حقا لهذه المشكلة.
الضغط على المياه من الحجر
عدد الأحرف:106
صغير التواء لتجنب تقسيم-من قبل-صفر الاختيار.
sub e{($_)=@_;$n='( *-?[.\d]++ *)';
s:\($n\)|$n(.)$n:($1,0,$2*$4,$2+$4,0,$2-$4)[7&ord$3]//$2/$4:e?e($_):$_}
هنا هو اختبار تسخير لهذه الوظيفة:
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'
نصائح أخرى
مجمع
427 بايت
obfcated، تجميعها مع ممتاز 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
روبي
عدد الشخصيات: 103
N='( *-?[\d.]+ *)'
def e x
x.sub!(/\(#{N}\)|#{N}([^.\d])#{N}/){$1or(e$2).send$3,e($4)}?e(x):x.to_f
end
هذا ال غير العودية نسخة من محلول البراغيث الشرير. يتم تقييم التعبيرات الفرعية بين قوسين من أسفل إلى أعلى من أعلى إلى أسفل.
يحرر: تحويل "بينما" إلى عريضة ذيل مشروطة أنقذ بعض الأحرف، لذلك لم يعد غير متراكف (على الرغم من أن العودية ليست ضرورية دلالة.)
يحرر: اقتراض فكرة دانيال مارتن عن دمج Regexps يوفر 11 حرفا آخر!
يحرر: أن العودية أكثر فائدة مما اعتقدت لأول مرة! x.to_f
يمكن إعادة كتابتها e(x)
, ، إذا x
يحدث لاحتواء رقم واحد.
يحرر: استخدام 'or
' بدلا من '||
يسمح بإسقاط زوج من الأقواس.
نسخة طويلة:
# Decimal number, as a capturing group, for substitution
# in the main regexp below.
N='( *-?[\d.]+ *)'
# The evaluation function
def e(x)
matched = x.sub!(/\(#{N}\)|#{N}([^\d.])#{N}/) do
# Group 1 is a numeric literal in parentheses. If this is present then
# just return it.
if $1
$1
# Otherwise, $3 is an operator symbol and $2 and $4 are the operands
else
# Recursively call e to parse the operands (we already know from the
# regexp that they are numeric literals, and this is slightly shorter
# than using :to_f)
e($2).send($3, e($4))
# We could have converted $3 to a symbol ($3.to_s) or converted the
# result back to string form, but both are done automatically anyway
end
end
if matched then
# We did one reduction. Now recurse back and look for more.
e(x)
else
# If the string doesn't look like a non-trivial expression, assume it is a
# string representation of a real number and attempt to parse it
x.to_f
end
end
ج (VS2005)
عدد الشخصيات: 1360
إساءة استخدام Preprocessor وتحذيرات تخطيط رمز ممتع (قم بالتمرير لأسفل لرؤية):
#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";}
Visual Basic.net.
عدد الشخصيات: 9759
أنا أكثر من الرامي نفسي.
ملاحظة: لا يأخذ الأقواس المتداخلة في الاعتبار. أيضا، لم تختبر، لكنني متأكد من أنه يعمل.
Imports Microsoft.VisualBasic
Imports System.Text
Imports System.Collections.Generic
Public Class Main
Public Shared Function DoArithmaticFunctionFromStringInput(ByVal MathematicalString As String) As Double
Dim numberList As New List(Of Number)
Dim operationsList As New List(Of IOperatable)
Dim currentNumber As New Number
Dim currentParentheticalStatement As New Parenthetical
Dim isInParentheticalMode As Boolean = False
Dim allCharactersInString() As Char = MathematicalString.ToCharArray
For Each mathChar In allCharactersInString
If mathChar = Number.ZERO_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.ONE_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.TWO_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.THREE_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.FOUR_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.FIVE_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.SIX_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.SEVEN_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.EIGHT_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.NINE_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Number.DECIMAL_POINT_STRING_REPRESENTATION Then
currentNumber.UpdateNumber(mathChar)
ElseIf mathChar = Addition.ADDITION_STRING_REPRESENTATION Then
Dim addition As New Addition
If Not isInParentheticalMode Then
operationsList.Add(addition)
numberList.Add(currentNumber)
Else
currentParentheticalStatement.AllNumbers.Add(currentNumber)
currentParentheticalStatement.AllOperators.Add(addition)
End If
currentNumber = New Number
ElseIf mathChar = Number.NEGATIVE_NUMBER_STRING_REPRESENTATION Then
If currentNumber.StringOfNumbers.Length > 0 Then
currentNumber.UpdateNumber(mathChar)
Dim subtraction As New Addition
If Not isInParentheticalMode Then
operationsList.Add(subtraction)
numberList.Add(currentNumber)
Else
currentParentheticalStatement.AllNumbers.Add(currentNumber)
currentParentheticalStatement.AllOperators.Add(subtraction)
End If
currentNumber = New Number
Else
currentNumber.UpdateNumber(mathChar)
End If
ElseIf mathChar = Multiplication.MULTIPLICATION_STRING_REPRESENTATION Then
Dim multiplication As New Multiplication
If Not isInParentheticalMode Then
operationsList.Add(multiplication)
numberList.Add(currentNumber)
Else
currentParentheticalStatement.AllNumbers.Add(currentNumber)
currentParentheticalStatement.AllOperators.Add(multiplication)
End If
currentNumber = New Number
ElseIf mathChar = Division.DIVISION_STRING_REPRESENTATION Then
Dim division As New Division
If Not isInParentheticalMode Then
operationsList.Add(division)
numberList.Add(currentNumber)
Else
currentParentheticalStatement.AllNumbers.Add(currentNumber)
currentParentheticalStatement.AllOperators.Add(division)
End If
currentNumber = New Number
ElseIf mathChar = Parenthetical.LEFT_PARENTHESIS_STRING_REPRESENTATION Then
isInParentheticalMode = True
ElseIf mathChar = Parenthetical.RIGHT_PARENTHESIS_STRING_REPRESENTATION Then
currentNumber = currentParentheticalStatement.EvaluateParentheticalStatement
numberList.Add(currentNumber)
isInParentheticalMode = False
End If
Next
Dim result As Double = 0
Dim operationIndex As Integer = 0
For Each numberOnWhichToPerformOperations As Number In numberList
result = operationsList(operationIndex).PerformOperation(result, numberOnWhichToPerformOperations)
operationIndex = operationIndex + 1
Next
Return result
End Function
Public Class Number
Public Const DECIMAL_POINT_STRING_REPRESENTATION As Char = "."
Public Const NEGATIVE_NUMBER_STRING_REPRESENTATION As Char = "-"
Public Const ZERO_STRING_REPRESENTATION As Char = "0"
Public Const ONE_STRING_REPRESENTATION As Char = "1"
Public Const TWO_STRING_REPRESENTATION As Char = "2"
Public Const THREE_STRING_REPRESENTATION As Char = "3"
Public Const FOUR_STRING_REPRESENTATION As Char = "4"
Public Const FIVE_STRING_REPRESENTATION As Char = "5"
Public Const SIX_STRING_REPRESENTATION As Char = "6"
Public Const SEVEN_STRING_REPRESENTATION As Char = "7"
Public Const EIGHT_STRING_REPRESENTATION As Char = "8"
Public Const NINE_STRING_REPRESENTATION As Char = "9"
Private _isNegative As Boolean
Public ReadOnly Property IsNegative() As Boolean
Get
Return _isNegative
End Get
End Property
Public ReadOnly Property ActualNumber() As Double
Get
Dim result As String = ""
If HasDecimal Then
If DecimalIndex = StringOfNumbers.Length - 1 Then
result = StringOfNumbers.ToString
Else
result = StringOfNumbers.Insert(DecimalIndex, DECIMAL_POINT_STRING_REPRESENTATION).ToString
End If
Else
result = StringOfNumbers.ToString
End If
If IsNegative Then
result = NEGATIVE_NUMBER_STRING_REPRESENTATION & result
End If
Return CType(result, Double)
End Get
End Property
Private _hasDecimal As Boolean
Public ReadOnly Property HasDecimal() As Boolean
Get
Return _hasDecimal
End Get
End Property
Private _decimalIndex As Integer
Public ReadOnly Property DecimalIndex() As Integer
Get
Return _decimalIndex
End Get
End Property
Private _stringOfNumbers As New StringBuilder
Public ReadOnly Property StringOfNumbers() As StringBuilder
Get
Return _stringOfNumbers
End Get
End Property
Public Sub UpdateNumber(ByVal theDigitToAppend As Char)
If IsNumeric(theDigitToAppend) Then
Me._stringOfNumbers.Append(theDigitToAppend)
ElseIf theDigitToAppend = DECIMAL_POINT_STRING_REPRESENTATION Then
Me._hasDecimal = True
Me._decimalIndex = Me._stringOfNumbers.Length
ElseIf theDigitToAppend = NEGATIVE_NUMBER_STRING_REPRESENTATION Then
Me._isNegative = Not Me._isNegative
End If
End Sub
Public Shared Function ConvertDoubleToNumber(ByVal numberThatIsADouble As Double) As Number
Dim numberResult As New Number
For Each character As Char In numberThatIsADouble.ToString.ToCharArray
numberResult.UpdateNumber(character)
Next
Return numberResult
End Function
End Class
Public MustInherit Class Operation
Protected _firstnumber As New Number
Protected _secondnumber As New Number
Public Property FirstNumber() As Number
Get
Return _firstnumber
End Get
Set(ByVal value As Number)
_firstnumber = value
End Set
End Property
Public Property SecondNumber() As Number
Get
Return _secondnumber
End Get
Set(ByVal value As Number)
_secondnumber = value
End Set
End Property
End Class
Public Interface IOperatable
Function PerformOperation(ByVal number1 As Double, ByVal number2 As Number) As Double
End Interface
Public Class Addition
Inherits Operation
Implements IOperatable
Public Const ADDITION_STRING_REPRESENTATION As String = "+"
Public Sub New()
End Sub
Public Function PerformOperation(ByVal number1 As Double, ByVal number2 As Number) As Double Implements IOperatable.PerformOperation
Dim result As Double = 0
result = number1 + number2.ActualNumber
Return result
End Function
End Class
Public Class Multiplication
Inherits Operation
Implements IOperatable
Public Const MULTIPLICATION_STRING_REPRESENTATION As String = "*"
Public Sub New()
End Sub
Public Function PerformOperation(ByVal number1 As Double, ByVal number2 As Number) As Double Implements IOperatable.PerformOperation
Dim result As Double = 0
result = number1 * number2.ActualNumber
Return result
End Function
End Class
Public Class Division
Inherits Operation
Implements IOperatable
Public Const DIVISION_STRING_REPRESENTATION As String = "/"
Public Const DIVIDE_BY_ZERO_ERROR_MESSAGE As String = "I took a lot of time to write this program. Please don't be a child and try to defile it by dividing by zero. Nobody thinks you are funny."
Public Sub New()
End Sub
Public Function PerformOperation(ByVal number1 As Double, ByVal number2 As Number) As Double Implements IOperatable.PerformOperation
If Not number2.ActualNumber = 0 Then
Dim result As Double = 0
result = number1 / number2.ActualNumber
Return result
Else
Dim divideByZeroException As New Exception(DIVIDE_BY_ZERO_ERROR_MESSAGE)
Throw divideByZeroException
End If
End Function
End Class
Public Class Parenthetical
Public Const LEFT_PARENTHESIS_STRING_REPRESENTATION As String = "("
Public Const RIGHT_PARENTHESIS_STRING_REPRESENTATION As String = ")"
Private _allNumbers As New List(Of Number)
Public Property AllNumbers() As List(Of Number)
Get
Return _allNumbers
End Get
Set(ByVal value As List(Of Number))
_allNumbers = value
End Set
End Property
Private _allOperators As New List(Of IOperatable)
Public Property AllOperators() As List(Of IOperatable)
Get
Return _allOperators
End Get
Set(ByVal value As List(Of IOperatable))
_allOperators = value
End Set
End Property
Public Sub New()
End Sub
Public Function EvaluateParentheticalStatement() As Number
Dim result As Double = 0
Dim operationIndex As Integer = 0
For Each numberOnWhichToPerformOperations As Number In AllNumbers
result = AllOperators(operationIndex).PerformOperation(result, numberOnWhichToPerformOperations)
operationIndex = operationIndex + 1
Next
Dim numberToReturn As New Number
numberToReturn = Number.ConvertDoubleToNumber(result)
Return numberToReturn
End Function
End Class
End Class
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)
بيثون
عدد الشخصيات: 237
وظيفة التباطؤ بالكامل:
from operator import*
def e(s,l=[]):
if s:l+=list(s.replace(' ','')+')')
a=0;o=add;d=dict(zip(')*+-/',(0,mul,o,sub,div)));p=l.pop
while o:
c=p(0)
if c=='(':c=e(0)
while l[0]not in d:c+=p(0)
a=o(a,float(c));o=d[p(0)]
return a
وظيفة واضحة / شبه عبفا:
import operator
def calc(source, stack=[]):
if source:
stack += list(source.replace(' ', '') + ')')
answer = 0
ops = {
')': 0,
'*': operator.mul,
'+': operator.add,
'-': operator.sub,
'/': operator.div,
}
op = operator.add
while op:
cur = stack.pop(0)
if cur == '(':
cur = calc(0)
while stack[0] not in ops:
cur += stack.pop(0)
answer = op(answer, float(cur))
op = ops[stack.pop(0)]
return answer
FORTRAN 77 (لهجة Govortran، الآن مع دعم G77)
عدد الشخصيات: 2059
النسخة المبهجة:
function e(c)
character*99 c
character b
real f(24)
integer i(24)
nf=0
ni=0
20 nf=kf(0.0,nf,f)
ni=ki(43,ni,i)
30 if (isp(c).eq.1) goto 20
h=fr(c)
31 g=fp(nf,f)
j=ip(ni,i)
select case(j)
case (40)
goto 20
case (42)
d=g*h
case (43)
d=g+h
case (45)
d=g-h
case (47)
d=g/h
end select
50 nf=kf(d,nf,f)
60 j=nop(c)
goto (20, 70, 75, 75, 60, 75, 60, 75) (j-39)
65 e=fp(nf,f)
return
70 h=fp(nf,f)
goto 31
75 ni=ki(j,ni,i)
goto 30
end
function kf(v,n,f)
real f(24)
kf=n+1
f(n+1)=v
return
end
function ki(j,n,i)
integer i(24)
ki=n+1
i(n+1)=j
return
end
function fp(n,f)
real f(24)
fp=f(n)
n=n-1
return
end
function ip(n,i)
integer i(24)
ip=i(n)
n=n-1
return
end
function nop(s)
character*99 s
l=1
do while(s(l:l).eq." ".and.l.lt.99)
l=l+1
enddo
nop=ichar(s(l:l))
s(l:l)=" "
return
end
function isp(s)
character*99 s
isp=0
l=1
do while(s(l:l).eq." ".and.l.lt.99)
l=l+1
enddo
isp=41-ichar(s(l:l))
if (isp.eq.1) s(l:l)=" "
return
end
function fr(s)
character*99 s
m=1
n=1
i=1
do while(i.le.99)
j=ichar(s(i:i))
if (j.eq.32) goto 90
if (j.ge.48.and.j.lt.58) goto 89
if (j.eq.43.or.j.eq.45) goto (89,80) m
if (j.eq.46) goto (83,80) n
80 exit
83 n=2
89 m=2
90 i=i+1
enddo
read(s(1:i-1),*) fr
do 91 j=1,i-1
s(j:j)=" "
91 continue
return
end
نسخة واضحة: (3340 حرفا مع سقالة)
program infixeval
character*99 c
do while (.true.)
do 10 i=1,99
c(i:i)=" "
10 continue
read(*,"(A99)") c
f=e(c)
write(*,*)f
enddo
end
function e(c)
character*99 c
character b
real f(24) ! value stack
integer i(24) ! operator stack
nf=0 ! number of items on the value stack
ni=0 ! number of items on the operator stack
20 nf=pushf(0.0,nf,f)
ni=pushi(43,ni,i) ! ichar(+) = 43
D write (*,*) "'",c,"'"
30 if (isp(c).eq.1) goto 20
h=fr(c)
D write (*,*) "'",c,"'"
31 g=fpop(nf,f)
j=ipop(ni,i)
D write(*,*) "Opperate ",g," ",char(j)," ",h
select case(j)
case (40)
goto 20
case (42) ! "*"
d=g*h
case (43) ! "+"
d=g+h
case (45) ! "-"
d=g-h
case (47) ! "*"
d=g/h
end select
50 nf=pushf(d,nf,f)
60 j=nop(c)
D write(*,*) "Got op: ", char(j)
goto (20, 70, 75, 75, 60, 75, 60, 75) (j-39)
65 e=fpop(nf,f)
return
70 h=fpop(nf,f) ! Encountered a "("
goto 31
75 ni=pushi(j,ni,i)
goto 30
end
c push onto a real stack
c OB as kf
function pushf(v,n,f)
real f(24)
pushf=n+1
f(n+1)=v
D write(*,*) "Push ", v
return
end
c push onto a integer stack
c OB as ki
function pushi(j,n,i)
integer i(24)
pushi=n+1
i(n+1)=j
D write(*,*) "Push ", char(j)
return
end
c pop from real stack
c OB as fp
function fpop(n,f)
real f(24)
fpop=f(n)
n=n-1
D write (*,*) "Pop ", fpop
return
end
c pop from integer stack
c OB as ip
function ipop(n,i)
integer i(24)
ipop=i(n)
n=n-1
D write (*,*) "Pop ", char(ipop)
return
end
c Next OPerator: returns the next nonws character, and removes it
c from the string
function nop(s)
character*99 s
l=1
do while(s(l:l).eq." ".and.l.lt.99)
l=l+1
enddo
nop=ichar(s(l:l))
s(l:l)=" "
return
end
c IS an open Paren: return 1 if the next non-ws character is "("
c (also overwrite it with a space. Otherwise return not 1
function isp(s)
character*99 s
isp=0
l=1
do while(s(l:l).eq." ".and.l.lt.99)
l=l+1
enddo
isp=41-ichar(s(l:l))
if (isp.eq.1) s(l:l)=" "
return
end
c Float Read: return the next real number in the string and removes the
c character
function fr(s)
character*99 s
m=1 ! No sign (Minus or plus) so far
n=1 ! No decimal so far
i=1
do while(i.le.99)
j=ichar(s(i:i))
if (j.eq.32) goto 90 ! skip spaces
if (j.ge.48.and.j.lt.58) goto 89
if (j.eq.43.or.j.eq.45) goto (89,80) m
if (j.eq.46) goto (83,80) n
c not part of a number
80 exit
83 n=2
89 m=2
90 i=i+1
enddo
read(s(1:i-1),*) fr
do 91 j=1,i-1
s(j:j)=" "
91 continue
return
end
ملاحظات هذا الإصدار المحرر أكثر شررا أكثر من محاولتي الأولى. نفس الخوارزمية، ولكن الآن مضمنة مع تشابك فظيع من goto
س. لقد تخللت الروتين المشارك، لكنني الآن باستخدام بضع نكهات من الفروع المحسوبة. تمت إزالة جميع فحص الأخطاء وإعداد التقارير، ولكن هذا الإصدار سوف يتعافى بصمت من بعض الفئات من الأحرف غير المتوقعة في الإدخال. هذا الإصدار يتجمع أيضا مع G77.
الحدود الأساسية لا تزال تنسيق فورتران الصلب والكلمات الرئيسية الطويلة في كل مكان، والبئرية البسيطة.
C99.
عدد الشخصيات: 239 (ولكن انظر أدناه ل 209)
وظيفة مضغوطة:
#define S while(*e==32)++e
#define F float
F strtof();char*e;F v();F g(){S;return*e++-40?strtof(e-1,&e):v();}F v(){F b,a=g();for(;;){S;F o=*e++;if(!o|o==41)return a;b=g();a=o==43?a+b:o==45?a-b:o==42?a*b:a/b;}}F f(char*x){e=x;return v();}
وظيفة decompressed:
float strtof();
char* e;
float v();
float g() {
while (*e == ' ') ++e;
return *e++ != '(' ? strtof(e-1, &e) : v();
}
float v() {
float b, a = g();
for (;;) {
while (*e == ' ') ++e;
float op = *e++;
if (op == 0 || op == ')') return a;
b = g();
a = op == '+' ? a + b : op == '-' ? a - b : op == '*' ? a * b : a / b;
}
}
float eval(char* x) {
e = x;
return v();
}
وظيفة ليست إعادة الدخول.
تحرير من كريس لوتز: أنا أكره الدوس على رمز رجل آخر، ولكن هنا هو 209-Character النسخة:
#define S for(;*e==32;e++)
#define X (*e++-40?strtof(e-1,&e):v())
float strtof();char*e;float v(){float o,a=X;for(;;){S;o=*e++;if(!o|o==41)return a;S;a=o-43?o-45?o-42?a/X:a*X:a-X:a+X;}}
#define f(x) (e=x,v())
قابل للقراءة (حسنا، ليست حقا مقروءة جدا، ولكن DemoMpressed):
float strtof();
char *e;
float v() {
float o, a = *e++ != '(' ? strtof(e - 1, &e) : v();
for(;;) {
for(; *e == ' '; e++);
o = *e++;
if(o == 0 || o==')') return a;
for(; *e == ' '; e++);
// I have no idea how to properly indent nested conditionals
// and this is far too long to fit on one line.
a = o != '+' ?
o != '-' ?
o != '*' ?
a / (*e++ != '(' ? strtof(e - 1, &e) : v()) :
a * (*e++ != '(' ? strtof(e - 1, &e) : v()) :
a - (*e++ != '(' ? strtof(e - 1, &e) : v()) :
a + (*e++ != '(' ? strtof(e - 1, &e) : v());
}
}
#define f(x) (e = x, v())
نعم، f()
هو ماكرو، وليس وظيفة، ولكنها تعمل. النسخة القابلة للقراءة لديها بعض من المنطق أعيد كتابتها ولكن لم يتم إعادة ترتيبها (مثل o != '+'
بدلا من o - '+'
)، ولكن هل مجرد إصدار مسافة بادئة (والمعبادة) من الآخر. واصلت محاولة تبسيط if(!o|o==41)return a;
جزء في for()
حلقة، لكنها لا تجعلها أقصر. ما زلت أعتقد أنه يمكن القيام به، لكنني انتهيت من الغولف. إذا كنت أعمل في هذا السؤال بعد الآن، فستكون في اللغة التي يجب عدم اسمها.
lisp المشترك
(SBCL)
عدد الشخصيات: 251
(defun g(e)(if(numberp e)e(let((m (g (pop e)))(o(loop for x in e by #'cddr collect x))(n(loop for x in (cdr e)by #'cddr collect (g x))))(mapcar(lambda(x y)(setf m(apply x(list m y))))o n)m)))(defun w(e)(g(read-from-string(concatenate'string"("e")"))))
الإصدار المناسب (387 حرف):
(defun wrapper (exp) (golf-eval (read-from-string (concatenate 'string "(" exp ")"))))
(defun golf-eval (exp)
(if (numberp exp)
exp
(let ((mem (golf-eval (pop exp)))
(op-list (loop for x in exp by #'cddr collect x))
(num-list (loop for x in (cdr exp) by #'cddr collect (golf-eval x))))
(mapcar (lambda (x y) (setf mem (apply x (list mem y)))) op-list num-list)
mem)))
المدخلات هي شكل w()
, ، والتي تأخذ حجة سلسلة واحدة. يستخدم الخدعة التي تطبق / المعاملات والمشغلون في نمط nonon ... ويقيم بشكل متكرر جميع المعاملات، وبالتالي الحصول على التعشيش رخيصة جدا. ؛)
جافا سكريبت (وليس متوافق)
عدد الشخصيات: 268/260
وظيفة التباطؤ بالكامل:
function e(x){x=x.replace(/ /g,'')+')'
function P(n){return x[0]=='('?(x=x.substr(1),E()):(n=/^[-+]?[\d.]+/(x)[0],x=x.substr(n.length),+n)}function E(a,o,b){a=P()
for(;;){o=x[0]
x=x.substr(1)
if(o==')')return a
b=P()
a=o=='+'?a+b:o=='-'?a-b:o=='*'?a*b:a/b}}return E()}
أو في JavaScript 1.8 (Firefox 3+)، يمكنك حفظ بعض الأحرف باستخدام إغلاق التعبير:
e=function(x,P,E)(x=x.replace(/ /g,'')+')',P=function(n)(x[0]=='('?(x=x.substr(1),E()):(n=/^[-+]?[\d.]+/(x)[0],x=x.substr(n.length),+n)),E=function(a,o,b){a=P()
for(;;){o=x[0]
x=x.substr(1)
if(o==')')return a
b=P()
a=o=='+'?a+b:o=='-'?a-b:o=='*'?a*b:a/b}},E())
وظيفة واضحة / شبه عبفا:
function evaluate(x) {
x = x.replace(/ /g, "") + ")";
function primary() {
if (x[0] == '(') {
x = x.substr(1);
return expression();
}
var n = /^[-+]?\d*\.?\d*/.exec(x)[0];
x = x.substr(n.length);
return +n;
}
function expression() {
var a = primary();
for (;;) {
var operator = x[0];
x = x.substr(1);
if (operator == ')') {
return a;
}
var b = primary();
a = (operator == '+') ? a + b :
(operator == '-') ? a - b :
(operator == '*') ? a * b :
a / b;
}
}
return expression();
}
لن تعمل أي إصدار في IE، لأنهم يستخدمون الاشتراكات على غرار الصفيف على السلسلة. إذا استبدلت كلا الحوادث x[0]
مع x.charAt(0)
, ، أول واحد يجب أن يعمل في كل مكان.
لقد قطعت بعض الأحرف الأخرى منذ الإصدار الأول عن طريق تحويل المتغيرات إلى معلمات الوظيفة واستبدالها آخر إذا كان العبارة الشرطية.
ج # مع ريجيكس الحب
عدد الشخصيات: 384
تعطل بالكامل:
float E(string i){i=i.Replace(" ","");Regex b=new Regex(@"\((?>[^()]+|\((?<D>)|\)(?<-D>))*(?(D)(?!))\)");i=b.Replace(i,m=>Eval(m.Value.Substring(1,m.Length-2)).ToString());float r=0;foreach(Match m in Regex.Matches(i,@"(?<=^|\D)-?[\d.]+")){float f=float.Parse(m.Value);if(m.Index==0)r=f;else{char o=i[m.Index-1];if(o=='+')r+=f;if(o=='-')r-=f;if(o=='*')r*=f;if(o=='/')r/=f;}}return r;}
غير مبتهج:
private static float Eval(string input)
{
input = input.Replace(" ", "");
Regex balancedMatcher = new Regex(@"\(
(?>
[^()]+
|
\( (?<Depth>)
|
\) (?<-Depth>)
)*
(?(Depth)(?!))
\)", RegexOptions.IgnorePatternWhitespace);
input = balancedMatcher.Replace(input, m => Eval(m.Value.Substring(1, m.Length - 2)).ToString());
float result = 0;
foreach (Match m in Regex.Matches(input, @"(?<=^|\D)-?[\d.]+"))
{
float floatVal = float.Parse(m.Value);
if (m.Index == 0)
{
result = floatVal;
}
else
{
char op = input[m.Index - 1];
if (op == '+') result += floatVal;
if (op == '-') result -= floatVal;
if (op == '*') result *= floatVal;
if (op == '/') result /= floatVal;
}
}
return result;
}
يستفيد من .NET's Regex موازنة مجموعة ميزة.
بي أتش بي
عدد الشخصيات: 284
تباطؤ:
function f($m){return c($m[1]);}function g($n,$m){$o=$m[0];$m[0]=' ';return$o=='+'?$n+$m:($o=='-'?$n-$m:($o=='*'?$n*$m:$n/$m));}function c($s){while($s!=($t=preg_replace_callback('/\(([^()]*)\)/',f,$s)))$s=$t;preg_match_all('![-+/*].*?[\d.]+!',"+$s",$m);return array_reduce($m[0],g);}
قابل للقراءة:
function callback1($m) {return c($m[1]);}
function callback2($n,$m) {
$o=$m[0];
$m[0]=' ';
return $o=='+' ? $n+$m : ($o=='-' ? $n-$m : ($o=='*' ? $n*$m : $n/$m));
}
function c($s){
while ($s != ($t = preg_replace_callback('/\(([^()]*)\)/','callback1',$s))) $s=$t;
preg_match_all('![-+/*].*?[\d.]+!', "+$s", $m);
return array_reduce($m[0], 'callback2');
}
$str = ' 2.45/8.5 * -9.27 + ( 5 * 0.0023 ) ';
var_dump(c($str));
# float(-2.66044117647)
يجب أن تعمل مع أي إدخال صالح (بما في ذلك الأرقام السالبة والبطاقات البيضاء التعسفي)
SQL (SQL Server 2008)
عدد الشخصيات: 4202
وظيفة التباطؤ بالكامل:
WITH Input(id,str)AS(SELECT 1,'1 + 3 / -8'UNION ALL SELECT 2,'2*3*4*5+99'UNION ALL SELECT 3,'4 * (9 - 4)/ (2 * 6 - 2)+ 8'UNION ALL SELECT 4,'1 + ((123 * 3 - 69)/ 100)'UNION ALL SELECT 5,'2.45/8.5*9.27+(5*0.0023)'),Separators(i,ch,str_src,priority)AS(SELECT 1,'-',1,1UNION ALL SELECT 2,'+',1,1UNION ALL SELECT 3,'*',1,1UNION ALL SELECT 4,'/',1,1UNION ALL SELECT 5,'(',0,0UNION ALL SELECT 6,')',0,0),SeparatorsStrSrc(str,i)AS(SELECT CAST('['AS varchar(max)),0UNION ALL SELECT str+ch,SSS.i+1FROM SeparatorsStrSrc SSS INNER JOIN Separators S ON SSS.i=S.i-1WHERE str_src<>0),SeparatorsStr(str)AS(SELECT str+']'FROM SeparatorsStrSrc WHERE i=(SELECT COUNT(*)FROM Separators WHERE str_src<>0)),ExprElementsSrc(id,i,tmp,ele,pre_ch,input_str)AS(SELECT id,1,CAST(LEFT(str,1)AS varchar(max)),CAST(''AS varchar(max)),CAST(' 'AS char(1)),SUBSTRING(str,2,LEN(str))FROM Input UNION ALL SELECT id,CASE ele WHEN''THEN i ELSE i+1 END,CAST(CASE WHEN LEFT(input_str,1)=' 'THEN''WHEN tmp='-'THEN CASE WHEN pre_ch LIKE(SELECT str FROM SeparatorsStr)THEN tmp+LEFT(input_str,1)ELSE LEFT(input_str,1)END WHEN LEFT(input_str,1)IN(SELECT ch FROM Separators)OR tmp IN(SELECT ch FROM Separators)THEN LEFT(input_str,1)ELSE tmp+LEFT(input_str,1)END AS varchar(max)),CAST(CASE WHEN LEFT(input_str,1)=' 'THEN tmp WHEN LEFT(input_str,1)='-'THEN CASE WHEN tmp IN(SELECT ch FROM Separators)THEN tmp ELSE''END WHEN LEFT(input_str,1)IN(SELECT ch FROM Separators)OR tmp IN(SELECT ch FROM Separators)THEN CASE WHEN tmp='-'AND pre_ch LIKE(SELECT str FROM SeparatorsStr)THEN''ELSE tmp END ELSE''END AS varchar(max)),CAST(LEFT(ele,1)AS char(1)),SUBSTRING(input_str,2,LEN(input_str))FROM ExprElementsSrc WHERE input_str<>''OR tmp<>''),ExprElements(id,i,ele)AS(SELECT id,i,ele FROM ExprElementsSrc WHERE ele<>''),Scanner(id,i,val)AS(SELECT id,i,CAST(ele AS varchar(max))FROM ExprElements WHERE ele<>''UNION ALL SELECT id,MAX(i)+1,NULL FROM ExprElements GROUP BY id),Operator(op,priority)AS(SELECT ch,priority FROM Separators WHERE priority<>0),Calc(id,c,i,pop_count,s0,s1,s2,stack,status)AS(SELECT Scanner.id,1,1,0,CAST(scanner.val AS varchar(max)),CAST(NULL AS varchar(max)),CAST(NULL AS varchar(max)),CAST(''AS varchar(max)),CAST('init'AS varchar(max))FROM Scanner WHERE Scanner.i=1UNION ALL SELECT Calc.id,Calc.c+1,Calc.i,3,NULL,NULL,NULL,CASE Calc.s1 WHEN'+'THEN CAST(CAST(Calc.s2 AS real)+CAST(Calc.s0 AS real)AS varchar(max))WHEN'-'THEN CAST(CAST(Calc.s2 AS real)-CAST(Calc.s0 AS real)AS varchar(max))WHEN'*'THEN CAST(CAST(Calc.s2 AS real)*CAST(Calc.s0 AS real)AS varchar(max))WHEN'/'THEN CAST(CAST(Calc.s2 AS real)/CAST(Calc.s0 AS real)AS varchar(max))ELSE NULL END+' '+stack,CAST('calc '+Calc.s1 AS varchar(max))FROM Calc INNER JOIN Scanner NextVal ON Calc.id=NextVal.id AND Calc.i+1=NextVal.i WHERE Calc.pop_count=0AND ISNUMERIC(Calc.s2)=1AND Calc.s1 IN(SELECT op FROM Operator)AND ISNUMERIC(Calc.s0)=1AND(SELECT priority FROM Operator WHERE op=Calc.s1)>=COALESCE((SELECT priority FROM Operator WHERE op=NextVal.val),0)UNION ALL SELECT Calc.id,Calc.c+1,Calc.i,3,NULL,NULL,NULL,s1+' '+stack,CAST('paren'AS varchar(max))FROM Calc WHERE pop_count=0AND s2='('AND ISNUMERIC(s1)=1AND s0=')'UNION ALL SELECT Calc.id,Calc.c+1,Calc.i,Calc.pop_count-1,s1,s2,CASE WHEN LEN(stack)>0THEN SUBSTRING(stack,1,CHARINDEX(' ',stack)-1)ELSE NULL END,CASE WHEN LEN(stack)>0THEN SUBSTRING(stack,CHARINDEX(' ',stack)+1,LEN(stack))ELSE''END,CAST('pop'AS varchar(max))FROM Calc WHERE Calc.pop_count>0UNION ALL SELECT Calc.id,Calc.c+1,Calc.i+1,Calc.pop_count,CAST(NextVal.val AS varchar(max)),s0,s1,coalesce(s2,'')+' '+stack,cast('read'as varchar(max))FROM Calc INNER JOIN Scanner NextVal ON Calc.id=NextVal.id AND Calc.i+1=NextVal.i WHERE NextVal.val IS NOT NULL AND Calc.pop_count=0AND((Calc.s0 IS NULL OR calc.s1 IS NULL OR calc.s2 IS NULL)OR NOT(ISNUMERIC(Calc.s2)=1AND Calc.s1 IN(SELECT op FROM Operator)AND ISNUMERIC(calc.s0)=1AND (SELECT priority FROM Operator WHERE op=Calc.s1)>=COALESCE((SELECT priority FROM Operator WHERE op=NextVal.val),0))AND NOT(s2='('AND ISNUMERIC(s1)=1AND s0=')')))SELECT Calc.id,Input.str,Calc.s0 AS result FROM Calc INNER JOIN Input ON Calc.id=Input.id WHERE Calc.c=(SELECT MAX(c)FROM Calc calc2 WHERE Calc.id=Calc2.id)ORDER BY id
وظيفة واضحة / شبه عبفا:
WITH
Input(id, str) AS (
SELECT 1, '1 + 3 / -8'
UNION ALL SELECT 2, '2*3*4*5+99'
UNION ALL SELECT 3, '4 * (9 - 4) / (2 * 6 - 2) + 8'
UNION ALL SELECT 4, '1 + ((123 * 3 - 69) / 100)'
UNION ALL SELECT 5, '2.45/8.5*9.27+(5*0.0023)'
)
, Separators(i, ch, str_src, priority) AS (
SELECT 1, '-', 1, 1
UNION ALL SELECT 2, '+', 1, 1
UNION ALL SELECT 3, '*', 1, 1
UNION ALL SELECT 4, '/', 1, 1
UNION ALL SELECT 5, '(', 0, 0
UNION ALL SELECT 6, ')', 0, 0
)
, SeparatorsStrSrc(str, i) AS (
SELECT CAST('[' AS varchar(max)), 0
UNION ALL
SELECT
str + ch
, SSS.i + 1
FROM
SeparatorsStrSrc SSS
INNER JOIN Separators S ON SSS.i = S.i - 1
WHERE
str_src <> 0
)
, SeparatorsStr(str) AS (
SELECT str + ']' FROM SeparatorsStrSrc
WHERE i = (SELECT COUNT(*) FROM Separators WHERE str_src <> 0)
)
, ExprElementsSrc(id, i, tmp, ele, pre_ch, input_str) AS (
SELECT
id
, 1
, CAST(LEFT(str, 1) AS varchar(max))
, CAST('' AS varchar(max))
, CAST(' ' AS char(1))
, SUBSTRING(str, 2, LEN(str))
FROM
Input
UNION ALL
SELECT
id
, CASE ele
WHEN '' THEN i
ELSE i + 1
END
, CAST(
CASE
WHEN LEFT(input_str, 1) = ' '
THEN ''
WHEN tmp = '-'
THEN CASE
WHEN pre_ch LIKE (SELECT str FROM SeparatorsStr)
THEN tmp + LEFT(input_str, 1)
ELSE LEFT(input_str, 1)
END
WHEN LEFT(input_str, 1) IN (SELECT ch FROM Separators)
OR
tmp IN (SELECT ch FROM Separators)
THEN LEFT(input_str, 1)
ELSE tmp + LEFT(input_str, 1)
END
AS varchar(max))
, CAST(
CASE
WHEN LEFT(input_str, 1) = ' '
THEN tmp
WHEN LEFT(input_str, 1) = '-'
THEN CASE
WHEN tmp IN (SELECT ch FROM Separators)
THEN tmp
ELSE ''
END
WHEN LEFT(input_str, 1) IN (SELECT ch FROM Separators)
OR
tmp IN (SELECT ch FROM Separators)
THEN CASE
WHEN tmp = '-' AND pre_ch LIKE (SELECT str FROM SeparatorsStr)
THEN ''
ELSE tmp
END
ELSE ''
END
AS varchar(max))
, CAST(LEFT(ele, 1) AS char(1))
, SUBSTRING(input_str, 2, LEN(input_str))
FROM
ExprElementsSrc
WHERE
input_str <> ''
OR
tmp <> ''
)
, ExprElements(id, i, ele) AS (
SELECT
id
, i
, ele
FROM
ExprElementsSrc
WHERE
ele <> ''
)
, Scanner(id, i, val) AS (
SELECT
id
, i
, CAST(ele AS varchar(max))
FROM
ExprElements
WHERE
ele <> ''
UNION ALL
SELECT
id
, MAX(i) + 1
, NULL
FROM
ExprElements
GROUP BY
id
)
, Operator(op, priority) AS (
SELECT
ch
, priority
FROM
Separators
WHERE
priority <> 0
)
, Calc(id, c, i, pop_count, s0, s1, s2, stack, status) AS (
SELECT
Scanner.id
, 1
, 1
, 0
, CAST(scanner.val AS varchar(max))
, CAST(NULL AS varchar(max))
, CAST(NULL AS varchar(max))
, CAST('' AS varchar(max))
, CAST('init' AS varchar(max))
FROM
Scanner
WHERE
Scanner.i = 1
UNION ALL
SELECT
Calc.id
, Calc.c + 1
, Calc.i
, 3
, NULL
, NULL
, NULL
, CASE Calc.s1
WHEN '+' THEN CAST(CAST(Calc.s2 AS real) + CAST(Calc.s0 AS real) AS varchar(max))
WHEN '-' THEN CAST(CAST(Calc.s2 AS real) - CAST(Calc.s0 AS real) AS varchar(max))
WHEN '*' THEN CAST(CAST(Calc.s2 AS real) * CAST(Calc.s0 AS real) AS varchar(max))
WHEN '/' THEN CAST(CAST(Calc.s2 AS real) / CAST(Calc.s0 AS real) AS varchar(max))
ELSE NULL
END
+ ' '
+ stack
, CAST('calc ' + Calc.s1 AS varchar(max))
FROM
Calc
INNER JOIN Scanner NextVal ON Calc.id = NextVal.id
AND Calc.i + 1 = NextVal.i
WHERE
Calc.pop_count = 0
AND ISNUMERIC(Calc.s2) = 1
AND Calc.s1 IN (SELECT op FROM Operator)
AND ISNUMERIC(Calc.s0) = 1
AND (SELECT priority FROM Operator WHERE op = Calc.s1)
>= COALESCE((SELECT priority FROM Operator WHERE op = NextVal.val), 0)
UNION ALL
SELECT
Calc.id
, Calc.c + 1
, Calc.i
, 3
, NULL
, NULL
, NULL
, s1 + ' ' + stack
, CAST('paren' AS varchar(max))
FROM
Calc
WHERE
pop_count = 0
AND s2 = '('
AND ISNUMERIC(s1) = 1
AND s0 = ')'
UNION ALL
SELECT
Calc.id
, Calc.c + 1
, Calc.i
, Calc.pop_count - 1
, s1
, s2
, CASE
WHEN LEN(stack) > 0
THEN SUBSTRING(stack, 1, CHARINDEX(' ', stack) - 1)
ELSE NULL
END
, CASE
WHEN LEN(stack) > 0
THEN SUBSTRING(stack, CHARINDEX(' ', stack) + 1, LEN(stack))
ELSE ''
END
, CAST('pop' AS varchar(max))
FROM
Calc
WHERE
Calc.pop_count > 0
UNION ALL
SELECT
Calc.id
, Calc.c + 1
, Calc.i + 1
, Calc.pop_count
, CAST(NextVal.val AS varchar(max))
, s0
, s1
, coalesce(s2, '') + ' ' + stack
, cast('read' as varchar(max))
FROM
Calc
INNER JOIN Scanner NextVal ON Calc.id = NextVal.id
AND Calc.i + 1 = NextVal.i
WHERE
NextVal.val IS NOT NULL
AND Calc.pop_count = 0
AND (
(Calc.s0 IS NULL or calc.s1 is null or calc.s2 is null)
OR
NOT(
ISNUMERIC(Calc.s2) = 1
AND Calc.s1 IN (SELECT op FROM Operator)
AND ISNUMERIC(calc.s0) = 1
AND (SELECT priority FROM Operator WHERE op = Calc.s1)
>= COALESCE((SELECT priority FROM Operator WHERE op = NextVal.val), 0)
)
AND NOT(s2 = '(' AND ISNUMERIC(s1) = 1 AND s0 = ')')
)
)
SELECT
Calc.id
, Input.str
, Calc.s0 AS result
FROM
Calc
INNER JOIN Input ON Calc.id = Input.id
WHERE
Calc.c = (SELECT MAX(c) FROM Calc calc2
WHERE Calc.id = Calc2.id)
ORDER BY
id
انها ليست أقصر. لكنني أعتقد أنه مرن للغاية ل SQL. من السهل إضافة مشغلين جدد. من السهل تغيير أولوية المشغلين.
F#
عدد الشخصيات: 327
كان OP يبحث عن نسخة F #، ها هو. يمكن القيام به الكثير أجمل منذ أن أشغل رجع هنا لحفظ الشخصيات. هذا يعالج معظم الأشياء مثل -(1.0), 3 - -3 وحتى 0 - .5 إلخ.
let g s=
let c=ref[for x in System.Text.RegularExpressions.Regex.Matches(s,"[0-9.]+|[^\s]")->x.Value]
let rec e v=if (!c).IsEmpty then v else
let h=(!c).Head
c:=(!c).Tail
match h with|"("->e(e 0.0)|")"->v|"+"->e(v+(e 0.0))|"-"->e(v-(e 0.0))|"/"->e(v/(e 0.0))|"*"->e(v*(e 0.0))|x->float x
e(e 0.0)
ج
عدد الشخصيات: 208
بعد جيف مومستعليق، لقد أدركت أنني قد نسيت تماما هذه اللغة ... أنا لا خبير، لكن محاولتي الأولى ذهبت بشكل جيد إلى حد ما.
e=:>@{:@f@;:
f=:''&(4 :0)
'y x'=.x g y
while.($y)*-.')'={.>{.y do.'y x'=.(x,>(-.'/'={.>{.y){('%';y))g}.y end.y;x
)
g=:4 :0
z=.>{.y
if.z='('do.'y z'=.f}.y else.if.z='-'do.z=.'_',>{.}.y end.end.(}.y);":".x,z
)
إنه مزعج بعض الشيء، مع الخريطة x/y
و -z
إلى ي هو x%y
و _z
. وبعد دون ذلك، ربما تختفي 50٪ من هذا الرمز.
بيثون (دون استيراد أي شيء)
عدد الشخصيات: 222
لقد سرقت العديد من الحيل من إجابة ديف، لكنني تمكنت من حلق بعض الشخصيات.
def e(s,l=0,n=0,f='+'):
if s:l=[c for c in s+')'if' '!=c]
while f!=')':
p=l.pop;m=p(0)
if m=='(':m=e(0,l)
while l[0]not in'+-*/)':m+=p(0)
m=float(m);n={'+':n+m,'-':n-m,'*':n*m,'/':n/(m or 1)}[f];f=p(0)
return n
علق الإصدار:
def evaluate(stringexpr, listexpr=0, n=0, f_operation='+'):
# start out as taking 0 + the expression... (or could use 1 * ;)
# We'll prefer to keep the expression as a list of characters,
# so we can use .pop(0) to eat up the expression as we go.
if stringexpr:
listexpr = [c for c in stringexpr+')' if c!=' ']
# use ')' as sentinel to return the answer
while f_operation != ')':
m_next = listexpr.pop(0)
if m_next == '(':
# lists are passed by reference, so this call will eat the (parexp)
m_next = evaluate(None, listexpr)
else:
# rebuild any upcoming numeric chars into a string
while listexpr[0] not in '+-*/)':
m_next += listexpr.pop(0)
# Update n as the current answer. But never divide by 0.
m = float(m_next)
n = {'+':n+m, '-':n-m, '*':n*m, '/':n/(m or 1)}[f_operation]
# prepare the next operation (known to be one of '+-*/)')
f_operation = listexpr.pop(0)
return n
ج #
عدد الشخصيات: 403
إذن إليك حلاي ... ما زلت في انتظار شخص ما لنشر واحد في C # الذي يمكنه التغلب عليه. (كان مارك جرافيل قريبا، وقد يكون ذلك أفضل بعد مني بعد بعض العبث.)
وظيفة التباطؤ بالكامل:
float e(string x){float v=0;if(float.TryParse(x,out v))return v;x+=';';int t=0;
char o,s='?',p='+';float n=0;int l=0;for(int i=0;i<x.Length;i++){o=s;if(
x[i]!=' '){s=x[i];if(char.IsDigit(x[i])|s=='.'|(s=='-'&o!='1'))s='1';if(s==')')
l--;if(s!=o&l==0){if(o=='1'|o==')'){n=e(x.Substring(t,i-t));if(p=='+')v+=n;
if(p=='-')v-=n;if(p=='*')v*=n;if(p=='/')v/=n;p=x[i];}t=i;if(s=='(')t++;}
if(s=='(')l++;}}return v;}
وظيفة شبه Obfuscated:
public static float Eval(string expr)
{
float val = 0;
if (float.TryParse(expr, out val))
return val;
expr += ';';
int tokenStart = 0;
char oldState, state = '?', op = '+';
float num = 0;
int level = 0;
for (int i = 0; i < expr.Length; i++)
{
oldState = state;
if (expr[i] != ' ')
{
state = expr[i];
if (char.IsDigit(expr[i]) || state == '.' ||
(state == '-' && oldState != '1'))
state = '1';
if (state == ')')
level--;
if (state != oldState && level == 0)
{
if (oldState == '1' || oldState == ')')
{
num = Eval(expr.Substring(tokenStart, i - tokenStart));
if (op == '+') val += num;
if (op == '-') val -= num;
if (op == '*') val *= num;
if (op == '/') val /= num;
op = expr[i];
}
tokenStart = i;
if (state == '(')
tokenStart++;
}
if (state == '(')
level++;
}
}
return val;
}
لا شيء ذكي للغاية يحدث هنا، يبدو أن Woul. ومع ذلك، فإن الوظيفة لديها ميزة كونها إعادة الدخول (أي آمنة للخيط).
أنا أيضا سعداء بشكل معقول بعدد الأحرف، بالنظر إلى أنه مكتوب في C # (صالح 1.0، 2.0، و 3.0 وأعتقد).
هنا يأتي آخر واحد:
SHELT SCRIPT (باستخدام SED + AWK)
عدد الشخصيات: 295
تباطؤ:
e(){ a="$1";while echo "$a"|grep -q \(;do eval "`echo "$a"|sed 's/\(.*\)(\([^()]*\))\(.*\)/a="\1\`e \"\2\"\`\3"/'`";done; echo "$a"|sed 's/\([-+*/]\) *\(-\?\) */ \1 \2/g'|awk '{t=$1;for(i=2;i<NF;i+=2){j=$(i+1);if($i=="+") t+=j; else if($i=="-") t-=j; else if($i=="*") t*=j; else t/=j}print t}';}
قابل للقراءة
e () {
a="$1"
# Recursively process bracket-expressions
while echo "$a"|grep -q \(; do
eval "`echo "$a"|
sed 's/\(.*\)(\([^()]*\))\(.*\)/a="\1\`e \"\2\"\`\3"/'`"
done
# Compute expression without brackets
echo "$a"|
sed 's/\([-+*/]\) *\(-\?\) */ \1 \2/g'|
awk '{
t=$1;
for(i=2;i<NF;i+=2){
j=$(i+1);
if($i=="+") t+=j;
else if($i=="-") t-=j;
else if($i=="*") t*=j;
else t/=j
}
print t
}'
}
اختبار:
str=' 2.45 / 8.5 * 9.27 + ( 5 * 0.0023 ) '
echo "$str"|bc -l
e "$str"
نتيجة:
2.68344117647058823526
2.68344
matlab (v7.8.0)
عدد الشخصيات: 239
وظيفة obfcated:
function [v,s]=m(s),r=1;while s,s=regexp(s,'( ?)(?(1)-?)[\.\d]+|\S','match');c=s{end};s=[s{1:end-1}];if any(c>47),v=str2num(c);elseif c>41,[l,s]=m(s);v=[l/v l*v l+v l-v];v=v(c=='/*+-');if r,break;end;r=1;elseif c<41,break;end;r=r&c~=41;end
واضح (إيه) وظيفة:
function [value,str] = math(str)
returnNow = 1;
while str,
str = regexp(str,'( ?)(?(1)-?)[\.\d]+|\S','match');
current = str{end};
str = [str{1:end-1}];
if any(current > 47),
value = str2num(current);
elseif current > 41,
[leftValue,str] = math(str);
value = [leftValue/value leftValue*value ...
leftValue+value leftValue-value];
value = value(current == '/*+-');
if returnNow,
break;
end;
returnNow = 1;
elseif current < 41,
break;
end;
returnNow = returnNow & (c ~= 41);
end
اختبار:
>> [math('1 + 3 / -8'); ...
math('2*3*4*5+99'); ...
math('4 * (9 - 4) / (2 * 6 - 2) + 8'); ...
math('1 + ((123 * 3 - 69) / 100)'); ...
math('2.45/8.5*9.27+(5*0.0023)')]
ans =
-0.5000
219.0000
10.0000
4.0000
2.6834
Synopsis: مزيج من التعبيرات العادية والعودية. إلى حد كبير أفضل ما كنت قادرا على القيام به حتى الآن، دون الغش واستخدام eval.
روبي
عدد الشخصيات: 170
تباطؤ:
def s(x)
while x.sub!(/\(([^\(\)]*?)\)/){s($1)}
x.gsub!('--','')
end
while x.sub!(/(-?[\d.]+)[ ]*([+\-*\/])[ ]*(-?[\d.]+)/){$1.to_f.send($2,$3.to_f)}
end
x.strip.to_f
end
قابل للقراءة:
def s(x)
while x.sub!(/\(([^\(\)]*?)\)/){s($1)}
x.gsub!('--','')
end
while x.sub!(/(-?[\d.]+)[ ]*([+\-*\/])[ ]*(-?[\d.]+)/){$1.to_f.send($2,$3.to_f)}
end
x.strip.to_f
end
[
['1 + 3 / -8', -0.5],
['2*3*4*5+99', 219],
['4 * (9 - 4) / (2 * 6 - 2) + 8', 10],
['1 + ((123 * 3 - 69) / 100)', 4],
['2.45/8.5*9.27+(5*0.0023)',2.68344117647059],
['(3+7) - (5+2)', 3]
].each do |pair|
a,b = s(String.new(pair[0])),pair[1]
print pair[0].ljust(25), ' = ', b, ' (', a==b, ')'
puts
end
لا يوجد أي تطهير حقيقي لهذا واحد، والذي قررت نشره جديدا لأنه يختلف بعنف عن الأول. كان يجب أن رأيته من البداية. العملية هي عملية بسيطة للغاية للقضاء: ابحث عن وحل أعلى زوج من الأقواس (الأكثر تداولا) في عدد حتى لا يتم العثور على المزيد، ثم حل جميع الأرقام والعمليات الموجودة في النتيجة. وعلى الرغم من حل العبارات الفرعية التي أجريتها قطاع شرطات مزدوجة (float.to_f لا يعرف ماذا تفعل معهم).
لذلك، فإنه يدعم الأرقام الإيجابية والسلبية (+3 و 3 و / -3) ونفي التعبيرات الفرعية داخل الأقواس فقط بترتيب المعالجة. التنفيذ الأقصر الوحيد هو PERL (W / O EVER).
يحرر: ما زلت أطارد بيرل، لكن هذا هو ثاني أصغر إجابة الآن. تقلصت مع التغييرات في Regex الثانية ومن خلال تغيير علاج السلسلة لتكون مدمرة (يحل محل السلسلة القديمة). هذا القضاء على الحاجة إلى تكرار السلسلة، والتي اكتشفت أنها مجرد مؤشر جديد على السلسلة. وإعادة تسمية الوظيفة ل س من يحل حفظ بعض الأحرف.
بيثون مع تعبيرات منتظمة
عدد الشخصيات: 283
وظيفة التباطؤ بالكامل:
import re
from operator import*
def c(e):
O=dict(zip("+-/*()",(add,sub,truediv,mul)))
a=[add,0];s=a
for v,o in re.findall("(-?[.\d]+)|([+-/*()])",e):
if v:s=[float(v)]+s
elif o=="(":s=a+s
elif o!=")":s=[O[o]]+s
if v or o==")":s[:3]=[s[1](s[2],s[0])]
return s[0]
لا يطيع:
import re
from operator import *
def compute(s):
operators = dict(zip("+-/*()", (add, sub, truediv, mul)))
stack = [add, 0]
for val, op in re.findall("(-?[.\d]+)|([+-/*()])", s):
if val:
stack = [float(val)] + stack
elif op == "(":
stack = [add, 0] + stack
elif op != ")":
stack = [operators[op]] + stack
if val or op == ")":
stack[:3] = [stack[1](stack[2], stack[0])]
return stack[0]
أردت أن أرى ما إذا كنت قد تغلبت على حلول الثعبان الأخرى باستخدام تعبيرات منتظمة.
لا يمكن.
يعبر التعبير العادي الذي أستخدمه إنشاء قائمة بالأزواج (VAL، OP) حيث يكون عنصر واحد فقط في كل زوج صالح. إن بقية الرمز هو محلل مكدس قياسي إلى حد ما مع خدعة أنيقة لاستبدال أعلى 3 خلايا في المكدس نتيجة الحساب باستخدام بناء جملة تعيين قائمة Python. جعل هذا العمل بأرقام سلبية مطلوبة شخصين إضافيين فقط (-؟ في Regex).
بيثون
عدد الشخصيات: 382
حل ثعبان آخر، باستخدام استبدال التعبير العادي. يتم تشغيل كل تشغيل من خلال حلقة أبسط تعبيرات محسوبة ويتم وضع النتائج في السلسلة.
هذا هو الكود غير المفترض، إلا إذا كنت تفكر في التعبيرات العادية التي يجب تعبيرها.
import re
from operator import *
operators = dict(zip("+-/*", (add, sub, truediv, mul)))
def compute(s):
def repl(m):
v1, op, v2 = m.groups()
return str(operators[op](float(v1), float(v2)))
while not re.match("^\d+\.\d+$", s):
s = re.sub("([.\d]+)\s*([+-/*])\s*([.\d]+)", repl, s)
s = re.sub("\(([.\d]+)\)", r"\1", s)
return s
كان له هذه الفكرة تماما كما كنت أتحول ولا يمكنك السماح لها بالرحيل حتى كتبته وجعلها تعمل.
ج #
عدد الشخصيات: 396 (محدث)
(لكنه فشل في الاختبار الذي أضفته مع "/ -8"، وأنا لا أميل لإصلاحها ...
static float Eval(string s){int i,j;s=s.Trim();while((i=s.IndexOf(')'))>=0){j=s.LastIndexOf('(',i,i);s=s.Substring(0,j++)+Eval(s.Substring(j,i-j))+s.Substring(i+1);}if((i=s.LastIndexOfAny("+-*/".ToCharArray()))<0) return float.Parse(s);var r=float.Parse(s.Substring(i+1));var l=i>0?Eval(s.Substring(0,i)):(float?)null;return s[i]=='+'?(l??0)+r:(s[i]=='-'?(l??0)-r:(s[i]=='/'?(l??1)/r:(l??1)*r));}
من:
static float Eval(string s)
{
int i, j;
s = s.Trim();
while ((i = s.IndexOf(')')) >= 0)
{
j = s.LastIndexOf('(', i, i);
s = s.Substring(0, j++) + Eval(s.Substring(j, i - j)) + s.Substring(i + 1);
}
if ((i = s.LastIndexOfAny("+-*/".ToCharArray())) < 0) return float.Parse(s);
var r = float.Parse(s.Substring(i + 1));
var l = i > 0 ? Eval(s.Substring(0, i)) : (float?)null;
return s[i] == '+'
? (l ?? 0) + r
: (s[i] == '-'
? (l ?? 0) - r
: (s[i] == '/'
? (l ?? 1) / r
: (l ?? 1) * r));
}
بيثون
عدد الشخصيات: 235
وظيفة التباطؤ بالكامل:
def g(a):
i=len(a)
while i:
try:m=g(a[i+1:]);n=g(a[:i]);a=str({'+':n+m,'-':n-m,'*':n*m,'/':n/(m or 1)}[a[i]])
except:i-=1;j=a.rfind('(')+1
if j:k=a.find(')',j);a=a[:j-1]+str(g(a[j:k]))+a[k+1:]
return float(a.replace('--',''))
نصف عبث:
def g(a):
i=len(a);
# do the math
while i:
try:
# recursively evaluate left and right
m=g(a[i+1:])
n=g(a[:i])
# try to do the math assuming that a[i] is an operator
a=str({'+':n+m,'-':n-m,'*':n*m,'/':n/(m or 1)}[a[i]])
except:
# failure -> next try
i-=1
j=a.rfind('(')+1
# replace brackets in parallel (this part is executed first)
if j:
k=a.find(')',j)
a=a[:j-1]+str(g(a[j:k]))+a[k+1:]
return float(a.replace('--',''))
FWIW، حل ثعبان N + 1. في إساءة استخدام صارخ للمحاولة، إلا أنني أستخدم نهج تجريبي وخطأ. يجب أن تتعامل مع جميع الحالات بشكل صحيح بما في ذلك الأشياء مثل -(8)
, --8
و g('-(1 - 3)')
. وبعد إنه إعادة الدخول. دون دعم ل --
الحالة التي لا تدعم العديد من التطبيقات، وهي في 217 حرفا (انظر المراجعة السابقة).
شكرا على ساعة مثيرة للاهتمام يوم الأحد و 30 دقيقة أخرى يوم الاثنين. بفضل krubo. لبلده لطيف.
روبي
عدد الشخصيات: 217 179
هذا هو أقصر حل روبي يصل الآن (واحد بشكل كبير على أساس RegExP، مقابل إجابات غير صحيحة عندما تحتوي السلسلة على عدد قليل من مجموعات الأقواس) -- لم يعد صحيحا. الحلول القائمة على Regex والاستبدال أقصر. يعتمد هذا على كومة من المتراكم ويوزع التعبير الكامل من اليسار إلى اليمين. إنه إعادة الدخول، ولا يعدل سلسلة الإدخال. يمكن اتهامه بتقسيم قواعد عدم استخدام eval
, ، كما يستدعي Float
أساليب مع أسماء متطابقة كأنسان الإسلياف الرياضي (+، -، /، *).
رمز Obfuscated (النسخة القديمة، المعدل أدناه):
def f(p);a,o=[0],['+']
p.sub(/-/,'+-').scan(/(?:(-?\d+(?:\.\d+)?)|(.))\s*/).each{|n|
q,w=n;case w;when'(';a<<0;o<<'+';when')';q=a.pop;else;o<<w
end if q.nil?;a[-1]=a[-1].method(o.pop).call(q.to_f) if !q.nil?};a[0];end
رمز أكثر تباطؤ:
def f(p);a,o=[0],[:+]
p.scan(/(?:(-?\d+(?:\.\d+)?)|(.))\s*/).each{|n|q,w=n;case w
when'(';a<<0;o<<:+;when')';q=a.pop;else;o<<w;end if !q
a<<a.pop.send(o.pop,q.to_f)if q};a[0];end
رمز نظيف:
def f(p)
accumulators, operands = [0], ['+']
p.gsub(/-/,'+-').scan(/(?:(-?\d+(?:\.\d+)?)|(.))\s*/).each do |n|
number, operand = n
case operand
when '('
accumulators << 0
operands << '+'
when ')'
number = accumulators.pop
operands.pop
else
operands[-1] = operand
end if number.nil?
accumulators[-1] = accumulators.last.method(operands[-1]).call(number.to_f) unless number.nil?
end
accumulators.first
end
روبي 1.8.7.
عدد الشخصيات: 620
هل تحاول أن تأخذ الأمر سهلا في تنفيذي، إنها المرة الأولى التي كتب فيها محلل تعبير في حياتي! أنا أضمن أنه ليس هو الأفضل.
تباطؤ:
def solve_expression(e)
t,r,s,c,n=e.chars.to_a,[],'','',''
while(c=t.shift)
n=t[0]
if (s+c).match(/^(-?)[.\d]+$/) || (!n.nil? && n.match(/\d/) && c=='-')
s+=c
elsif (c=='-' && n=='(') || c=='('
m,o,x=c=='-',1,''
while(c=t.shift)
o+=1 if c=='('
o-=1 if c==')'
x+=c unless c==')' && o==0
break if o==0
end
r.push(m ? -solve_expression(x) : solve_expression(x))
s=''
elsif c.match(/[+\-\/*]/)
r.push(c) and s=''
else
r.push(s) if !s.empty?
s=''
end
end
r.push(s) unless s.empty?
i=1
a=r[0].to_f
while i<r.count
b,c=r[i..i+1]
c=c.to_f
case b
when '+': a=a+c
when '-': a=a-c
when '*': a=a*c
when '/': a=a/c
end
i+=2
end
a
end
قابل للقراءة:
def solve_expression(expr)
chars = expr.chars.to_a # characters of the expression
parts = [] # resulting parts
s,c,n = '','','' # current string, character, next character
while(c = chars.shift)
n = chars[0]
if (s + c).match(/^(-?)[.\d]+$/) || (!n.nil? && n.match(/\d/) && c == '-') # only concatenate when it is part of a valid number
s += c
elsif (c == '-' && n == '(') || c == '(' # begin a sub-expression
negate = c == '-'
open = 1
subExpr = ''
while(c = chars.shift)
open += 1 if c == '('
open -= 1 if c == ')'
# if the number of open parenthesis equals 0, we've run to the end of the
# expression. Make a new expression with the new string, and add it to the
# stack.
subExpr += c unless c == ')' && open == 0
break if open == 0
end
parts.push(negate ? -solve_expression(subExpr) : solve_expression(subExpr))
s = ''
elsif c.match(/[+\-\/*]/)
parts.push(c) and s = ''
else
parts.push(s) if !s.empty?
s = ''
end
end
parts.push(s) unless s.empty? # expression exits 1 character too soon.
# now for some solutions!
i = 1
a = parts[0].to_f # left-most value is will become the result
while i < parts.count
b,c = parts[i..i+1]
c = c.to_f
case b
when '+': a = a + c
when '-': a = a - c
when '*': a = a * c
when '/': a = a / c
end
i += 2
end
a
end
روبي 1.9.
(بسبب Regex)
عدد الشخصيات: 296
def d(s)
while m = s.match(/((?<pg>\((?:\\[()]|[^()]|\g<pg>)*\)))/)
s.sub!(m[:pg], d(m[:pg][1,m[:pg].size-2]))
end
while m = s.match(/(-?\d+(\.\d+)?)\s*([*+\-\/])\s*(-?\d+(\.\d+)?)/)
r=m[1].to_f.send(m[3],m[4].to_f) if %w{+ - * /}.include?m[3]
s.sub!(m[0], r.to_s)
end
s
end
تحرير: يشمل تحسين مارتن.
snobol4.
عدد الشخصيات: 232
a = pos(0) | '('
n = span('0123456789.')
j = '!+;!-;!*;!/; output = e'
d j '!' len(1) . y = " e a . q n . l '" y "' n . r = q (l " y " r) :s(p)" :s(d)
k = code(j)
e = input
s e ' ' = :s(s)
p e ('(' n . i ')') = i :s(p)f<k>
end
هذا هو شبه الغش. ويستخدم ذلك code()
(متغير التقييم) لإزالة ضغط نفسه، ولكن ليس لتقييم تعبير الإدخال.
نسخة إزالة code
:
prefix = pos(0) | '('
num = span('0123456789.')
expr = input
spaces expr ' ' = '' :s(spaces)
paren expr ('(' num . x ')') = x :s(paren)
add expr (prefix . pfx) (num . l) '+' (num . r) = pfx (l + r) :s(paren)
sub expr (prefix . pfx) (num . l) '-' (num . r) = pfx (l - r) :s(paren)
mul expr (prefix . pfx) (num . l) '*' (num . r) = pfx (l * r) :s(paren)
div expr (prefix . pfx) (num . l) '/' (num . r) = pfx (l / r) :s(paren)
output = expr
end
إستراتيجية:
- أولا، قم بإزالة جميع المسافات (
spaces
) - كلما أمكن ذلك، قم بإزالة الأقواس المحيطة بالرقم (
paren
) - خلاف ذلك، ابحث عن تعبير بسيط ينطوي على رقمين مسبقا مسبقا
'('
أو في بداية السلسلة - إذا لم تنطبق أي من القواعد المذكورة أعلاه، يتم تقييم التعبير بالكامل. الآن إذا تم تشكيل المدخلات بشكل جيد، يجب أن نترك مع عدد.
مثال:
1 + (2 * 3) + 4
1+(2*3)+4
[spaces
]1+(6)+4
[mul
]1+6+4
[paren
]7+4
[add
]11
[add
]
ج #
عدد الشخصيات: 355
أخذت إجابة نولدمورين وتعديلها، لذلك أعط Noldorin 99٪ من الائتمان لهذا. أفضل ما يمكنني فعله مع الخوارزمية كان يستخدم كان 408 حرفا. يرى إجابة نولدمورين للحصول على إصدار رمز أوضح.
التغييرات التي تم إجراؤها:
تغيير مقارنات سحر للمقارنة مع الأرقام.
إزالة بعض التصريحات الافتراضية ومجتمعة نفس النوع من الإعلانات.
أعد عمل بعض البيانات إذا.
float q(string x){float v,n;if(!float.TryParse(x,out v)){x+=';';int t=0,l=0,i=0;char o,s='?',p='+';for(;i<x.Length;i++){o=s;if(x[i]!=32){s=x[i];if(char.IsDigit(x[i])|s==46|(s==45&o!=49))s='1';if(s==41)l--;if(s!=o&l==0){if(o==49|o==41){n=q(x.Substring(t,i-t));v=p==43?v+n:p==45?v-n:p==42?v*n:p==47?v/n:v;p=x[i];}t=i;if(s==40)t++;}if(s==40)l++;}}}return v;}
تحرير: طرقه إلى أسفل بعض، من 361 إلى 355، عن طريق إزالة إحدى بيانات الإرجاع.