MapleMathMatt

477 Reputation

9 Badges

6 years, 279 days

MaplePrimes Activity


These are answers submitted by MapleMathMatt

You can use programmer indexing (e.g. A(3,2) := 0) when before A only had 2 rows) to grow a Matrix (or other rtable) in-place. In this code, I take some care to ensure there is no clashing of datatype and fill value:

GrowRtable := proc( A :: rtable, U :: list( nonnegint ), x :: anything := 0, $ )
    local dt, V, W, y;
    V := map( rhs - lhs + 1, [ rtable_dims( A ) ] );
    W := U -~ V;
    dt := rtable_options( A, 'datatype' );
    if min( W ) < 0 or max( W ) <= 0 then
        error "expecting rtable to grow in one or more dimensions and not shrink in any dimension";
    elif not x :: dt then
        error "expecting fill value to be of datatype %1", dt;
    end if;
    y := rtable_options( A, 'fill' );
    rtable_options( A, 'fill' = x );
    A( seq( U ) ) := x;
    rtable_options( A, 'fill' = y );
    return A;
end proc;

# Example
A := Matrix( [[1,2],[3,4]], 'datatype' = 'posint' );
GrowRtable( A, [2, 3], 5 );
A;

@jasser

Note that Maple 2023 has such a command for this purpose, ArrayTools:-IsSubsequence. It is designed for arrays, but supports lists, too.

Another approach, which uses arrays and the member command:

IsSubsequence := proc( A :: list, B :: list, $ )
    local AA, BB, C, i, j, m, n;
    AA := Array( A );
    BB := Array( B );
    m := numelems( AA );
    n := numelems( BB );
    C := BB;
    for i from 1 to m do
        if not member( AA[i], C, 'j' ) then
            return false;
        else
            C := ArrayTools:-Alias( BB, j, [ j + 1 .. n ] );
        end if;
    end do;
    return true;
end proc;

IsSubsequence( [7,2,4], [2,6,5,7,3,2,9,4] ); # true
IsSubsequence( [7,2,6], [2,6,5,7,3,2,9,4] ); # false

Note: Correction made to the indices used in the alias.

Does this work for you? Note that if there are repeats in the common digits, all of them are removed.

GetDigits := proc( p :: posint, $ )
    local A, q, r;
    A := Array( 1 .. 0 );
    q := p;
    while q > 0 do
        q := iquo( q, 10, 'r' );
        A ,= r;
    end do;
    ArrayTools:-Reverse( A, 'inplace' );
    A := convert( A, 'list' );
    return A;
end proc;

CombineDigits := proc( A :: list( nonnegint ), $ )
    local i, n;
    n := numelems( A );
    return add( 10^(n-i) * A[i], i = 1 .. n );
end proc;

FilterNumbers := proc( p :: posint, q :: posint, $ )
    local A, B, C, pp, qq:
    A := GetDigits( p );
    B := GetDigits( q );
    ( C, A ) := selectremove( member, A, B );
    B := remove( member, B, C );
    pp := CombineDigits( A );
    qq := CombineDigits( B );
    return ( pp, qq );
end proc;

# Example.
GetDigits( 2345 ); # [2,3,4,5]
CombineDigits( [2,3,4,5] ); # 2345
FilterNumbers( 2345, 1536 ); # 24, 16

Hi @JAMET,

You can use Calendar:-DayOfWeek:

DaysOfWeek := table( [
    "Sunday" = 1,
    "Monday" = 2,
    "Tuesday" = 3,
    "Wednesday" = 4,
    "Thursday" = 5,
    "Friday" = 6,
    "Saturday" = 7
] );

FridayThe13ths := proc( year :: posint, $ )
    local A, B, C, day, month, num_months;
    day := 13;
    num_months := 12;
    A := [ seq( Date( year, month, day ), month = 1 .. num_months ) ];
    B := select( date -> Calendar:-DayOfWeek( date ) = DaysOfWeek[ "Friday" ], A );
    C := map( Calendar:-VariantFormat, B, "%A, %B %d, %Y" );
    return C;
