Joe Riel

9660 Reputation

23 Badges

20 years, 3 days

MaplePrimes Activity


These are answers submitted by Joe Riel

This is known as Dudney's Digital Century puzzle.  Coincidentally, I included a simplified version of it as an example in the Iterator package I added to the Maple Application Center a few weeks ago.  Actually, that isn't quite accurate; the example is in an update to the package that I haven't yet uploaded.  I've been adding various features to it over the holidays.  Here is how I solved the simplified version (restricting the operators to just  addition and  multiplication, with no parentheses).

with(Iterator):

# Assign a procedure that converts a boolean Vector to the relevant
# string.

VecToStr := proc(V)
local i;
    cat("",seq('(i,`if`(V[i]=0,"+","*"))',i=1..8),"9=100")
end proc:

# Construct an iterator that steps through all 8-bit boolean Vectors,
# keeps those for which the equation is true, and returns the
# transformed string.
iter := BinaryGrayCode(8
                       , 'accept' = (V -> evalb(parse(VecToStr(V))))
                       , 'transformer' = VecToStr
                      ):
# Use the iterator to generate all the solutions.
seq(s, s=iter);
   "1*2*3*4+5+6+7*8+9=100", "1*2*3+4+5+6+7+8*9=100", "1+2+3+4+5+6+7+8*9=100"

Here's a quick extension to handle all four arithmetic operations, but without parentheses.

VecToStr := proc(V)
local i,ops;
    cat("",seq('(i,"+*/-"[V[i]+1])',i=1..8),"9=100")
end proc:

iter := MixedRadixTuples([4$8]
                         , 'accept' = (V -> evalb(parse(VecToStr(V))))
                         , 'transformer' = VecToStr
                        ):
seq(s, s=iter);
"1+2+3+4+5+6+7+8*9=100", "1+2+3-4*5+6*7+8*9=100", "1+2*3+4*5-6+7+8*9=100",
    "1+2*3*4*5/6+7+8*9=100", "1+2-3*4+5*6+7+8*9=100", "1+2-3*4-5+6*7+8*9=100",
    "1*2*3+4+5+6+7+8*9=100", "1*2*3*4+5+6+7*8+9=100", "1*2*3*4+5+6-7+8*9=100",
    "1*2*3-4*5+6*7+8*9=100", "1-2+3*4*5+6*7+8-9=100", "1-2+3*4*5-6+7*8-9=100",
    "1-2*3+4*5+6+7+8*9=100", "1-2*3-4+5*6+7+8*9=100", "1-2*3-4-5+6*7+8*9=100"

The structure you have created is a ?list, not an ?Array. Use ?numelems or ?nops to compute its length.

The conversion is correct but is for the relative temperature. Use ?convert/temperature to convert absolute temperatures.

_params can only be indexed by one element (_params['b','c'] makes no sense).  Changing _params['b','c'] to _params['b'] fixes your procedure.

There are others ways to achieve the same thing.  Here are two

f1 := proc() local x; add(x, x = args) end proc: 
f2 := proc(a:=0, b:=0, c:=0) a+b+c end proc:

The key is that you are using ?PDEtools[declare], which uses Maple's ?print facility to modify the display of the output. Fortunately, there is a simple hack to allow you to access this stuff directly.

 sprintf("%A & %A", op(eval(S,[diff=`print/diff`,`declare/display`[2][]])));

That should give you what you want. Note, however, that, in the GUI, the ampersand is displayed by itself (without the "amp;").  I'm guessing that isn't really a problem.  The string actually consists of what you want; to verify that, do lprint(%).  I'm thinking you want to send this to some other application, so that should suffice.

Addendum

I suppose some explanation would be in order.  The ?eval command is used to replace diff(x(t),t) with `x'` and x(t) with x.   The former replacement (diff(t),t) --> `x`')  is handled by replacing the diff function with `print/diff`, which returns the form used when displaying the result.  The latter replacement is handled by using the list of replacements, stored in `declare/display`[2].  It is used by PDEtools[declare] to build the replacements.

The %A format string is used in ?sprintf, rather than %a, to elide the backquotes around `x'`.

Generalization

