แก้ปัญหาการแสดงออกทางคณิตศาสตร์จากการสลับด้าน


9

สร้างโปรแกรมที่สามารถแก้ปัญหาการแสดงออกทางคณิตศาสตร์โดยใช้องค์ประกอบจากการสลับด้านของการแสดงออก วิธีที่มันทำคือแทนที่จะอ่านจากซ้ายไปขวาคุณอ่านตัวอักษรแรกแล้วตัวสุดท้ายจากนั้นตัวที่สองจากนั้นตัวที่สองไปที่อื่นเป็นต้นสิ่งนี้จะให้นิพจน์ใหม่ที่คุณต้องประเมินและแสดงผล

a*b/c+d-e
135798642  <-- Order you read the expression in
ae*-bd/+c  <-- Order of operation. 

ตัวอย่าง:

1*3/2+4-5
15*-34/+2 = -255

หากการแสดงออกไม่ได้«ทำงาน» 1จะต้องแทรกในตำแหน่งที่จำเป็นเพื่อให้การทำงาน

ตัวอย่างบางส่วนอาจแสดงให้เห็นได้ดีขึ้น:

Input: 1+1+1+1+1
Result: 23     // Because 1+1+1+1+1 -> 11++11++1 -> 23

Input: 1+2-3+12-5
Result: -19    // Because 1+2-3+12-5 -> 15+-22-13+ -> 15+-22-13+1 -> -19
               //                                 |
               //                                 Not valid expression

Input: 2*2*2*2*2
Result: 968    // Because 2*2*2*2*2 -> 22**22**2 -> 22*1*22*1*2 -> 968
               //                        ||  ||
               //                        Not valid, 1 must be inserted

Input: 17/2
Output: 127    // Because 17/2 = 127/ -> 127/1 -> 127

+ - * /ผู้ประกอบการที่จะต้องได้รับการสนับสนุน จะไม่มีวงเล็บ มีการใช้กฎคณิตศาสตร์ปกติและ "ไวยากรณ์" ดังนั้นอินสแตนซ์**ไม่ได้หมายถึงการยกกำลัง a++++1เทียบเท่ากับa+1(เช่นรูปแบบ MATLAB ไม่ใช่ C ++)

ในกรณีที่มีข้อสงสัยการดำเนินการที่ถูกต้องคือ:

-a
+a
a++b
a+-b
a*-b
a*+b
a*++b
a/b
a/-b
a/+b
-a/--b

ในขณะที่ทั้งหมดต่อไปนี้ไม่ถูกต้อง มันแสดงให้เห็นสิ่งที่พวกเขาควรจะทดแทนด้วย:

a+      | a+1
a-      | a-1
a++++   | a++++1   (This is equivalent to a+1)
a*+++   | a*+++1   (This is equivalent to a*1)
a**b    | a*1*b
a*/b    | a*1/b
a/*b    | a/1*b
a*      | a*1
*a      | 1*a
***a    | 1*1*1*a

กฎ:

  • รหัสสามารถเป็นฟังก์ชั่นหรือโปรแกรมเต็มรูปแบบ
  • อินพุตสามารถเป็น STDIN หรืออาร์กิวเมนต์ของฟังก์ชัน
  • การป้อนข้อมูลจะต้องเป็นแสดงออกทางคณิตศาสตร์ที่ถูกต้องโดยไม่ใส่เครื่องหมายคำพูด''""หรือ
  • ผลลัพธ์ควรเป็นคำตอบของนิพจน์ใหม่ในรูปของจำนวนเต็มทศนิยมหรือเศษส่วนแบบง่าย
  • ต้องมีอย่างน้อยสามหลักหลังจุดทศนิยมต้องได้รับการสนับสนุน ดังนั้นไม่1/3 = 0.333 ได้รับการยอมรับ0.330.333333333
  • ans = ... ได้รับการยอมรับ
  • ขึ้นบรรทัดใหม่และเว้นช่องว่างนำหน้าและต่อท้าย
  • อินพุตจะเป็นจำนวนเต็มเท่านั้น
  • การหารด้วยศูนย์อาจทำให้เกิดข้อผิดพลาด NaN, Inf ฯลฯ ไม่อนุญาตให้ส่งออกตัวเลข

เช่นเคยรหัสสั้นที่สุดในไบต์ชนะ ผู้ชนะจะได้รับการคัดเลือกหนึ่งสัปดาห์จากวันที่มีการโพสต์ความท้าทาย คำตอบที่โพสต์ในภายหลังอาจยังคงชนะถ้ามันสั้นกว่าผู้นำปัจจุบัน


มีความยาวสูงสุดในสายป้อนข้อมูลหรือจำนวนของผู้ประกอบการ / จำนวนเต็ม? ฉันต้องสนับสนุนคณิตศาสตร์ด้วย2^64และควรผิดพลาดหรือไม่ถ้าคุณไป?
แมว

"ผลลัพธ์ควรเป็นคำตอบ [...] เศษส่วนอย่างง่าย ... " ดังนั้นฉันจะกลับมาได้0/0ไหมถ้านิพจน์วิวัฒนาการไปที่การหารจำนวนเต็มหรือโมดูโลตามศูนย์?
แมว

2
หากคำตอบให้การหารด้วยศูนย์แล้วx/0เป็นผลลัพธ์ที่ถูกต้อง ตราบใดที่มันไม่ส่งออกคำตอบที่ไม่ถูกต้องมันก็โอเค ข้อผิดพลาดและ "ไม่ใช่ตัวเลข" ถูกต้องตามคำจำกัดความและอินฟินิตี้คือ "ถูกต้องเพียงพอ"
Stewie Griffin

เพียงเพื่อให้แน่ใจว่าสามารถใช้ eval ได้ใช่ไหม
orlp

ใช่ eval ก็โอเค
Stewie Griffin

คำตอบ:


3

Perl, 108 100 ไบต์

$_="";while(@F){$_.=shift@F;$_.=pop@F}s@(\*|/)\1+@\1@g;s@^[*/]@1$&@;s@\D$@$&1@;s@\D@$&@g;$_=eval

