การทดแทนทางคณิตศาสตร์


13

บางครั้งมันมีประโยชน์ในการรันปัญหาคณิตศาสตร์ด้วยอินพุตหลายตัว เป้าหมายของความท้าทายนี้คือการสร้างโปรแกรมที่ช่วยให้งานนี้ง่ายขึ้น

นิพจน์ที่สร้างตัวเลข

คุณต้องสนับสนุนการแสดงออก 3 ประเภท:

  • ตัวสร้างตัวเลขเดี่ยว: ง่ายมากเพียงแค่ตัวอักษร
  • เครื่องกำเนิดหลายหมายเลข: ตาดซับซ้อนมากขึ้น Thees ถูกล้อมรอบด้วยวงเล็บเหลี่ยม ( []) ตัวเลขคั่นด้วยเครื่องหมายจุลภาค ( ,) ในนิพจน์ [-1,2,3.26]ตัวอย่าง
  • Range generator: อันนี้ล้อมรอบด้วยเครื่องหมายปีกกา ( {}) มันจะมี 3 ตัวเลขคั่นด้วยเครื่องหมายจุลภาค {start,stop,step}รูปแบบของการแสดงออกนี้อยู่ startและstopรวม

กฎสำหรับการประเมินผล

  • คุณต้องสนับสนุนคำสั่งของการดำเนินงาน ( https://en.wikipedia.org/wiki/Order_of_operations#Definition )
  • คุณไม่จำเป็นต้องสนับสนุนวงเล็บ
  • จำนวนช่องว่างใด ๆ ที่อาจเกิดขึ้นในการแสดงออก
  • คุณต้องสนับสนุนตัวเลขทศนิยม (สิ่งที่แม่นยำค่าเริ่มต้นของภาษาของคุณจะดี)
  • หารด้วย0ผลลัพธ์ในNaN(ไม่ใช่ตัวเลข)

โปรแกรมของคุณต้องรองรับการคูณ ( *), การหาร ( /), การเพิ่ม ( +) และการลบ ( -)

เอาท์พุต

เอาต์พุตแต่ละบรรทัดเป็นหนึ่งในการรวมกันของเครื่องกำเนิดไฟฟ้า รูปแบบคือนิพจน์ (ที่มีจำนวนจริงแทนลงไป) ตามด้วยเครื่องหมายเท่ากับ ( =) และผลลัพธ์ของการประเมิน การรวมกันทั้งหมดของเครื่องกำเนิดไฟฟ้าจะต้องเป็นตัวแทนในการส่งออก

ตัวอย่าง

( >>>หมายถึงอินพุต)

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

โปรแกรมต้องสั้นเพื่อให้สามารถจดจำและใช้งานได้ทุกที่

ขอบคุณ @PeterTaylor และ @geokavel ที่ช่วยฉันด้วยการโพสต์นี้ในกล่องทราย


คุณต้องสนับสนุนตัวเลขทศนิยม (สิ่งที่แม่นยำค่าเริ่มต้นของภาษาของคุณจะดี) จะทำอย่างไรถ้าภาษาของฉันรองรับเฉพาะเลขจำนวนเต็ม ฉันสามารถอ้างได้ว่าฉันมีความแม่นยำของตำแหน่งทศนิยมเป็นศูนย์หรือไม่?
บาดเจ็บทางดิจิทัล

สามารถผสมช่วงอินพุตและตัวเลขหลายตัวได้หรือไม่?
Maltysen

@ DigitalTrauma ฉันไม่ได้คิดถึงภาษาเหล่านั้น .... ฉันจะบอกว่าไม่
J Atkin

ยังx/0ส่งผลให้มีการประเมินผลทันทีให้กับ NaN หรือไม่หรือฉันต้องถือว่า NaN เป็นค่าหรือไม่?
Maltysen

@ Maltysen ใช่ฉันควรจะมีตัวอย่างหรือไม่
J Atkin

คำตอบ:


4

JavaScript (ES6), 213 211 ไบต์

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}
`)

คำอธิบาย

ฟังก์ชั่นเรียกซ้ำที่ดำเนินการแสดงออกถ้ามันไม่ได้มีหลายหมายเลขหรือช่วงกำเนิดหรือถ้ามันมีหนึ่งในเครื่องกำเนิดไฟฟ้าเหล่านี้เรียกตัวเองด้วยเครื่องกำเนิดไฟฟ้าที่ถูกแทนที่ด้วยแต่ละหมายเลขที่ผลิตโดยมัน

หารด้วย0ในการผลิตงาน JavaScript Infinityเพื่อให้สามารถเพียงแค่ถูกแทนที่ด้วยInfinityNaN

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

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
)

ทดสอบ

การทดสอบไม่ได้ใช้การมอบหมายการทำลายโครงสร้างเพื่อความเข้ากันได้ของเบราว์เซอร์

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>


อันนี้จริง ๆ แล้วใกล้กับคำตอบที่ฉันจินตนาการ
J Atkin

4

Haskell, 474 362 ไบต์

ฟังก์ชัน f รับสตริงเป็นอินพุตและพิมพ์ผลลัพธ์

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)

การทดสอบ:

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}"

เอาท์พุท:

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 Bytes

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")

คุณสามารถทดสอบด้วยรหัสต่อไปนี้:

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()

นี่คือรหัส ungolfed:

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")

มันทำงานได้โดยการค้นหาชุดแรกของวงเล็บประเภทใดแล้ววนลูปผ่านค่าทั้งหมดภายในนั้นโดยแทนที่วงเล็บและเนื้อหาของมันด้วยค่าและเรียกใช้วิธีการซ้ำ มันใช้evalเมื่อไม่มีเครื่องหมายวงเล็บในบรรทัด ก็จะส่งกลับถ้ามีข้อยกเว้นการทำงานNaNeval


(ช้าไปหน่อย) ยินดีต้อนรับสู่ Programming Programming & Golf Golf!
J Atkin

ทำไมคุณต้องe[:]=s[:]? จะไม่e[:]=sทำเช่นเดียวกัน?
Cyoce

1

Java, 874 ไบต์

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);}

ลองรายละเอียดที่นี่

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

Dyalog APL , 164 ไบต์

คำตอบนี้ไม่เป็นไปตามข้อกำหนดที่อัพเดตและดังนั้นจึงไม่ใช่การแข่งขัน:

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

มันใช้ regexes เพื่อเปลี่ยนการแสดงออกที่กำหนดลงใน APL ที่สอดคล้องกัน (และผู้ประกอบการทั้งหมดมีการแก้ไขเพื่อนำไปใช้NaN) และเพื่อแยกผู้ประกอบการ มันจะแทนที่ตัวดำเนินการทั้งหมดด้วยการ catenation และดำเนินการแสดงออกเพื่อรับหมายเลขอินพุตสุดท้าย จากนั้นจึงรวมเข้าด้วยกันเพื่อให้ได้ผลลัพธ์สุดท้าย

รักษาลำดับการประเมินของ APL (จากขวาไปซ้ายเข้มงวด)

จัดการวงเล็บอย่างถูกต้อง

กรณีทดสอบ (ที่มีวงเล็บที่เพิ่มเข้ามาเพื่อบังคับให้ลำดับการดำเนินการเหมือนคณิตศาสตร์):

      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 

มันผ่านกรณีทดสอบ (ไม่ได้แก้ไข) หรือไม่? ถ้าเป็นเช่นนั้นมันก็ไม่เป็นไร
J Atkin

@JAtkin ลองดูสิ
อดัม

ไม่ดีที่สุดเท่าที่ฉันเข้าใจว่านี่ยังไม่สนับสนุนลำดับการดำเนินการ
J Atkin

@JAtkin "คุณต้องสนับสนุนคำสั่งของการดำเนินการ" คุณไม่เคยระบุไว้ซึ่งการสั่งซื้อ นี้ไม่สนับสนุนคำสั่งของภาษาที่ใช้ ทุกภาษา (รวมคณิตศาสตร์ระดับมัธยม) มีกฎเกณฑ์ที่สำคัญ (แต่น่าเสียดายที่บางครั้งก็คลุมเครือ) กฎของ APL นั้นไม่คลุมเครือ
อดัม

1
มาตรฐานสำหรับคณิตศาสตร์เป็นสิ่งที่ผมหมายความ: en.wikipedia.org/wiki/Order_of_operations#Definition ฉันจะเพิ่มที่โพสต์ในขณะนี้
J Atkin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.