end proc;

FridayThe13ths( 2023 ); # [ "Friday, January 13, 2023", "Friday, October 13, 2023" ]

 

Hi @quoteswindy0,

There seems to be a bug with the 2-D Math input. If you either add an explicit multiplication before the piecewise, or remove the added condition (which is not necessary), then there won't be an error.

Hi @John2020, the intsolve command doesn't work here, directly anyway, because of the derivative and second variable. To use intsolve with the Laplace transform, you can perform a change of variables and specify the method as an option:

fde := fracdiff( u(x,t), t, 1/2 ) = t^(1/2) * sin(x) / GAMMA(3/2);
ie := subs( diff( u(x,tau), tau ) = v(tau), fde );
pde := eval( intsolve( ie, v(t), 'method' = 'Laplace' ), v(t) = diff( u(x,t), t ) );
sol := pdsolve( pde, u(x,t) ); # u(x,t) = sin(t) * t + _F1(x)

Here, _F1(x) is an arbitrary function of x, which you have taken to be zero.

Hi @kiraMou,

I think the main issue is that the areas need to be cumulative, that is each element of area you compute with the trapezoid rule needs to be added to the previous value. Within IntNum, you should have this:

xvi[i] := xvi[i-1] + evalf( ( ( a[i] - a[i-1] ) * ( c[i] + c[i-1] ) ) / 2 );

Here's a variation:

# Create the data for the time and velocity vectors.
v := sin; # velocity
a, b := -Pi, Pi; # time endpoints
n := 1000; # number of points
dt := evalf((b-a)/(n-1)); # time step
T := Vector( n, i -> evalf(a+(i-1)*dt) ); # time data
V := map( v, T ); # velocity data

# Create the displacement vector using the trapezoid rule.
alpha := 0; # initial displacement
X := Vector( n, i -> datatype = float[8] ):
X[1] := alpha;
for i from 2 to n do
  X[i] := X[i-1] + 0.5 * (T[i]-T[i-1]) * (V[i]+V[i-1]);
end do:
'X' = X;

# Data plot.
dataplot( T, [V,X], style = line, legend = [velocity,displacement], color = [red,blue], title = "Discrete Velocity and Displacement" );

# Compare with continuous version.
x := unapply( alpha + int( v(s), s = a .. t ), t );
plot( [ v, x ], a .. b, legend = [velocity,displacement], color = [red,blue], title = "Continuous Velocity and Displacement" );

 

 

 

Hi @mapleatha,

You could edit the typesetting to include colour. First, note the elements present for sin(x), namely mfenced, mi, and mo:

a := Typesetting:-Typeset( sin(x) );
lprint( a ); # Typesetting:-mrow(Typesetting:-mi("sin",fontstyle = "normal"),Typesetting:-mo("&ApplyFunction;"),Typesetting:-mfenced(Typesetting:-mi("x")))

Now, create a custom procedure to add options to these specific elements:

ChangeOptions := proc( a )
  local F := { Typesetting:-mfenced, Typesetting:-mi, Typesetting:-mo };
  local R := _rest;
  return subsindets( a, 'specfunc'( F ), u -> op(0,u)( op(u), R ) );
end proc;

Finally, create a plot:

a := ChangeOptions( Typesetting:-Typeset( sin(x) ), "color" = "red", "size" = 20 );
plot( sin(x), x = 0 .. 2 * Pi, title = typeset( "Plot of %1", a ) );

 

 

Hi @daljit97,

I had hoped that

isolve( y^2 * z + y * z^2 = x^2 );

would work, but it didn't find any solutions.

There may well be quicker and more direct ways, but I tried these two programmatic methods, and they found solutions.

One: Find and test all possible [x,y,z]:

restart;

# Equation to be solved.
f := y^2 * z + y * z^2 = x^2;

# Variables in equation, {x,y,z}.
U := indets( f, 'name' );

# Values the variables can take.
V := [0,1];

