Математичне заміщення


13

Іноді корисно запустити математичну задачу з кількома входами. Мета цього завдання - скласти програму, яка полегшує це завдання.

Вирази, що утворюють число

Ви повинні підтримувати 3 типи вираження:

  • Генератор одиничних чисел: Дуже простий, просто буквальний номер
  • Генератор декількох чисел: Tad складніше. Вони оточені квадратними дужками ( []). Числа ,у виразу розділені комами ( ). Приклад [-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 з точністю до нуля після коми?
Цифрова травма

Чи можуть входи змішувати діапазони та декілька чисел?
Мальтісен

@DigitalTrauma Я не думав про ці мови .... Я б сказав "ні".
J Atkin

також, чи x/0призводить до миттєвої оцінки NaN, чи я повинен ставитися до NaN як до значення?
Мальтісен

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

Пояснення

Рекурсивна функція, яка виконує вираз, якщо вона не містить множинних чисел чи діапазонів, або якщо він містить один з цих генераторів, викликає себе за допомогою генератора, заміненого на кожне створене ним число.

Поділ на 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

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

Пітон 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()

Ось код без вольфів:

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вчинив би так само?
Кіос

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

Діалог 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) та вилучення операторів. Він підміняє всі оператори катенацією та виконує вираз для отримання кінцевих вхідних чисел. Потім він плете все це для отримання остаточного результату.

Зберігає порядок оцінювання 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.