Matematiksel ikame


13

Bazen birden fazla girişle matematik problemi çalıştırmak faydalı olabilir. Bu zorluğun amacı bu görevi kolaylaştıran bir program yapmaktır.

Sayı üreten ifadeler

3 tür ifadeyi desteklemelisiniz:

  • Tek sayı üreteci: Çok basit, sadece gerçek bir sayı
  • Çok sayı üreteci: Biraz daha karmaşık. Parmaklar köşeli parantez ( []) ile çevrilidir . Sayılar ,ifadede virgülle ( ) ayrılır. Örnek [-1,2,3.26].
  • Menzil üreteci: Bu, kıvırcık parantez ( {}) ile çevrilidir . Virgülle ayrılmış 3 sayı olacaktır. Bu ifadenin biçimi {start,stop,step}. startve stopkapsayıcı.

Değerlendirme kuralları

  • İşlem sırasını desteklemelisiniz. ( https://en.wikipedia.org/wiki/Order_of_operations#Definition )
  • Parantezi desteklemenize gerek yoktur.
  • İfadede herhangi bir sayıda boşluk oluşabilir.
  • Kayan nokta sayılarını desteklemelisiniz (dilinizin varsayılan değeri ne olursa olsun iyi).
  • 0Sonuçlara göre bölümleme NaN(sayı değil).

Programınız çarpma ( *), bölme ( /), toplama ( +) ve çıkarma ( -) işlevlerini desteklemelidir .

Çıktı

Her çıkış hattı, jeneratörlerin kombinasyonlarından biridir. Biçim, ifade (gerçek sayılar ikame edilmiş) ve ardından eşittir işareti ( =) ve değerlendirmenin sonucudur. Jeneratörlerin tüm kombinasyonları çıktıda temsil edilmelidir.

Örnekler

( >>>girişi gösterir)

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

Programın kısa olması gerekir, böylece onu ezberler ve her yerde kullanabilirim.

@PeterTaylor ve @geokavel'e sandbox'ta bu gönderiyle yardımcı olduğun için teşekkürler


Kayan nokta sayılarını desteklemelisiniz (dilinizin varsayılan değeri ne olursa olsun iyi). Dilim yalnızca tamsayı aritmetiği destekliyorsa ne olur? Sıfır ondalık basamak hassasiyetli FP'ye sahip olduğumu iddia edebilir miyim?
Dijital Travma

Giriş karışımı aralıkları ve çoklu sayılar olabilir mi?
Maltysen

@DigitalTrauma Bu dilleri düşünmemiştim .... Hayır derdim.
J Atkin

Ayrıca, x/0NaN için anında değerlendirme ile sonuçlanır mı, yoksa NaN'ı bir değer olarak mı değerlendirmem gerekir?
Maltysen

@Maltysen Evet, bir örnek vermeli miyim?
J Atkin

Yanıtlar:


4

JavaScript (ES6), 213 211 bayt

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

açıklama

Herhangi bir çok sayı veya aralık üreteci içermiyorsa veya bu üreteçlerden birini içeriyorsa ifadeyi yürüten özyinelemeli işlev, kendisini ürettiği her sayı ile değiştirilmiş jeneratör ile çağırır.

0JavaScript ile bölme üretir Infinity, böylece Infinitybasitçe değiştirilebilir NaN.

Bu yöntem kullanılarak çoklu jeneratörler, test durumlarında olduğu gibi önden arkaya yerine arkadan öne doğru ayrıştırılır. Bu sadece çıktı ifadelerinin sırasının bazen farklı olduğu anlamına gelir.

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
)

Ölçek

Test, tarayıcı uyumluluğu için yıkıcı atamalar kullanmaz.

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>


Aslında bu benim öngördüğüm cevaba çok yakın.
J Atkin

4

Haskell, 474362 bayt

F işlevi girdi olarak bir dize alır ve sonuçları yazdırır

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)

testler:

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

çıktı:

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 Bayt

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

Aşağıdaki kodla test edebilirsiniz:

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

İşte ungolfed kodu:

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

Herhangi bir türdeki ilk parantez kümesini bularak ve ardından parantezleri ve içeriğini değerle değiştirip yöntemi özyinelemeli olarak çalıştırarak içindeki tüm değerler arasında döngü yaparak çalışır. Hatta evalparantez olmadığında kullanır . NaNÇalışan bir istisna varsa geri döner eval.


(biraz geç) Programlama Bulmacaları ve Kod Golf hoş geldiniz!
J Atkin

Neden ihtiyacın var e[:]=s[:]? Olmaz e[:]=saynı şeyi?
Cyoce

1

Java, 874 bayt

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

Detaylı Burada Deneyin

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 bayt

Bu cevap güncellenen gereksinimleri karşılamamaktadır ve bu nedenle rekabet etmemektedir:

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

Verilen ifadeyi karşılık gelen APL'ye değiştirmek için regexes kullanır (ve tüm operatörler uygulamak için değiştirilir NaN) ve operatörleri ayıklar. Tüm operatörleri katener ile değiştirir ve son girdi sayılarını elde etmek için ifadeyi yürütür. Daha sonra nihai çıktıyı elde etmek için hepsini bir araya getirir.

APL'nin değerlendirme sırasını korur (katı sağdan sola).

Parantezleri doğru şekilde işler.

Test senaryoları (matematik benzeri yürütme sırasını zorlamak için parantez eklenmiş olarak):

      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 

(Değiştirilmemiş) test vakalarını geçiyor mu? Eğer öyleyse o zaman gayet iyi.
J Atkin

@JAtkin Şimdi bir göz atın.
Adam

Hayır, anladığım kadarıyla bunun hala operasyon sırasını desteklemediğini düşünüyorum.
J Atkin

@JAtkin "İşlem sırasını desteklemelisin." Hangi siparişi asla belirtmediniz . Bu does desteklemek kullanılan dil sırasını. Her dilin (lise matematiği dahil) keyfi (ama ne yazık ki bazen belirsiz) bir öncelik kuralı vardır. APL'nin kural seti açık.
Adam

1
Matematik standardı benim ima ettiğim şey: en.wikipedia.org/wiki/Order_of_operations#Definition . Bunu şimdi yazıya ekleyeceğim
J Atkin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.