รหัสคือ 96 ไบต์บวก 4 สำหรับอาร์กิวเมนต์บรรทัดคำสั่ง-pF//โดยที่

  • -pเม็ดมีดwhile (<>) { .. } continue { print }และ
  • -F//@Fแยกเข้าและทำให้มันอยู่ใน

โปรดทราบว่าอินพุตไม่ควรมีบรรทัดขึ้นบรรทัดใหม่ให้ใช้ /bin/echo -n 'formula' | perl ...

หักกอล์ฟ:

$_='';              # reset $_
while(@F) {         # reorder input
   $_.=shift @F;    # take first element off of @_
   $_.=pop @F       # idem for last; if @F is empty, undef is appended
}

s@(\*|/)\1+@\1@g;   # replace 2 or more '*' or '/' with just one: *1 and /1 = nop
s@^[*/]@1$&@;       # if expression starts with * or / prepend a 1
s@\D$@$&1@;         # if expression doesn't end with a number, append 1
s@\D@$& @g;         # eval doesn't like '++1': add spaces after operators
$_ = eval           # set $_ to 3v1l, so the `-p` will print the new value

การทดสอบ

ใส่ข้างต้นในไฟล์ที่เรียกว่า114.plและสคริปต์ทดสอบด้านล่างในไฟล์ถัดจากมัน:

%test = (
    '1+1+1+1+1' =>   23,
    '1*3/2+4-5' => -255,
    '1+2-3+12-5'=>  -19,
    '2*2*2*2*2' =>  968,
    '17/2'      =>  127,
    '--/-1-2-'  =>   -2,
    '**2*'      =>    2,
    '++1++'     =>    1,
    '/2/'       =>  0.5,
    '10/'       =>   '',
);

printf "%-20s -> %5s: %5s\n", $_, $test{$_}, `/bin/echo -n '$_' | perl -pF// 114.pl`
for keys %test;

กำลังรันเอาต์พุต:

++1++                ->     1:     1
**2*                 ->     2:     2
17/2                 ->   127:   127
10/                  ->      :
1+1+1+1+1            ->    23:    23
1*3/2+4-5            ->  -255:  -255
2*2*2*2*2            ->   968:   968
1+2-3+12-5           ->   -19:   -19
--/-1-2-             ->    -2:    -2
/2/                  ->   0.5:   0.5

โปรดทราบว่า1/0ทำให้เกิดการหารด้วยข้อผิดพลาดเป็นศูนย์: evalผลลัพธ์undefที่แสดงโดยสตริงว่าง


อีกสองสามกรณีทดสอบ! ฉันจะใช้มัน
edc65

3

JavaScript ES6, 105 106

แก้ไขที่บันทึกไว้ 1 byte thx @Kenney

t=>eval("for(t=[...t],p=o='';c=t.reverse().pop();p=c)o+=p<'0'?(c=='/'|c<'+'||' ')+c:c;eval(p<'0'?o+1:o)")

// Less golfed
t=>{
  for(t = [...t], p = o = '';
      c = t.reverse().pop();
      p = c)
    o += p<'0' 
     ? (c=='/' | c=='*' || ' ')+c  // '1' or ' '
     : c;
  return eval(p<'0' ? o+1 : o)
}

ตัวอย่างการทดสอบ

f=t=>eval("for(t=[...t],p=o='';c=t.reverse().pop();p=c)o+=p<'0'?(c=='/'|c<'+'||' ')+c:c;eval(p<'0'?o+1:o)")

console.log=x=>O.innerHTML+=x+'\n'

function test() { console.log(I.value + ' -> '+f(I.value)) }

;['1+1+1+1+1', '1*3/2+4-5', '1+2-3+12-5', '2*2*2*2*2',
  '17/2', '--/-1-2-', '**2*', '++1++', '/2/', '10/' ]
.forEach(t=>console.log(t+' -> '+f(t)))
Your test <input id=I><button onclick="test()">-></button>
<pre id=O></pre>


p < '0' ? ( c=='/' | c<'+' || ' ' )+c : c ;ที่บันทึกไว้คุณไบต์:
Kenney
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.