Evaluate polynomial expression string

18

3

Create a function which takes a polynomial equation, a value for x and returns the result of the operation.

Example: given 4x^2+2x-5 and x=3 output 37. This is the result of 4(3)^2+2(3)-5

  • Assume all polynomials are valid
  • Polynomial format will always be coefficient(variable)^exponent => 4x^2 except :
    • When exponent is 1 it will be coefficient(variable) => 4x
    • When coefficient is 1 it will be (variable)^exponent => x^2
  • Polynomials are one variable only
  • Use of external libraries are forbidden
  • The coefficient and variable input can be positive and negative numbers.

Test cases

  • ("3x^3-5x^2+2x-10", 5) => 250
  • ("10x^4-5x^3-10x^2+3x+50", 3) => 644
  • ("10x+20", 10) => 120
  • ("-20x^2+20x-50", -8) => -1490
  • ("9", 5) => 9
  • ("8x^2+5", 0) => 5

Update

  • Polynomial format will always be coefficient(variable)^exponent => 4x^2 except :
    • When exponent is 1 it will be coefficient(variable) => 4x
    • When coefficient is 1 it will be (variable)^exponent => x^2
  • Removed the rule of negative exponent. My mistake. A valid polynomial does not contain negative exponent
  • An exponent of 0 would be just coefficient
  • Added test case for input 0

This is , so the shortest answer in bytes win.

Luis felipe De jesus Munoz

Posted 2018-06-04T12:37:03.817

Reputation: 9 639

3How flexible is the input format? Instead of 3x^3-5x^2+2x-10 can we input 3*x^3-5*x^2+2*x-10? Or [3 -5 2 -10]. [3 2 1 0]? – Luis Mendo – 2018-06-04T13:59:03.977

Can the exponent input sign be ** instead of ^? – sergiol – 2018-06-04T17:20:38.720

@sergiol no.... – Luis felipe De jesus Munoz – 2018-06-04T17:21:36.233

Can we take X in uppercase? – Arnauld – 2018-06-04T20:01:51.387

1@Arnauld Yes... – Luis felipe De jesus Munoz – 2018-06-04T20:04:20.767

4What is an "external library" and how is it fair, compared to languages who have "eval" already implemented as a feature? – Olivier Grégoire – 2018-06-04T23:02:59.913

1My apologies I haven't use my pc since yesterday. I have updated the challenge with the suggestions you gave me. Please take a look at it and reopen it if everything is ok. – Luis felipe De jesus Munoz – 2018-06-05T12:32:13.757

1Please merge the "Update" part. – user202729 – 2018-06-05T13:39:33.890

