2
$\begingroup$
ops = Map[Inactive, 

   Tuples[{Times, Plus, Subtract, Divide}, {4 - 1}], {2}];

rules = Thread[{a, b, c} -> #] & /@ ops;

matchQ[list_] := 

 Module[{}, 

  res = Fold[Replace[#1, List -> #2[[1]], {#2[[2]]}, Heads -> True] &,

  list, Transpose@{{a, b, c}, {1, 2, 3}}] /. rules //. 

    Inactive[Subtract][x_, y_] :> Inactive[Plus][x, -y];

  Select[res, Activate[#] == 24 &]]

list = {6, 4, 2, 3};

pattern = {{#[[1 ;; 2]], #[[3 ;; 4]]}, {#[[

 1]], {#[[2]], #[[3 ;; 4]]}}, 

    Reverse@{#[[1]], {#[[2]], #[[3 ;; 4]]}}, {{{#[[1]], #[[2]]}, #[[

  3]]}, #[[4]]}, Reverse@{{{#[[1]], #[[2]]}, #[[3]]}, #[[4]]}} &;

parts = Flatten[(pattern) /@ Permutations[list, {4}], 1];

res1 = matchQ /@ parts // Quiet // Flatten;

When I'm playing with a calculating 24, I used some function like Inactive. My question is how can I make the output more reasonble in human writing habbit? For example, here I replace Subtract with Plus.

I want to change ((6+4)+-2)*3 to ((6+4)-2)*3

StringForm is also OK, just for display

res1[[1]]

(*
    ((6+4)+-2)*3
*)

enter image description here

$\endgroup$
4
  • $\begingroup$ Is this what you're after: MakeBoxes[Inactive[Plus][x__], StandardForm] := MakeBoxes[Plus[x], StandardForm]? $\endgroup$
    – jkuczm
    May 1, 2015 at 16:37
  • $\begingroup$ @jkuczm thanks, yes, this works, ToString[res1[[1]], FormatType -> StandardForm] // ToString and this can give the string result. $\endgroup$ May 1, 2015 at 16:58
  • $\begingroup$ @jkuczm please consider posting an answer, or HyperGroups, maybe self-asnwer? $\endgroup$
    – Kuba
    Dec 7, 2015 at 13:57
  • $\begingroup$ @Kuba Answer posted, thanks for reminding me of this question. $\endgroup$
    – jkuczm
    Dec 8, 2015 at 13:50

1 Answer 1

2
$\begingroup$

You can create your own ...Form wrapper that will format inactive elements as if they where active.

Let's start with a helper function, that we'll use in a TagBox, to reinterpret expression created from active boxes, as inactive expression:

ClearAll[inactivateHead]
SetAttributes[inactivateHead, HoldAllComplete]
inactivateHead[head_[args___]] := Inactive[head][args]

Now our final activeForm wrapper, which locally overrides MakeBoxes for Inactive.

ClearAll[activeForm]
Options[activeForm] = {Editable -> True};
activeForm /: MakeBoxes[activeForm[expr_, opts : OptionsPattern[]], form_] :=
    Block[{Inactive},
        If[OptionValue[activeForm, {opts}, Editable],
            Inactive /: MakeBoxes[Inactive[head_][args___], f_] := 
                TagBox[MakeBoxes[head[args], f], inactivateHead]
        (* else *),
            Inactive /: MakeBoxes[Inactive[head_][args___], f_] := 
                InterpretationBox[#, expr] &@MakeBoxes[head[args], f]
        ];
        TagBox[MakeBoxes[expr, form], activeForm]
    ]

If you want to copy and paste output of activeForm and then edit what you pasted, set Editable option to True, then TagBox, with our inactivateHead function, will be used, to reinterpret expression from edited boxes as inactive expression, but this reinterpretation might not be completely accurate.

If you don't need to modify copy/pasted output of activeForm, you can use Editable -> False, then an uneditable InterpretationBox will be used.

To be able to convert activeForm-wrapped expressions to strings in arbitrary forms we can override ToString by setting activeForm up-values:

activeForm /: ToString[activeForm[expr_], rest___] := 
    Function[activeExpr,
        ToString[Unevaluated[activeExpr], rest],
        HoldAllComplete
    ] @@ (HoldComplete[expr] /. Inactive[x_] :> x)
activeForm /: ToString[expr_, activeForm, rest___] := 
    ToString[activeForm[expr], StandardForm, rest]

Finally add activeForm to $OutputForms:

If[FreeQ[$OutputForms, #, {1}],
    Unprotect @ $OutputForms;
    PrependTo[$OutputForms, #];
    Protect @ $OutputForms;
]& @ activeForm

An example inactive expression in StandardForm and activeForm:

tmpInactive = Inactive[Plus][Inactive[Subtract][1, 2], Inactive[Divide][6, 3], 4]
tmpInactive // activeForm

activeForm

Same expression converted to string in default OutputForm:

ToString[tmpInactive]
ToString[tmpInactive // activeForm]

ToString

in InputForm:

ToString[tmpInactive, InputForm]
ToString[tmpInactive // activeForm, InputForm]

ToString InputForm

in StandardForm:

ToString[tmpInactive, StandardForm]
ToString[tmpInactive // activeForm, StandardForm]

ToString StandardForm

and directly in activeForm which is equivalent to activeForm with StandardForm:

ToString[tmpInactive, activeForm]

ToString activeForm

All expressions given by OP (click on image to enlarge it):

res1 // activeForm

res1 activeForm

$\endgroup$

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.