Solve a quadratic equation using Vieta's formulas

2

Exposition

Your mathematics teacher is a big fan of Vieta's formulas, and he believes that you should use them to solve quadratic equations. Given the equation

ax^2 + bx + c = 0

the product of its roots is c/a, and their sum is -b/a. When all of a, b and c are nonzero integers, assuming the roots are rational numbers, it's enough to try all possible numbers in the form

r1 = ±s/t

where s is a divisor of abs(c), and t is a divisor of abs(a). For each such r1, plug it into ax^2 + bx + c, and see whether the result is 0. If yes, then r1 is a root. The second root is -b/a-r1 or (c/a)/r1 - you can choose whatever formula you like.

Your teacher decided to give you many exercises, and he expects you to describe how you used Vieta's formulas to solve each one. Each exercise looks like this (example):

9x^2+12x+4=0

Write a subroutine or a program that gets an exercise as input, and outputs your alleged "solving process" to appease your teacher.


Input

Since you will feed the exercise to your program manually, format it in any convenient form. For example, use space-separated values on stdin:

9 12 4

or call a function with 3 parameters:

SolveExercise(9, 12, 4);

or parse the exercise literally:

9x^2+12x+4=0

Your output should be formatted as described below. Use the standard output device or return it as a string from your subroutine.

Output (example)

x = 1? 9x^2+12x+4 = 25
x = 2? 9x^2+12x+4 = 64
x = 1/3? 9x^2+12x+4 = 9
x = 2/3? 9x^2+12x+4 = 16
... (as many or as few failed attempts as you like)
x = -2/3? 9x^2+12x+4 = 0
r1 = -2/3
r2 = -12/9-(-2/3) = -2/3

Alternatively, the last line can be:

r2 = 4/9/(-2/3) = -2/3

Some additional notes:

  • The minimum number of line-breaks in the output is as described in the example (trailing line-break is not required). Additional line-breaks are permitted.
  • All coefficients in input are integers in the range [-9999...9999], none can be equal to 0
  • All roots are rational numbers, and should be output as such - e.g. 0.66666667 is not equal to 2/3 and so is incorrect
  • In the final expressions for r1 and r2, integers should be output as such, e.g. -99/1 is unacceptable, and should be output as -99; in other places in the output, denominator equal to ±1 is acceptable
  • Reduced form for rational numbers is not required - e.g. 2/4 is a good substitute for 1/2, even though it's ugly, even for roots r1 and r2
  • Parentheses in the output are sometimes required by rules of mathematics, e.g. in the expression 12/9/(2/3). When precedence rules of mathematics permit omission of parentheses, they are not required, e.g. -12/9--2/3. Superfluous parentheses are permitted: 4-(2) is OK, even though it's ugly
  • There should be at least one case (input) for which your program tries 3 or more non-integer values for r1; however, it's allowed to "guess the right answer" almost always on the first try
  • All trial values for r1 must be rational numbers ±s/t, where s and t are constrained as described above

Test cases

  1. Input

    x^2-x-2=0
    

    or

    1 -1 -2
    

    Possible output

    x=1? x^2-x-2=-2
    x=-1? x^2-x-2=0
    r1=-1
    r2=-2/1/-1=2
    
  2. Input

    -x^2+2x-1=0
    

    or

    -1, 2x, -1
    

    Possible output

    x=1? -x^2+2x-1=0
    r1=1
    r2=-2/-1-1=1
    
  3. Input

    7x^2-316x+924=0
    

    or

    X(7, -316, 924);
    

    Possible output (a divisor of 924 is 42, which solves the equation by "luck")

    x=42? 7x^2-316x+924=0
    r1=42
    r2=316/7-42=22/7
    
  4. Input

    6x^2-35x-6=0
    

    or

    [6 -35 -6]
    

    Possible output (even though your program may "know" that 6 is a root, it decides to show some failed trials)

    x=1/2? 6x^2-35x-6=-88/4
    x=1/3? 6x^2-35x-6=-153/9
    x=3/2? 6x^2-35x-6=-180/4
    x=6/1? 6x^2-35x-6=0
    r1=6
    r2=35/6-6=-1/6
    

    Alternative versions for the last line:

    r2=--35/6-6=-1/6
    r2=-6/6/6=-1/6
    
  5. Impossible input (no rational solutions)

    x^2+5x+1=0
    
  6. Impossible input (zero coefficient)

    x^2-1=0
    

anatolyg

Posted 2016-04-12T21:08:01.047

Reputation: 10 719

1Does it have to be in ax^2 + bx + c form, or can we have the input simply be a b c? – Zwei – 2016-04-13T01:05:40.843

Simple input is OK; updated the text – anatolyg – 2016-04-13T06:46:35.523

Was this downvoted for being "too advanced", or am I missing something... ? – cat – 2016-04-14T15:58:30.080

Answers

1

Python - 202 200 bytes

2 bytes saved thanks to @FryAmTheEggman.