# Create a list of all possible [x,y,z] values.
W := [ seq( seq( seq( [x,y,z], x = V ), y = V ), z = V ) ];

# Adjust W so that it is a list of terms of the form [x=a,y=b,z=c].
W := map( w -> U =~ w, W );

# Select the elements of W at which the equation is satisfied.
S := select( w -> eval( f, w ), W );

Note that another way of determining a list of all possible [x,y,z] values is to use a Cartesian product iterator:

T := combinat:-cartprod( [ seq( V, 1 .. numelems(U) ) ] );
W := [ while not T['finished'] do T['nextvalue']() end do ];

Two: Use SMTLIB:-Satisfy() to find individual solutions:

restart;

# Equation to be solved.
f := y^2 * z + y * z^2 = x^2;

# Equation to be solved, along with restrictions on the variables.
g := And( f, Or(x=0,x=1), Or(y=0,y=1), Or(z=0,z=1) );

# Initialize list of solutions.
S := [];

# Use SMTLIB:-Satisfy() to find solutions. When a solution is found, 
# add a condition to g to exclude this solution in future rounds.
do
  T := SMTLIB:-Satisfy( g );
  if T = () then
    break;
  else
    S := [ seq(S), T ];
    g := And( g, Not(T) );
  end if;
end do;

# All solutions found.
'S' = S;

 

Hi @Anthrazit,

You can use the indices command in conjuction with member:

L[ "hello" ] := "funny";
L[ "hi" ] := "not funny";

K := [ indices( L, 'nolist' ) ]; # [ "hi", "hello" ]
member( "hello", K ); # true
member( "goodbye", K ); # false

Maple 2020 introduced the hasindex command, which is more direct:

hasindex( L, "hello" ); # true
hasindex( L, "goodbye" ); # false

 

 

Hi @Anthrazit,

The condition in an "if-statement" is not simplified, like in a call to evalb(). I suggest using the verify() command, which supports units:

a := 15 * Unit( MPa );
b := 16 * Unit( N / mm^2 );
verify( a, b, units( less_than ) ); # true

Hi @MapleUser2017,

Here are a couple of options:

# Original list.
L := [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];

# Split L into pairs, i.e. [ [1,2], [3,4], ... ], and then create the ranges from the pairs.
L1 := map( `..`@op, [ ListTools:-LengthSplit( L, 2 ) ] );

# Split L into two lists, for odd and even elements, and then use zip() to create the ranges.
L2 := zip( `..`, selectremove( type, L, odd ) );

Note that the first applies to any list of even length, whereas the first takes advantage of the specific values.

Hi @wagaren ,

Another way would be to set the original expression to the desired form with undetermined coefficients, and then solve the identity for the constants:

f := cos(t)^6;
g := add( a[k] * cos(2*k*t), k = 0 .. 3 );
S := solve( identity( f = g, t ) );
h := eval( g, S );

Hi @meatboi ,

If you define a procedure for a numeric integral, you can get the plot:

G := proc( epsilon )
  int( exp( -epsilon * ( x^4 + x^2 ) ), x = -10 .. 10, numeric );
end proc:
plot( G, 0 .. infinity );

 

Assuming you're using Maple 2018, you could try the SMTLIB:-Satisfy() command. By converting the equations to a boolean expression, the retriction that a certain number of terms be 1 can be written as a condition on the sum of all the terms. For instance:

# equations/inequalities
E := [
    abs( x[1] * x[2] * x[3] ) <= 1,
    x[4] * x[5] * x[6] = 0,
    x[1] * x[4] + x[2] * x[5] + x[3] * x[6] = 1
];

# variables
V := indets( E, name );

# convert to boolean expression
f := &and( op(E), seq( &or( v=0, v=1 ), v=V ) );

# solution with two non-zero terms
SMTLIB:-Satisfy( f );

# solution with three non-zero terms
g := &and( f, add(V) > 2 );
SMTLIB:-Satisfy( g );
1 2 3 Page 1 of 3