(also don't worry too much about slow update, closed challenges can be reopened, etc.) – user202729 – 2018-06-05T13:41:04.230

Your specs don't match your examples. It should be 10x^0 under your specs, but your examples use 10. – Yakk – 2018-06-05T19:50:03.567

1Your test cases don't have any coefficients of 1 – Noodle9 – 2018-06-05T21:01:18.223

Answers

12

JavaScript (ES7), 48 bytes

Based upon a suggestion from @RickHitchcock

Expects X in uppercase. Takes input in currying syntax (p)(X).

p=>X=>eval(p.replace(/[X^]/g,c=>c<{}?'*X':'**'))

Try it online!


JavaScript (ES7), 49 bytes

Same approach as @DeadPossum. Takes input in currying syntax (p)(x).

p=>x=>eval(p.split`x`.join`*x`.split`^`.join`**`)

Try it online!

Arnauld

Posted 2018-06-04T12:37:03.817

Reputation: 111 334

1I think you can save a couple bytes by using replace: p=>x=>eval(p.replace(/[x^]/g,a=>a>f?'*x':'**')) – Rick Hitchcock – 2018-06-04T19:50:36.800

@RickHitchcock I can't use a reference to f unless it's included in the byte count, at the cost of the 2 bytes that are supposed to be saved. I like this method, though. There might be a way to save a byte or two by revamping it somehow. – Arnauld – 2018-06-04T20:00:06.807

Oh, of course. Hmm. – Rick Hitchcock – 2018-06-04T20:02:54.413

2@RickHitchcock If we can take X in uppercase, then we can do a<{}?'*X':'**', saving a byte. Hence my question to the OP. – Arnauld – 2018-06-04T20:03:46.457

1cant handle x alone – l4m2 – 2018-06-07T09:01:27.760

1@l4m2 The challenge rules were updated. :/ It used to be 1x for x. – Arnauld – 2018-06-07T09:08:26.103

8

Python 2, 54 bytes

-2 bytes thanks to Jo King

-5 bytes thanks to Arnauld

lambda p,x:eval(p.replace('^','**').replace('x','*x'))

Try it online!

Dead Possum

Posted 2018-06-04T12:37:03.817

Reputation: 3 256

8

Python 3, 53 50 48 bytes

edit: -5 bytes thanks to Dennis !

lambda p,x:eval(p.translate({94:"**",120:"*x"}))

Try it online!

Used translate to avoid chaining replace calls; Python 3's version of translate is less awkward than its predecessor's.

etene

Posted 2018-06-04T12:37:03.817

Reputation: 448

"*(%d)"%x can become "*(x)". – Dennis – 2018-06-04T14:11:23.917

Thank you, I hadn't event figured out x was in my eval scope ! I'll update. – etene – 2018-06-04T15:36:28.493

1Actually, since x is no longer a string representation, "*x" works as well. – Dennis – 2018-06-04T15:56:02.570

Even better ! Thanks again. – etene – 2018-06-04T18:00:48.003

5

R, 44 bytes

function(f,x)eval(parse(t=gsub("x","*x",f)))

Try it online!

Fairly straightforward with R. Replace nx with n*x and then eval the parsed string. x is used as this is how we name the second argument.

The eval function could even be used more directly with a properly formatted first argument, and other formal arguments (y, z, etc.) could be easily added:

R, 20 bytes (non-competing)

function(f,x)eval(f)

Try it online!

JayCe

Posted 2018-06-04T12:37:03.817

Reputation: 2 655

4

Japt 2.0, 13 bytes

OvUd^'*²'x"*V

Try it.

Explanation:

OvUd^'*²'x"*V
              U = Implicit first input
              V = Implicit second input

Ov            Eval:
  Ud            In U, replace:
    ^             "^" with:
     '*²            "**"
        'x        "x" with:
          "*V       "*V"

Oliver

Posted 2018-06-04T12:37:03.817

Reputation: 7 160

4

Wolfram Language (Mathematica), 22 bytes

ToExpression@#/.x->#2&

Try it online!

alephalpha

Posted 2018-06-04T12:37:03.817

Reputation: 23 988

3

JavaScript (Node.js), 113 108 bytes

_=>x=>_.match(/-?(?:[x\d]+|\^?)+/g).reduce((a,b)=>b.split`x`[0]*(~b.indexOf`x`?x**(b.split`^`[1]||1):1)+a,0)

Try it online!

Thanks to @Arnauld


Since the best JS solution so far by @Arnauld (49 bytes) has already been posted and it uses eval, I decided to use Regex and reduce instead of that.

Pretty lengthy compared to his though.

Explanation :

A =>                            // lambda function accepting argument 1 
    x =>                        // argument number 2 (currying syntax used)
        A.match(                // this matches all instance of what comes next 
                                // and converts to array
       /[-]?(?:[x\d]+|\^?)+/g)  // regexp for -ve sign , variable number and ^ sign 
            .reduce((a, b) =>   // reduce the array to single (take 2 params a,b)
                b.split `x`     // split b at instances of `x` 
                        [0]     // and select the first instance 
                * (b.indexOf`x` // multiply that by value of index of x in b 
                    > 0 ?       // if it is greater than 0 then 
                x **            // multiplication will be with x raised to power
               (l = b.split `^` // set variable split b at every `x` 
                   [1]||1       // choose first index otherwise set to one
                )               // this is what x is raised to the power 
                : 1)            // in the case x is not present multiply by 1
                + a,            //  add value of `a` to that value 
        0)                      // in case no reduce is possible set value to 0

Muhammad Salman

Posted 2018-06-04T12:37:03.817

Reputation: 2 361

This currently fails on the last test case (should be 0.25). You can save a few bytes by using - instead of [-], ~b.indexOf\x` instead ofb.indexOf`x`>0and removingl=` which is not used. (But this doesn't fix the bug.) – Arnauld – 2018-06-04T20:39:47.640

@Arnauld: Thanks. No idea why it does that, will see what the problem – Muhammad Salman – 2018-06-04T20:59:40.207

Well, the problem is that your regex splits 1x^-2 on the -. – Arnauld – 2018-06-04T21:03:08.973

3

05AB1E, 16 19 bytes

„*(I')J'xs:'^„**:.E

+3 bytes as bug-fix for negative input x.

.E (Run as Batch code) has been replaced with Run as Python eval in this latest commit of @Adnan, but this version isn't on TIO yet. @Mr.Xcoder tested it on his local (latest version) 05AB1E to verify it's working.
See this version without .E to see how it converted the expression string.

Explanation:

„*I')J'xs:    # Replace all "x" with "*(n)" (where `n` is the input-integer)
              #  i.e. 5 and 3x^3-5x^2+2x-10 → 3*(5)^3-5*(5)^2-2*(5)-10
'^„**:        # Replace all "^" with "**"
              #  i.e. 3*(5)^3-5*(5)^2-2*(5)-10 → 3*(5)**3-5*(5)**2-2*(5)-10
.E            # Evaluate as Python-eval
              #  i.e. 3*(5)**3-5*(5)**2-2*(5)-10 → 250

Alternative 25 28 bytes program that works on the current version of TIO:

„*(I')J'xs:'^„**:“…¢(“s')J.e

Try it online.

Explanation:

„*(I')J'xs:'^„**:    # Same as explained above
“…¢(“                # Literal string "print("
     s               # Swap both
      ')             # Literal character ")"
        J            # Join everything together
                     #  i.e. 3*(5)**3-5*(5)**2-2*(5)-10 → print(3*(5)**3-5*(5)**2-2*(5)-10)
.e                   # Run as Python code
                     #  i.e. print(3*(5)**3-5*(5)**2-2*(5)-10) → 250

“…¢(“ is the string print(, because:

  • and starts and ends the compressed string
  • …¢ is equal to 0426 because it looks at the indices in the info.txt file, where has index 4, and ¢ has index 26.
  • This index 0426 is then used in the dictionary-file, where line 427 (index 426) is the word it fetches, which is print in this case.
  • The ( doesn't have an index in the info.txt file, so it is interpret as is.

Kevin Cruijssen

Posted 2018-06-04T12:37:03.817

Reputation: 67 575

2

JavaScript (Node.js), 143 bytes

I know there are better answers but I wanted to do it without using eval

(_,x)=>_.match(/[+-]?(?:[a-z0-9.]+|\^-?)+/gi).reduce((a,b)=>~~(b.split('x')[0])*(b.indexOf('x')>0?Math.pow(x,(l=(b.split('^')[1]))?l:1):1)+a,0)

Try it online!

Luis felipe De jesus Munoz

Posted 2018-06-04T12:37:03.817

Reputation: 9 639

Your regex doesn't need [a-z0-9.] does it? The only letter that can appear is x. Any why .? You don't need to handle non-integer coefficients or exponents. – Peter Cordes – 2018-06-05T04:58:31.067

2

Physica, 35 bytes

->e;x:Eval@Replace[e;"x";f"*({x})"]

Try it online!

Mr. Xcoder

Posted 2018-06-04T12:37:03.817

Reputation: 39 774

2

Octave, 47 38 37 bytes

Saved a lot of bytes by taking the second input as a string instead of a number.

@(x,c)eval(strrep(x,'x',['*(',c,41]))

Try it online!

Explanation:

Fairly straight forward: Replace x by (c) , where c is the second input, and evaluate. The paretheses are necessary because in Octave -8^2 == -64.

Stewie Griffin

Posted 2018-06-04T12:37:03.817

Reputation: 43 471

2

Java 8, 150 149 148 bytes

n->s->new javax.script.ScriptEngineManager().getEngineByName("JS").eval(s.replace("x","*"+n).replaceAll((s="(\\-?\\d+)")+"\\^"+s,"Math.pow($1,$2)"))

Not sure if it's possible to have a currying lambda function that throws an Exception. If it is, 1 byte can be saved changing (s,n)-> to n->s->. -1 byte thanks to @OlivierGrégoire for showing me how to do this.

Try it online.

Explanation:

n->s->     // Method with integer and String parameters and Object return-type
  new javax.script.ScriptEngineManager().getEngineByName("JS")
            //  Use a JavaScript engine
   .eval(s  //  And eval the input
      .replace("x","*"+n)
            //   After all 'x' has been replaced with '*n'
            //   (where `n` is the input-integer)
      .replaceAll((s="(\\-?\\d+)")+"\\^"+s,"Math.pow($1,$2)"))
            //   And all `A^B` have have been replaced with `Math.pow(A,B)`
            //   (where both `A` and `B` are integers)

Unfortunately the JavaScript eval doesn't support **, so I have to use a longer replace to convert it to Math.pow instead..

Kevin Cruijssen

Posted 2018-06-04T12:37:03.817

Reputation: 67 575

JavaScript does support ** (ES7+), why does this not support that ? – Muhammad Salman – 2018-06-04T14:16:36.547

Also is there no eval in java. That can't be right ? – Muhammad Salman – 2018-06-04T14:17:12.237

@MuhammadSalman Nope, Java has no eval. And I think this builtin JavaScript-eval I can use with ScriptEngineManager hasn't been updated in the Java JDK for years, so it doesn't support ES7+.. – Kevin Cruijssen – 2018-06-04T14:20:01.283

Man, java sucks, no eval why ? Okay why hasn't it been updated ? – Muhammad Salman – 2018-06-04T14:21:18.090

@MuhammadSalman I dunno.. You'll have to ask the creators of Java that question. ;) – Kevin Cruijssen – 2018-06-04T14:26:25.777

Good idea, will go ask them (most of of your byte count is for importing the engine – Muhammad Salman – 2018-06-04T14:29:45.427

1

Yes, there's an eval in java, since Java 9.

– Olivier Grégoire – 2018-06-04T22:54:38.077

And here's your curried version (148 bytes) ;-)

– Olivier Grégoire – 2018-06-04T23:01:22.380

2

Jelly, 21 bytes

ṣ”^j⁾**ṣ”xjØ(j”*;Ʋ}ŒV

Try it online!

Erik the Outgolfer

Posted 2018-06-04T12:37:03.817

Reputation: 38 134

Due to operator precedence, this doesn't work for ("-20x^2+20x-50", -8). – Dennis – 2018-06-04T18:15:36.977

@Dennis Adjusted accordingly. – Erik the Outgolfer – 2018-06-04T18:51:51.340

2

TI-Basic, 6 bytes

Prompt X:expr(Ans

Expression is taken as argument and X is entered during runtime. Alternatively 8 bytes without expr:

Prompt X,u:u

Here both arguments are entered at runtime.

Timtech

Posted 2018-06-04T12:37:03.817

Reputation: 12 038

1

Ruby, 43 bytes

->s,x{eval s.gsub /[x^]/,?x=>"*x",?^=>"**"}

Try it online!

G B

Posted 2018-06-04T12:37:03.817

Reputation: 11 099

Nice approach with hash replacement, but straight two gsubs are even shorter

– Kirill L. – 2018-06-04T13:34:41.903

1

Ruby, 43 41 bytes

->p,x{eval p.gsub('^','**').gsub'x','*x'}

Try it online!

Saved two bytes thanks to @Mr.Xcoder


Since there isn't a Ruby answer yet I added one. Nvm there was one that used a different approach

Explanation :

->p,x{                    # lambda function that takes two arguments p and x
    eval(                 # eval 
        p.gsub(           # replace all instance of 
            '^' , '**'    # `^` with `**` (use for raised to power of)
        )                 # end gsub
        .gsub(            # start another replace all
            'x' , '*x'    # replace all instances of `x` with `*x`
        )                 # end the replace function
    )                     # end eval function
}                         # end lambda function

Muhammad Salman

Posted 2018-06-04T12:37:03.817

Reputation: 2 361

I think using gsub"x","*x" saves two bytes. – Mr. Xcoder – 2018-06-05T07:59:25.010

1

Perl 5 -pl, 35 bytes

s/\^/**/g;$q=<>;s/x/*($q)/g;$_=eval

Try it online!

Xcali

Posted 2018-06-04T12:37:03.817

Reputation: 7 671

1

Wolfram Language (Mathematica), 19 bytes

(x=#;ToExpression)&

Try it online!

Take input by currying: f[x][expr].

user202729

Posted 2018-06-04T12:37:03.817

Reputation: 14 620

1

Excel, 36+2 bytes, Non-competing

Evaluating a Text field as a formula is not straight forward in Excel. There is a hidden =EVALUATE() function, that can be called by defining a Name.

In Excel 2007, Formulas > Define Name. Define a Name called E, with Refers to:

=EVALUATE(SUBSTITUTE(A1,"x","*"&B1))

Then, with Formula input in A1, x value in B1, entering =E in C1 returns expected result.

Wernisch

Posted 2018-06-04T12:37:03.817

Reputation: 2 534