Reputation: 18420
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
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
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:
Table[Subscript ...
in your
example`)Part[ ;; ]
, etc)Upvotes: 4