The technique described above works, but requires some knowledge of PDEtools[declare] to figure out. Actually, my knowlege of PDEtools[declare] is minimal; I was able to quickly figure out the hackery above by using a Maple debugger. In hindsight, that wasn't necessary. That is, it is possible to achieve the same goal in a more general way.  Here is a simple procedure that replaces Maple subexpressions that with their printed equivalent.

toPrint := proc(ex)
local n,p;
    p := select(type, [anames(procedure)], 'suffixed(`print/`)');
    n := map(substring, p, 7..-1);
    eval(ex, n =~ p);
end proc:

It can be used in the above by doing

sprintf("%A & %A", op(toPrint(S)));
         "x' = y & y' = x^2"

To sort the columns, without creating a permutation Matrix, you could do

(m,n) := upperbound(M):
for j to n do
    M[..,j] := sort(M[..,j]);
end do:

Here's another approach for generating permutation lists/vectors.

 

There is a syntax error in the  large expression. I'm not sure how you want to resolve it.  The exp((.28*...   near the end is never completely closed. Removing one of the open parentheses allows Maple to solve it very quickly.

A usual method for solving this sort of problem is to use Lagrange multipliers. That avoids having to solve the constraint for one of variables. Maple provides a routine for this,

(**) V := x*y*z:                                                          
(**) L:=4*x+2*y+2*z:                                                      
(**) Student[MultivariateCalculus][LagrangeMultipliers](L,[V-32],[x,y,z]);
                  1/2              1/2            1/2
[2, 4, 4], [-1 + 3    I, -2 + 2 I 3   , -2 + 2 I 3   ],

           1/2              1/2            1/2
    [-1 - 3    I, -2 - 2 I 3   , -2 - 2 I 3   ]

It is an inert function used by some Multibody components as a flag to indicate special handling (used by the engine). In equations it is generally safe to replace it with its argument.  That is preopt(some_expr) is equivalent to some_expr.

Here is a technique I learned from a colleague.  Replace x with x/a, where a is an unassigned variable that proceeds x, lexicograhically. Apply ?normal to the result, then replace a with 1.  Thus

(**) y:=sum(x^k,k=0..infinity);
                                          1
                                 y := - -----
                                        x - 1

(**) subs(a=1, normal(subs(x=x/a,y)));                   
                                      1
                                    ------
                                    -x + 1

There is the ?RealDomain package, which might be useful.  However, it doesn't assume variables are positive, just real.  And it doesn't work with the assume facility.

Note that Maple automatically simplifies 5^(5/2) to 25*5^(1/2).

Addendum

Given the above, the most useful thing you can do is to create ``(5)^(5/2). A rather pointless one-line procedure that does that is

y := 5^2 * 5^(1/2):
map(x->`if`(x::integer,ifactor(x),`if`(x::`^`,``(op(1,x))^op(2,x),x)),y);
                                       (5/2)
                                    (5)

The blank function (``) evaluates to its argument when expanded, thus

expand(%);
                                        1/2
                                    25 5



 

Here's a different approach.

(**) y := [1,2*b] + [3,4]*(x-1)^2*3;      
                                                                    2
                                    y := [1, 2 b] + 3 [3, 4] (x - 1)

(**) evalindets(y,`*`,p->`~`[`*`](op(p)));
                                             2                2
                                   [9 (x - 1)  + 1, 12 (x - 1)  + 2 b]

expand([1,2] + [3,4]*x);
                          [3 x + 1, 4 x + 2]


Here's the idea I suggested. It uses ?ListTools[BinarySearch] to quickly search a list of "basis" vectors (here a random collection of Vectors). The basis is sorted using the same procedure (lessthan) used in the binary search.

lessthan := proc(v,w)
local i,n;
    n := upperbound(v,1);
    for i to n while v[i] = w[i] do end do;
    i<=n and v[i] < w[i];
end proc:

equal := proc(v,w)
local i,n;
    n := upperbound(v,1);
    for i to n while v[i] = w[i] do end do;
    evalb(i>n);
end proc:
     
# Generate a list of 50 random vectors with dimension 5       
L := [seq(rtable(1..5, random(1..10)), i=1..50)]:
# Use lessthan to sort the Vectors
B := sort(L,lessthan);

# Choose a member from B, and find it in B
ListTools:-BinarySearch(B, B[34], lessthan, equal);
                              34
First 35 36 37 38 39 40 41 Last Page 37 of 114