Karsten W.
Karsten W.

Reputation: 18420

Using Solve in Mathematica

To get acquainted with Mathematica's solving functions, I tried to work out a solution to a MinuteMath problem:

There is a list of seven numbers. The average of the first four numbers is 5, and the average of the last four numbers is 8. If the average of all seven numbers is 46/7, then what is the number common to both sets of four numbers?

Of course, this is an excercise that can be solved without computer, but how can I solve this using Mathematica? My first approach

X = Table[Subscript[x, i], {i, 1, 7}];
cond = {
  Mean[Part[X, 1 ;; 4]] == 5,  
  Mean[Part[X, 4 ;; 7]] == 8, 
  Mean[X] == 46/7
};
Solve[cond, Subscript[x, 4]]

returned no solution. My second approach

X = Table[Subscript[x, i], {i, 1, 7}];
rules = {Mean[Part[X, 1 ;; 4]] -> 5,  
   Mean[Part[X, 4 ;; 7]] -> 8, 
   Mean[X] -> 46/7
};
Solve[
  Mean[X] == Mean[Part[X, 1 ;; 4]] 
    + Mean[Part[X, 4 ;; 7]] 
    - Subscript[x, 4] /. rules, 
  Subscript[x, 4]
]

gives a wrong solution (45/7 instead 6). What did I wrong?

Upvotes: 3

Views: 771

Answers (2)

Simon
Simon

Reputation: 14731

The first piece of code that you give is fine. The only problem is there is no solution for x_4 alone. If you replace the last line by Solve[cond] then Mathmatica automagically chooses the free variables and you'll get the solution.


I think that a simple/trivial example would make this type problem clear:

In[1]:= Solve[x==1&&y==2,x]
        Solve[x==1&&y==2,{x,y}]
Out[1]= {}
Out[2]= {{x->1,y->2}}

The final output can also be obtained using Solve[x==1&&y==2], where Mma guesses the free variables. This behaviour differs from that of Mathematica 7. In Mathematica 8 a new option for Solve (and related functions) called MaxExtraCondtions was introduced. This allows Solve to give solutions that use the new ConditionalExpression and is intended to make the behaviour of solve more consistent and predictable. Here's how it works in this simple example:

In[3]:= Solve[x==1&&y==2, x, MaxExtraConditions->1]
Out[3]= {{x -> ConditionalExpression[1, y==2]}}

See the above linked to docs for more examples that show why this Option is useful. (Although maybe defaulting to Automatic instead of 0 would be a more pragmatic design choice for the new option...)


Finally, here's your first solution rewritten a little:

In[1]:= X=Array[Symbol["x"<>ToString[#]]&,{7}]
Out[1]= {x1,x2,x3,x4,x5,x6,x7}

In[2]:= cond=Mean[X[[1;;4]]]==5&&Mean[X[[4;;7]]]==8&&Mean[X]==46/7;

In[3]:= Solve[cond]
         x4/.%
Out[3]= {{x1->14-x2-x3,x4->6,x5->26-x6-x7}}
Out[4]= {6}

Upvotes: 6

Dr. belisarius
Dr. belisarius

Reputation: 61016

Perhaps more compact:

Reduce[Mean@Array[f, 4] == 5 && 
       Mean@Array[f, 4, 4] == 8 && 
       Mean@Array[f, 7] == 46/7]
(*
-> f[5] == 26 - f[6] - f[7] && 
   f[4] == 6 && 
   f[1] == 14 - f[2] - f[3]
*)  

Although for clarity, I probably prefer:

Reduce[Sum[f@i, {i, 4}] == 20 && 
       Sum[f@i, {i, 4, 7}] == 32 && 
       Sum[f@i, {i, 7}] == 46]

Edit

Note that I am using function upvalues as vars and not list elements. I prefer this way because:

  • You don't need to initialize the list (Table[Subscript ... in your example`)
  • The resulting expressions are usually less cluttered (No Part[ ;; ], etc)

Upvotes: 4

Related Questions