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

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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