Giải một biểu thức toán học từ các mặt xen kẽ


9

Tạo một chương trình giải một biểu thức toán học bằng cách sử dụng các phần tử từ các cạnh xen kẽ của biểu thức. Cách thực hiện là, thay vì đọc từ trái sang phải, bạn đọc ký tự đầu tiên, sau đó đến cuối cùng, sau đó là thứ hai để cuối cùng, v.v. Điều này sẽ cung cấp cho bạn một biểu thức mới mà bạn phải đánh giá và xuất ra.

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

Thí dụ:

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

Nếu biểu thức không «hoạt động», 1phải chèn vào các vị trí cần thiết để làm cho biểu thức hoạt động.

Một vài ví dụ có thể sẽ minh họa nó tốt hơn:

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

Các toán tử phải được hỗ trợ là + - * /. Sẽ không có dấu ngoặc đơn. Các quy tắc toán học thông thường và "cú pháp" được sử dụng, vì vậy, ví dụ **không có nghĩa là lũy thừa. a++++1tương đương với a+1(tức là kiểu MATLAB, không phải C ++).

Trong trường hợp có nghi ngờ, một số hoạt động hợp lệ là:

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

Trong khi tất cả những điều sau đây không hợp lệ. Nó cho thấy những gì họ nên được thay thế bằng:

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

Quy tắc:

  • Mã có thể là một chức năng hoặc một chương trình đầy đủ
  • Đầu vào có thể là STDIN hoặc đối số chức năng
  • Đầu vào phải là một biểu thức toán học hợp lệ, không có dấu ngoặc kép ''hoặc"" .
  • Đầu ra phải là câu trả lời cho biểu thức mới, dưới dạng một số nguyên, thập phân hoặc một phần được đơn giản hóa.
  • Ít nhất ba chữ số sau dấu thập phân phải được hỗ trợ. Vì vậy 1/3 = 0.333, không 0.33. 0.333333333được chấp nhận.
  • ans = ... được chấp nhận.
  • Dòng mới và dấu vết hàng đầu và không gian được chấp nhận.
  • Đầu vào sẽ chỉ là số nguyên
  • Chia cho số 0 có thể dẫn đến lỗi, NaN, Inf, v.v. Xuất ra một số không được chấp nhận.

Như mọi khi, mã ngắn nhất trong byte thắng. Một người chiến thắng sẽ được chọn một tuần kể từ ngày thử thách được đăng. Câu trả lời được đăng sau đó vẫn có thể giành chiến thắng nếu nó ngắn hơn nhà lãnh đạo hiện tại.


Có độ dài tối đa trên chuỗi đầu vào hoặc số lượng toán tử / số nguyên đầu vào không? Ngoài ra, tôi có phải hỗ trợ toán học không 2^64, và nó có bị lỗi hay không nếu bạn đi qua?
con mèo

"đầu ra phải là câu trả lời [...] phần đơn giản hóa ..." vì vậy tôi có thể trả về 0/0nếu biểu thức thay đổi thành phép chia số nguyên hoặc modulo bằng 0 không?
con mèo

2
Nếu câu trả lời chia cho 0, thì đó x/0là một đầu ra hợp lệ. Miễn là nó không đưa ra một câu trả lời không chính xác, nó ổn. Lỗi và "Không phải là số" là theo định nghĩa chính xác và vô cùng là "đủ chính xác",
Stewie Griffin

Chỉ cần chắc chắn - eval có thể được sử dụng, phải không?
orlp

Vâng, eval là ok.
Stewie Griffin

Câu trả lời:


3

Perl, 108 100 byte

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

Mã này là 96 byte, cộng với 4 cho đối số dòng lệnh -pF//, trong đó

  • -pchèn while (<>) { .. } continue { print }
  • -F//tách đầu vào và đặt nó vào @F.

Lưu ý rằng đầu vào không nên có một dòng mới, vì vậy hãy sử dụng /bin/echo -n 'formula' | perl ...

Ít chơi gôn hơn:

$_='';              # 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

Kiểm tra

Đặt phần trên vào một tệp được gọi 114.plvà tập lệnh kiểm tra bên dưới trong một tệp bên cạnh tệp đó:

%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;

Chạy nó đầu ra:

++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

Lưu ý rằng 1/0gây ra sự phân chia theo lỗi không: các evalđầu ra undef, được biểu thị bằng chuỗi rỗng.


Một vài trường hợp thử nghiệm nữa! Tôi sẽ sử dụng chúng
edc65

3

JavaScript ES6, 105 106

Chỉnh sửa Đã lưu 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)
}

Kiểm tra đoạn

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>


Tiết kiệm cho bạn một byte : p < '0' ? ( c=='/' | c<'+' || ' ' )+c : c ;.
Kenney
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.