수학적 대체


13

때로는 여러 입력으로 수학 문제를 실행하는 것이 유용합니다. 이 과제의 목표는이 작업을 용이하게하는 프로그램을 만드는 것입니다.

숫자 생성 표현식

세 가지 유형의 표현을 지원해야합니다.

  • 단일 숫자 생성기 : 매우 간단하고 리터럴 숫자
  • 다중 숫자 생성기 : 조금 더 복잡합니다. 대괄호 ( []) 로 둘러싸여 있습니다. ,표현식에서 숫자는 쉼표 ( )로 구분됩니다. 예 [-1,2,3.26].
  • 레인지 제너레이터 : 이것은 중괄호 ( {})로 둘러싸여 있습니다. 쉼표로 구분 된 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에게 감사합니다.


부동 소수점 숫자를 지원해야합니다 (언어의 기본 정밀도가 좋은지). 내 언어가 정수 산술 만 지원하면 어떻게됩니까? 소수 자리 정밀도 FP가 0이라고 주장 할 수 있습니까?
Digital Trauma

입력 믹스 범위와 다중 숫자가 가능합니까?
Maltysen

@DigitalTrauma 나는 그런 언어를 생각하지 못했습니다 .... 나는 아니오라고 말할 것입니다.
J Atkin

또한 x/0NaN에 대한 즉각적인 평가가 이루어 지거나 NaN을 가치로 취급해야합니까?
Maltysen

@ Maltysen 예, 예를 포함시켜야합니까?
J Atkin

답변:


4

자바 스크립트 (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}
`)

설명

다중 숫자 또는 범위 생성기를 포함하지 않거나 이러한 생성기 중 하나를 포함하는 경우 표현식을 실행하는 재귀 함수는 생성 된 각 번호로 대체 된 생성기를 사용하여 자체 호출합니다.

0JavaScript로 나누면 생성 Infinity되므로 Infinity간단히 바꿀 수 있습니다 NaN.

이 방법을 사용하면 멀티 제너레이터가 테스트 사례 에서처럼 앞뒤로가 아니라 앞뒤로 구문 분석됩니다. 이것은 출력 표현식의 순서가 때때로 다르다는 것을 의미합니다.

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

하스켈, 474362 바이트

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

파이썬 3, 387 바이트

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줄에 괄호가 없으면 사용 합니다. NaN실행중인 예외 가 있으면 반환 합니다 eval.


프로그래밍 퍼즐과 코드 골프에 오신 것을 환영합니다!
J Atkin

왜 필요한 e[:]=s[:]가요? 하지 않을까요 e[:]=s동일한 작업을 수행?
Cyoce

1

자바, 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⍵}'⊢⍵}

정규 표현식을 사용하여 주어진 표현식을 해당 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 지금 살펴보십시오.
Adám

아니요, 내가 이해하는 한 여전히 작동 순서를 지원하지 않습니다.
J Atkin

@JAtkin "작업 순서를 지원해야합니다." 어떤 순서를 지정하지 않았습니다 . 이 수행 지원 사용되는 언어의 순서를. 모든 언어 (고등학교 수학 포함)에는 임의의 (그러나 불행히도 때로는 모호한) 우선 순위 규칙 세트가 있습니다. APL의 규칙은 분명합니다.
Adám

1
수학의 표준은 내가 암시 한 것입니다 : en.wikipedia.org/wiki/Order_of_operations#Definition . 지금 게시물에 추가하겠습니다
J Atkin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.