11
$\begingroup$

I'm trying to achieve something similar to Bret Victor's brilliant Scrubbing Calculator in Mathematica.

By using Manipulate I'd like to change the values of the variables such that if I modify one the others adapt to ensure the equation is always true.

In the example below I'd like to be able to move spaces and have boxes change accordingly.

Manipulate[4 spaces + 3 boxes = 640, {spaces, 0, 640}, {boxes, 0, 640}]

The simplest case

Solving for the two variables explicitly I can achieve the desired effect but doing so kind of voids the idea of an intuitive calculator.

Manipulate[{Dynamic[spaces = 160 - (3 boxes)/4], 
  Dynamic[boxes = -(4/3) (spaces - 160)]}, {boxes, 0, 640}, {spaces, 
  0, 640}]

The hard way

Now, kind Mathematicans, my question is this:

Is there a way of doing this the first, more intuitive, way?

$\endgroup$
3
  • 1
    $\begingroup$ Could you please post copiable code so that whoever wants to give solutions can easily do that? $\endgroup$ Commented Apr 13, 2012 at 15:55
  • $\begingroup$ Ok, you've added it. thanks. $\endgroup$ Commented Apr 13, 2012 at 16:25
  • $\begingroup$ Related: mathematica.stackexchange.com/questions/1373/… $\endgroup$
    – Mr.Wizard
    Commented Sep 14, 2012 at 9:06

1 Answer 1

2
$\begingroup$

Well, I have needed before to link variables within a manipulate object, and I always get complicated dynamic things, for your example if you want to add constraints to your variables, you could come up with something like this:

Module[{spaces, boxes, lastboxes, lastspaces, condition, solvebox, 
  solvespace},
 condition[s_, b_] := 4 s + 3 b == 640;
 solvebox[s_] := b /. First[Solve[condition[s, b], b]];
 solvespace[b_] := s /. First[Solve[condition[s, b], s]];
 lastboxes = 100;
 lastspaces = solvespace[lastboxes];
 Manipulate[{spaces, boxes}, 
  Control[{{boxes, lastboxes, "Boxes"}, 0, 640}], 
  Control[{{spaces, lastspaces, "Spaces"}, 0, 640}], 
  Dynamic[If[! condition[spaces, boxes], 
    If[lastboxes === boxes, 
      With[{newbox = solvebox[spaces]}, 
       If[newbox < 0, spaces = solvespace[boxes], lastboxes = boxes; 
        boxes = solvebox[spaces]]], 
      With[{newspaces = solvespace[boxes]}, 
       If[newspaces < 0, boxes = lastboxes, lastboxes = boxes; 
        spaces = newspaces]]];]; ""], ControlPlacement -> Left, 
  Deployed -> True]
 ]

That Dynamic after Control objects comes pretty good to do that stuff, but does your code become bigger.

$\endgroup$
1
  • $\begingroup$ Thank you for your answer. This does indeed achieve the same result, but doesn't quite manage to do so in a simpler, more intuitive way. It is quite possible that what I'm asking is not possible in Mathematica. $\endgroup$ Commented Apr 14, 2012 at 8:41

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.