from fractions import*;f=Fraction
lambda a,b,c:"\n".join(["x=%s?%dx^2+%dx+%d=%s"%(i,a,b,c,a*i*i+b*i+c)for i in[f(1,a),f(-1,a),f(c,a)]]+["r%d=%s"%((3-i)/2,f(i*(b*b-4*a*c)**.5-b)/f(2*a))for i in[1,-1]])

Maltysen

Posted 2016-04-12T21:08:01.047

Reputation: 25 023

2from fractions import*;f=Fraction? – FryAmTheEggman – 2016-04-13T13:17:31.110

1

JavaScript (ES6), 373

(a,b,c,z='',A=Math.abs,M=(c,x,a)=>'-+'[c>0|0]+(x&&a<2?x:a+x),G=(a,b)=>b?G(b,a%b):a,O=(n,d,g=G(n,d))=>(g=d*g<0?-g:g)-d?n/g+'/'+d/g:n/d,e=M(a,'x^2',o=A(a))+M(b,'x',A(b))+M(c,'',q=A(c)),K=s=>(z+=`
x=${s}/${t}? ${e}=`+(v=a*s*s+b*s*t+c*t*t)+(v?'':`
r1=${O(s,t)}
r2=(${c}/${a})/(${s}/${t})=`+O(c*t,s*a)),v))=>{for(s=0;++s<=q;)for(t=0;++t<=o;)if(!(q%s||o%t||K(-s)&&K(s)))return z}

Test

f=(a,b,c,z='',A=Math.abs,M=(c,x,a)=>'-+'[c>0|0]+(x&&a<2?x:a+x),G=(a,b)=>b?G(b,a%b):a,O=(n,d,g=G(n,d))=>(g=d*g<0?-g:g)-d?n/g+'/'+d/g:n/d,e=M(a,'x^2',o=A(a))+M(b,'x',A(b))+M(c,'',q=A(c)),K=s=>(z+=`
x=${s}/${t}? ${e}=`+(v=a*s*s+b*s*t+c*t*t)+(v?'':`
r1=${O(s,t)}
r2=(${c}/${a})/(${s}/${t})=`+O(c*t,s*a)),v))=>{for(s=0;++s<=q;)for(t=0;++t<=o;)if(!(q%s||o%t||K(-s)&&K(s)))return z}

// Less golfed
U=(a,b,c,
   // locals
   z='',
   A=Math.abs,
   M=(c,x,a)=>'-+'[c>0|0]+(x&&a<2?x:a+x),
   G=(a,b)=>b?G(b,a%b):a, // GCD
   O=(n,d,g=G(n,d))=>(g=d*g<0?-g:g)-d?n/g+'/'+d/g:n/d, // output a fraction
   o=A(a),q=A(c),
   e=M(a,'x^2',o)+M(b,'x',A(b))+M(c,'',q), // espression from coefficients
   K=s=>( // check & output a candidate solution
      z+=`\nx=${s}/${t}? ${e}=`+(v=a*s*s+b*s*t+c*t*t)+(v?'':`
r1=${O(s,t)}
r2=(${c}/${a})/(${s}/${t})=`+O(c*t,s*a)),v
  )
)=>{
  for(s=0;++s<=q;)
    for(t=0;++t<=o;)
      if(!(q%s||o%t||K(-s)&&K(s)))
        return z
}  

console.log=x=>O.textContent+=x+'\n'

// Test
console.log(f(9,12,4))
console.log(f(1,-1,-2))
console.log(f(-1,2,-1))
console.log(f(7,-316,924))
console.log(f(6,-35,-6))
<pre id=O></pre>

edc65

Posted 2016-04-12T21:08:01.047

Reputation: 31 086

0

Mathematica, 236 Bytes

I'm sure there's a way to shorten this further, but this was my first attempt at learning the language.

Golfed

s=Input[];f[x_]:=#3 x^2+#1 x+#2&@@s;t=Drop[Z1,1];r=Catch[Do[Print[StringForm["x=``? ``=``",y,f[x],f[y]]];If[f[y]==0,Throw[y]],{y,(Flatten[Outer[Divide,#1,#2]]&@@(Join[#,-#]&/@Divisors[#]&[t]))}]]StringForm["r1=``\nr2=``",r, #1/#2/r&@@t]

Ungolfed with comments

(*Get coefficients in list {B,C,A}*)
s=Input[];

(*Create the function*)
f[x_]:=#3 x^2+#1 x+#2&@@s;

(*Take C and A*)
t=Drop[Z1,1];

(*Get a list of all positive and negative divisors for C and A, then use those to get all possible permutations for R=S/T as given in the challenge*)
(*Print out each attempt at finding a root. If one is found, exit the loop and return it*)

r=Catch[Do[Print[StringForm["x=``? ``=``",y,f[x],f[y]]];If[f[y]==0,Throw[y]],{y,(Flatten[Outer[Divide,#1,#2]]&@@(Join[#,-#]&/@Divisors[#]&[t]))}]];

(*Print the roots using (c/a)/r1 *)
StringForm["r1=``\nr2= ``",r, #1/#2/r&@@t]

Coefficients must be entered in the (convenient) form {B,C,A}.

Xanderhall

Posted 2016-04-12T21:08:01.047

Reputation: 1 236