2
$\begingroup$

Suppose I have an equation relating a number of variables and I know the values of all but one of them. Using the equation and known values as input, is there a simple command (built-in or otherwise) to determine the missing value?

Original example:

Consider the formula for the area of a rectangle. I can write the formula as area[length_, width_] := length*width and plug in numbers for the dimensions and get the area. Also, I could write a formula for finding each specific dimension in terms of the remaining two. My question is this: Is there a way to write a single expression which will do the whole job, that is I can plug in any two of the components of the area formula and have Mathematica return the third?

So for instance, if

equation = area == area[length, width]

and let's say the area is 5 and the length is 2. The output should be

{area -> 5, length -> 2, width -> 5/2}

or simply

width -> 5/2

Response to comment: I'm not sure what the syntax should look like. Preferably it would be expressive and natural (obviously). Maybe area -> 5 or area == 5 is a natural way to code a given value; or maybe even as an argument. [Edit note, Michael E2: I don't know what the OP had mind. I don't want to restrict the question too much here, esp. if someone has a really nice way of doing it. I hope it is sufficient that the equation and all but one value of the variables are known and can be used as input.]

$\endgroup$
3
  • $\begingroup$ Yes, what you ask for can be done with Manipulate. $\endgroup$
    – m_goldberg
    Commented Mar 28, 2014 at 13:07
  • 1
    $\begingroup$ maybe it would help if you showed examples of what you expect the syntax to look like. The question title doesn't reflect at all what you are asking by the way. $\endgroup$
    – george2079
    Commented Mar 28, 2014 at 13:26
  • $\begingroup$ @george2079. The title is my edit, not the OP's original title. It's my best shot at describing what the OP is asking. Since you think it's way off target, please edit it to get it on target. $\endgroup$
    – m_goldberg
    Commented Mar 28, 2014 at 21:25

2 Answers 2

3
$\begingroup$
rectangle[{r1_Rule, r2_Rule}] :=
     (#~Join~First@Solve[ (e1 e2 == area) /. # , 
      First@Complement[ {area, e1, e2}, First /@ #] ]) &@{r1, r2}

rectangle[{e2 -> 3, e1 -> 2}]

{e2 -> 3, e1 -> 2, area -> 6}

rectangle[{area -> 12, e1 -> 2}]

{area -> 12, e1 -> 2, e2 -> 6}

$\endgroup$
2
$\begingroup$

Update

Another variation. This one shows that basically, with the right input, the solution the OP is after is simply Solve.

ClearAll[solveMissing];
solveMissing[eqns_, knowns : {_[_Symbol, _] ...}] := 
 Solve@Flatten[{eqns, Equal @@@ knowns}]

The original examples (below) may be written without specifying all variables, as follows:

solveMissing[area == length*width, {{length, 2}, {width, 4}}]
solveMissing[area == length*width, {{area, 8}, {width, 4}}]
solveMissing[area == length*width, {{width, 4}}]
solveMissing[volume == Pi*radius^2*height, {{volume, 12 Pi}, {height, 3}}]

(*
  {{area -> 8, length -> 2, width -> 4}}
  {{area -> 8, length -> 2, width -> 4}}
  {{area -> 4 length, width -> 4}}
  { {height -> 3, radius -> -2, volume -> 12 π},
    {height -> 3, radius -> 2, volume -> 12 π}}
*)

These variations are also allowed, if not preferred:

solveMissing[area == length*width, {length -> 2, width -> 4}]
solveMissing[area == length*width, {length == 2, width == 4}]
(* {{area -> 8, length -> 2, width -> 4}} *)

Or use Solve directly:

Solve[{area == length*width, length == 2, width == 4}]
(* {{area -> 8, length -> 2, width -> 4}} *)

Note: The pattern _[_Symbol, _] allows any head (that does not evaluate to something else), even ones that don't make sense. Stricter checking might be desired in some cases. For instance, (List | Rule | Equal)[_Symbol, _].

Original answer

A variation:

solveMissing[eqn_, vars_] := Solve[
  Append[Equal @@@ Cases[vars, {_Symbol, _}], eqn],
  Replace[vars, {x_Symbol, _} :> x, 1]]

Examples:

solveMissing[area == length*width, {area, {length, 2}, {width, 4}}]
solveMissing[area == length*width, {{area, 8}, length, {width, 4}}]
(*
  {{area -> 8, length -> 2, width -> 4}}
  {{area -> 8, length -> 2, width -> 4}}
*)

solveMissing[area == length*width, {area, length, {width, 4}}]
(*
  Solve::svars: Equations may not give solutions for all "solve" variables. >>
  {{area -> 4 length, width -> 4}}
*)

solveMissing[volume == Pi * radius^2 * height, {{volume, 12 Pi}, radius, {height, 3}}]
(*
  {{volume -> 12 π, radius -> -2, height -> 3},
   {volume -> 12 π, radius -> 2, height -> 3}}
*)
$\endgroup$
2
  • $\begingroup$ I like this abstraction. Would you consider editing the question to fit this such that it might be reopened? $\endgroup$
    – Mr.Wizard
    Commented Jun 26, 2015 at 16:56
  • $\begingroup$ @Mr.Wizard Done (or attempted to do so). I have an improvement in mind, but I'll hold off until it is reopened out of some sense of fairness. Or I might completely lose track and forget about it. $\endgroup$
    – Michael E2
    Commented Jun 27, 2015 at 16:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.