Thay thế toán học


13

Đôi khi nó rất hữu ích để chạy một bài toán với nhiều đầu vào. Mục tiêu của thử thách này là tạo ra một chương trình giúp giảm bớt nhiệm vụ này.

Biểu thức tạo số

Bạn phải hỗ trợ 3 loại biểu thức:

  • Trình tạo số đơn: Rất đơn giản, chỉ là một số bằng chữ
  • Trình tạo nhiều số: Một chút phức tạp hơn. Thees được bao quanh bởi dấu ngoặc vuông ( []). Các số được ,phân tách bằng dấu phẩy ( ) trong biểu thức. Ví dụ [-1,2,3.26].
  • Trình tạo phạm vi: Cái này được bao quanh bởi dấu ngoặc nhọn ( {}). Nó sẽ có 3 số cách nhau bởi một dấu phẩy. Định dạng của biểu thức này là {start,stop,step}. startvà đã stopbao gồm.

Quy tắc đánh giá

  • Bạn phải hỗ trợ thứ tự các hoạt động. ( https://en.wikipedia.org/wiki/Order_of_operations#DefDef )
  • Bạn không cần phải hỗ trợ dấu ngoặc đơn.
  • Bất kỳ số lượng không gian có thể xảy ra trong biểu thức.
  • Bạn phải hỗ trợ các số dấu phẩy động (bất kỳ độ chính xác nào mà ngôn ngữ của bạn mặc định là tốt).
  • Chia theo 0kết quả trong NaN(không phải là một số).

Chương trình của bạn phải hỗ trợ phép nhân ( *), phép chia ( /), phép cộng ( +) và phép trừ ( -).

Đầu ra

Mỗi dòng đầu ra là một trong những kết hợp của các máy phát. Định dạng là biểu thức (với các số thực được thay thế vào nó) theo sau là dấu bằng ( =) và kết quả đánh giá. Tất cả các kết hợp của các máy phát phải được đại diện trong đầu ra.

Ví dụ

( >>>biểu thị đầu vào)

>>>3 * [3,2]
3 * 3 = 9
3 * 2 = 6

>>>{1,2,3}
1 = 1 <-- this is because 1 + 3 > the end

>>>{0,2,1} + {0,1,1}
0 + 0 = 0
1 + 0 = 1
2 + 0 = 2
0 + 1 = 1
1 + 1 = 2
2 + 1 = 3

>>>6/[2,3]
6/2 = 3
6/3 = 2

>>>{1.5,2.5,0.5}
1.5 = 1.5
2 = 2
2.5 = 2.5

>>>3-{6,5,-1}
3-6 = -3
3-5 = -2

>>>5/{-1,1,1}
5/-1 = -5
5/0 = NaN
5/1 = 5

>>>4.4 / [1,2.2] + {0,2,1}
4.4 / 1 + 0 = 4.4
4.4 / 1 + 1 = 5.4
4.4 / 1 + 2 = 6.4
4.4 / 2.2 + 0 = 2
4.4 / 2.2 + 1 = 3
4.4 / 2.2 + 2 = 4

>>> [1,2] / 0 + 5
1 / 0 + 5 = NaN
2 / 0 + 5 = NaN

Chương trình cần phải ngắn để tôi có thể ghi nhớ và sử dụng nó ở bất cứ đâu.

Cảm ơn @PeterTaylor và @geokavel đã giúp tôi với bài đăng này trong hộp cát


Bạn phải hỗ trợ các số dấu phẩy động (bất kỳ độ chính xác nào mà ngôn ngữ của bạn mặc định là tốt). Nếu ngôn ngữ của tôi chỉ hỗ trợ số học số nguyên thì sao? Tôi có thể tuyên bố rằng tôi có độ chính xác vị trí thập phân không?
Chấn thương kỹ thuật số

Có thể trộn phạm vi đầu vào và nhiều số?
Maltysen

@DigitalTrauma Tôi không nghĩ về những ngôn ngữ đó .... Tôi sẽ nói không.
J Atkin

Ngoài ra, x/0kết quả là đánh giá ngay lập tức với NaN, hay tôi phải coi NaN là một giá trị?
Maltysen

@Maltysen Yep, tôi có nên đưa ra một ví dụ không?
J Atkin

Câu trả lời:


4

JavaScript (ES6), 213 211 byte

f=x=>(a=0,x=x.replace(/\[.+?]|{.+?}/,r=>([i,l,n]=a=r.slice(1,-1).split`,`,r[0]>"]"&&eval(`for(a=[];n>0?i<=+l:i>=+l;i-=-n)a.push(i)`),"x")),a?a.map(n=>f(x.replace("x",n))).join``:x+` = ${r=eval(x),r<1/0?r:NaN}
`)

Giải trình

Hàm đệ quy thực thi biểu thức nếu nó không chứa bất kỳ trình tạo nhiều số hoặc phạm vi hoặc nếu nó có chứa một trong các trình tạo này, hãy gọi chính nó bằng trình tạo được thay thế bằng mỗi số do nó tạo ra.

Chia theo 0JavaScript tạo ra Infinity, vì vậy Infinitycó thể chỉ cần thay thế bằng NaN.

Sử dụng phương pháp này, các bộ tạo đa năng được phân tích cú pháp từ trước ra trước thay vì từ trước ra sau như trong các trường hợp thử nghiệm. Điều này chỉ có nghĩa là thứ tự của các biểu thức đầu ra đôi khi khác nhau.

f=x=>(
  a=0,                                           // initialise a to false
  x=x.replace(/\[.+?]|{.+?}/,r=>(                // find the first multi-generator
    [i,l,n]=                                     // i = start, l = stop, n = step
      a=r.slice(1,-1).split`,`,                  // a = each number of generator
    r[0]>"]"&&                                   // if a range generator was found
      eval(`                                     // use eval to enable for loop here
        for(a=[];n>0?i<=+l:i>=+l;i-=-n)a.push(i) // add each number of the range to a
      `),
    "x"                                          // replace the generator with "x"
  )),
  a?                                             // if a multi-generator was found
    a.map(n=>                                    // for each number n in a
      f(x.replace("x",n))                        // call itself with n inserted
    )
    .join``                                      // combine the output of each result
  :x+` = ${r=eval(x),                            // evaluate the expression
    r<1/0?r:NaN}
`                                                // replace Infinity with NaN
)

Kiểm tra

Kiểm tra không sử dụng các bài tập phá hủy để tương thích trình duyệt.

f=x=>(a=0,x=x.replace(/\[.+?]|{.+?}/,r=>(a=r.slice(1,-1).split`,`,r[0]>"]"&&eval(`i=a[0],l=a[1],n=a[2];for(a=[];n>0?i<=+l:i>=+l;i-=-n)a.push(i)`),"x")),a?a.map(n=>f(x.replace("x",n))).join``:x+` = ${r=eval(x),r<1/0?r:NaN}
`)
<input type="text" id="input" value="4.4 / [1,2.2] + {0,2,1}" />
<button onclick="result.textContent=f(input.value)">Go</button>
<pre id="result"></pre>


Điều này thực sự rất gần với câu trả lời được hình dung của tôi.
J Atkin

4

Haskell, 474 362 byte

Hàm f lấy một chuỗi làm đầu vào và in kết quả

g '+'=(+);g '-'=(-);g '*'=(*);g '/'=(\a b->a*b/b/b)
p[]=[]
p(o:x:y)=[(flip(g o)$n,' ':o:' ':show n)|n<-v]:p r where
    [f,e,s]=z;(z,h)=reads('[':y)!!0;(w,m)=reads(x:y)!!0;(v,r)|x=='['=(z,h)|x=='{'=([f,f+s..e],h)|True=([w],m)
h '}'=']';h x=x
d(a,b)=putStrLn.drop 3$foldl(++)""b++" = "++show(foldl(flip($))0a)
f t=mapM_(d.unzip)$sequence$p(filter(/=' ')$'+':map h t)

kiểm tra:

main=do
    f "4.4 / [1,2.2] + {0,2,1}"
    putStrLn""
    f "[1,2] / 0 + 5"
    putStrLn""
    f "{0,2,1} + {0,1,1}"

đầu ra:

4.4 / 1.0 + 0.0 = 4.4
4.4 / 1.0 + 1.0 = 5.4
4.4 / 1.0 + 2.0 = 6.4
4.4 / 2.2 + 0.0 = 2.0
4.4 / 2.2 + 1.0 = 3.0
4.4 / 2.2 + 2.0 = 4.0

1.0 / 0.0 + 5.0 = NaN
2.0 / 0.0 + 5.0 = NaN

0.0 + 0.0 = 0.0
0.0 + 1.0 = 1.0
1.0 + 0.0 = 1.0
1.0 + 1.0 = 2.0
2.0 + 0.0 = 2.0
2.0 + 1.0 = 3.0

2

Python 3, 387 byte

def a(q,d=-1,f='',g=float,h=print):
 if any((c in q)for c in'[]{}'):
  for i,b in enumerate(q):
   if d!=-1:
    if b in'}]':
     e=f.split(",")
     if b=='}':
      r=g(e[0]);s=[]
      while r<=g(e[1]):s.append(str(r));r+=g(e[2])
      e[:]=s[:]
     [a(q[:d]+n+q[i+1:])for n in e];return
    f+=b
   if b in'[{':d=i
 else:
  h(q+" = ",end='')
  try:h(str(eval(q)))
  except:h("NaN")

Bạn có thể kiểm tra nó với đoạn mã sau:

tests=['3 * [3,2]', '{1,2,3}', '{0,2,1} + {0,1,1}',
       '6/[2,3]', '{1.5,2.5,0.5}', '3-{6,5,-1}',
       '5/{-1,1,1}', '4.4 / [1,2.2] + {0,2,1}',
       '[1,2] / 0 + 5']

for n in tests:
    print(n)
    a(n)
    print()

Đây là mã không được mã hóa:

def eval_statement(query):
    left_bracket_index = -1
    inside_bracket_content = ''
    if any((bracket in query) for bracket in '[]{}'):
        for i, character in enumerate(query):
            if left_bracket_index != -1:
                if character in '}]':
                    params = inside_bracket_content.split(",")
                    if character == '}':
                        value = float(params[0])
                        values = []
                        while value <= float(params[1]):
                            values.append(str(value))
                            value += float(params[2])
                        params[:] = values[:]
                    for param in params:
                        new_query = query[:left_bracket_index] + param + query[i + 1:]
                        eval_statement(new_query)
                    return
                inside_bracket_content += character
            if character in '[{':
                left_bracket_index = i
    else:
        print(query + " = ", end='')
        try:
            print(str(eval(query)))
        except:
            print("NaN")

Nó hoạt động bằng cách tìm bộ dấu ngoặc đầu tiên của bất kỳ loại nào, sau đó lặp qua tất cả các giá trị bên trong nó, bằng cách thay thế dấu ngoặc và nội dung của nó bằng giá trị và chạy phương thức theo cách đệ quy. Nó sử dụng evalmột lần không có dấu ngoặc trong dòng. Nó trả về NaNnếu có một ngoại lệ đang chạy eval.


(hơi muộn) Chào mừng bạn đến với Câu đố lập trình & Golf Code!
J Atkin

Tại sao bạn cần e[:]=s[:]? Sẽ không e[:]=slàm như vậy?
Cyoce

1

Java, 874 byte

void E(String s)throws Exception{int i=0;String t;List<String[]>z=new ArrayList<>();List<String>x=new ArrayList<>(),y=new ArrayList<>();for(String k:s.split(" "))t+=" "+(k.matches("[0-9]+")?"["+k+"]":k);for(String k:t.split(" "))s+=" "+(k.matches("\\{[^\\}]+\\}")?"["+R(k)+"]":k);for(String k:s.split(" "))t+=" "+(k.matches("\\[[^\\]]+\\]")?"$"+(i+=z.add(k.replaceAll("[\\[\\]]","").split(","))):k);x.add(t.substring(1));while (i-->0){y.clear();for(String e:x)for(String l:z.get(i))y.add(e.replace("$"+i,l));x.clear();x.addAll(y);}for(String e:x)System.out.println(e+"="+new javax.script.ScriptEngineManager().getEngineByName("JavaScript").eval(e).replace("Infinity","NaN"));}
String R(String t){String y="",[]s=t.replaceAll("[\\{\\}]","").split(",");int i=I(s[0]);y+="["+i;while ((i+=I(s[2]))<=I(s[1]))y+=","+i;y+="]";return y;}
int I(String t){return Integer.parseInt(t);}

Thử chi tiết tại đây

import java.util.*;
import java.lang.*;
import java.io.*;

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;

class Ideone
{
    // single : x -> [x]
    public static String expandSingle (String input)
    {
        String out = "";
        for (String str : input.split(" "))
        {
            out += " ";
            if(str.matches("[0-9]+"))
            {
                out += "["+str+"]";
            }
            else
            {
                out += str;
            }
        }
        return out.substring(1);
    }

    // range : {start,end,step} -> [x,..,y]
    public static String expandRange (String input)
    {
        String out = "";
        int a,b,c;
        int i=0;
        for (String str : input.split(" "))
        {
            out += " ";
            if(str.matches("\\{[0-9]+,[0-9]+,[0-9]+\\}"))
            {
                str = str.replaceAll("[\\{\\}]","");
                a = Integer.parseInt(str.split(",")[0]);
                b = Integer.parseInt(str.split(",")[1]);
                c = Integer.parseInt(str.split(",")[2]);

                out += "["+a;
                while ((a+=c) <= b) out += ","+a;
                out += "]";
            }
            else
            {
                out += str;
            }
        }
        return out.substring(1);
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        String input = "3 * [3,2] + {0,2,1}";
        System.out.println(" input = "+input);
        input = expandSingle(input);
        input = expandRange(input);
        System.out.println(" expand = "+input);
        evaluate(input);
    }

    public static void evaluate (String input) throws java.lang.Exception
    {
        int i = 0;
        String t = "";
        ArrayList<String[]> set = new ArrayList<String[]>();
        ArrayList<String> in = new ArrayList<String>();
        ArrayList<String> out = new ArrayList<String>();

        // map sets
        for (String str : input.split(" "))
        {
            t += " ";
            if(str.matches("\\[.+\\]"))
            {
                str = str.replaceAll("[\\[\\]]","");
                set.add(str.split(","));
                t+= "$"+i;
                i++;
            }
            else t+=str;
        }
        in.add(t.substring(1));

        // generate expressions
        while (i-->0)
        {
            out.clear();
            for (String exp : in)
            {
                for (String sub : set.get(i))
                {
                    out.add(exp.replace("$"+i,sub));
                }
            }
            in.clear();
            in.addAll(out);
        }

        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine engine = mgr.getEngineByName("JavaScript");

        // print expressions
        for (String exp : in)
        {
            System.out.println(" "+exp+" = "+engine.eval(exp).replace("Infinity","NaN"));
        }
    }
}

1

APL Dyalog , 164 byte

Câu trả lời này không tuân theo các yêu cầu được cập nhật và do đó không cạnh tranh:

{n←⊂'NaN'
R←{+\b,s/⍨⌊((2⊃⍵)-b←⊃⍵)÷s←⊃⌽⍵}
D←{0::n⋄⍺×÷⍵}
↑(∊¨(,⍎'[-+×D]'⎕R','⊢e),¨¨⊂('[-+×÷]'⎕S'\0'⊢⍵),⊂'='),¨,⍎e←'{' '}' '\[' ']' '÷' '[-+×]'⎕R'(R ' ')' '(' ')' '∘.D ' '∘.{0::n⋄⍺\0⍵}'⊢⍵}

Nó sử dụng biểu thức chính để thay đổi biểu thức đã cho thành APL tương ứng (và tất cả các toán tử được sửa đổi để thực hiện NaN) và để trích xuất các toán tử. Nó thay thế tất cả các toán tử bằng catenation và thực hiện biểu thức để có được các số đầu vào cuối cùng. Sau đó, nó kết hợp tất cả lại với nhau để có được đầu ra cuối cùng.

Giữ nguyên thứ tự đánh giá APL (nghiêm ngặt từ phải sang trái).

Xử lý dấu ngoặc đơn chính xác.

Các trường hợp thử nghiệm (có thêm dấu ngoặc đơn để buộc thứ tự thực hiện giống như toán học):

      f '3 × [3,2]'
3 × 3 = 9
3 × 2 = 6
      f '{1,2,3}'
1 = 1
      f '{0,2,1} + {0,1,1}'
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 2
2 + 0 = 2
2 + 1 = 3
      f '6÷[2,3]'
6 ÷ 2 = 3
6 ÷ 3 = 2
      f '{1.5,2.5,0.5}'
1.5 = 1.5
2   = 2  
2.5 = 2.5
      f '3-{6,5,¯1}'
3 - 6 = ¯3
3 - 5 = ¯2
      f '5÷{¯1,1,1}'
5 ÷ ¯1 =  ¯5 
5 ÷  0 = NaN 
5 ÷  1 =   5 
      f '(4.4 ÷ [1,2.2]) + {0,2,1}'
4.4 ÷ 1   + 0 = 4.4
4.4 ÷ 1   + 1 = 5.4
4.4 ÷ 1   + 2 = 6.4
4.4 ÷ 2.2 + 0 = 2  
4.4 ÷ 2.2 + 1 = 3  
4.4 ÷ 2.2 + 2 = 4  
      f '([1,2] ÷ 0) + 5'
1 ÷ 0 + 5 = NaN 
2 ÷ 0 + 5 = NaN 

Liệu nó có vượt qua các trường hợp thử nghiệm (không sửa đổi)? Nếu vậy thì nó là tốt.
J Atkin

@JAtkin Có một cái nhìn bây giờ.
Adám

Không, tốt nhất là tôi hiểu điều này vẫn không hỗ trợ thứ tự hoạt động.
J Atkin

@JAtkin "Bạn phải hỗ trợ thứ tự các hoạt động." Bạn không bao giờ quy định theo thứ tự. Đây không hỗ trợ các lệnh của ngôn ngữ sử dụng. Mỗi ngôn ngữ (bao gồm toán học trung học) có một quy tắc ưu tiên tùy ý (nhưng không may đôi khi thậm chí mơ hồ). Quy tắc của APL là không rõ ràng.
Adám

1
Tiêu chuẩn cho toán học là những gì tôi đã ngụ ý: en.wikipedia.org/wiki/Order_of_operations#DefDef . Tôi sẽ thêm nó vào bài viết ngay bây giờ
J Atkin
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.