How to define a sequence with condtions on the index? - maple

I need to deal with the sequence a[i][j] with i<j, but I do not know if there exists a command to do this.
I am trying to manipulate as in the screenshot below, but it is still keeping the cases j<i.

The approach of generating the full set (i=1..n and j=1..n) and then removing the unwanted portion is unnecessarily inefficient.
Here are two more efficient ways (as well as that way using minus, but fixed to use the double-seq).
n:=4:
{seq( seq( d[i][j], j=i..n ), i=1..n )};
{d[1][1], d[1][2], d[1][3], d[1][4],
d[2][2], d[2][3], d[2][4],
d[3][3], d[3][4], d[4][4]}
{seq( seq( d[i][j], i=1..j ), j=1..n )};
{d[1][1], d[1][2], d[1][3], d[1][4],
d[2][2], d[2][3], d[2][4],
d[3][3], d[3][4], d[4][4]}
# The next is less efficient
{seq( seq( d[i][j], j=1..n ), i=1..n )}
minus {seq( seq( d[i][j], j=1..i-1 ), i=1..n )};
{d[1][1], d[1][2], d[1][3], d[1][4],
d[2][2], d[2][3], d[2][4],
d[3][3], d[3][4], d[4][4]}

For this question, I would go with the first method in #acer's answer. But just in case, if the condition on the indices were a bit complicated such that you could not quickly come up with an easy formulation that can be used to create your indices in the 1st method in that answer or to write as set minus of two indices set etc. then you can use the select command in Maple and the original condition that you have as a boolean function. Here is how it would work in your case.
n := 4:
idxs := select( pair -> pair[1] < pair[2], [ seq( seq( [i, j], j = 1..n ), i = 1..n ) ] );
You knew how to generate all [i, j]'s with no restriction, the second argument of the select command above. And your condition on them is; if you pick up a pair, its 1st element being less than its 2nd element. So we wrote the 1st argument of select above which is a boolean function, for each pair, if the condition holds, it returns true otherwise returns false. The select command picks up the elements of its 2nd arguments that give true under the function in its 1st argument. Now that you have the list of indices, you can use a single seq to use them.
{ seq( d[ pair[1] ][ pair[2] ], pair in idxs ) };
Here is the screenshot of the outputs.

Related

Print the hash elements by grouping their values in Raku

I keep record of how many times a letter occur in a word e.g. 'embeddedss'
my %x := {e => 3, m => 1, b => 1, d => 3, s => 2};
I'd like to print the elements by grouping their values like this:
# e and d 3 times
# m and b 1 times
# s 2 times
How to do it practically i.e. without constructing loops (if there is any)?
Optional Before printing the hash, I'd like to convert and assing it to a temporary data structure such as ( <3 e d>, <1 m b>, <2 s> ) and then print it. What could be the most practical data structure and way to print it?
Using .categorize as suggested in the comments, you can group them together based on the value.
%x.categorize(*.value)
This produces a Hash, with the keys being the value used for categorization, and the values being Pairs from your original Hash ($x). This can be looped over using for or .map. The letters you originally counted are the key of the Pairs, which can be neatly extracted using .map.
for %x.categorize(*.value) {
say "{$_.value.map(*.key).join(' and ')} {$_.key} times";
}
Optionally, you can also sort the List by occurrences using .sort. This will sort the lowest number first, but adding a simple .reverse will make the highest value come first.
for %x.categorize(*.value).sort.reverse {
say "{$_.value.map(*.key).join(' and ')} {$_.key} times";
}

Minizinc: declare explicit set in decision variable

I'm trying to implement the 'Sport Scheduling Problem' (with a Round-Robin approach to break symmetries). The actual problem is of no importance. I simply want to declare the value at x[1,1] to be the set {1,2} and base the sets in the same column upon the first set. This is modelled as in the code below. The output is included in a screenshot below it. The problem is that the first set is not printed as a set but rather some sort of range while the values at x[2,1] and x[3,1] are indeed printed as sets and x[4,1] again as a range. Why is this? I assume that in the declaration of x that set of 1..n is treated as an integer but if it is not, how to declare it as integers?
EDIT: ONLY the first column of the output is of importance.
int: n = 8;
int: nw = n-1;
int: np = n div 2;
array[1..np, 1..nw] of var set of 1..n: x;
% BEGIN FIX FIRST WEEK $
constraint(
x[1,1] = {1, 2}
);
constraint(
forall(t in 2..np) (x[t,1] = {t+1, n+2-t} )
);
solve satisfy;
output[
"\(x[p,w])" ++ if w == nw then "\n" else "\t" endif | p in 1..np, w in 1..nw
]
Backend solver: Gecode
(Here's a summarize of my comments above.)
The range syntax is simply a shorthand for contiguous values in a set: 1..8 is a shorthand of the set {1,2,3,4,5,6,7,8}, and 5..6 is a shorthand for the set {5,6}.
The reason for this shorthand is probably since it's often - and arguably - easier to read the shorthand version than the full list, especially if it's a long list of integers, e.g. 1..1024. It also save space in the output of solutions.
For the two set versions, e.g. {1,2}, this explicit enumeration might be clearer to read than 1..2, though I tend to prefer the shorthand version in all cases.

Multiple commands in one, Matlab

Sometimes it is desired to make several calls in one command. A simple example could be strrep. Assume you want to replace all parentheses with brackets, all commas with dots and then remove all double quotations. The following pseudo code could then be desired:
strrep(myString, '()', '[]', ',', '.', '"', '')
Is there any way to accomplish this? You could of course go with:
strrep(strrep(strrep(myString, '()', '[]'), ',', '.'), '"', '')
Or save the strings in a cell array and use this in a for loop, but both solutions are incredibly ugly.
The most desired answer, is one that is generic for all functions that work in a similar way.
To directly answer your question, there is really no consistent way of doing this, no. It really depends on the function. If you search the documentation you will often find a way to do this. With strings, at least, you can usually pass cell arrays in place of strings to perform operations on multiple strings, and in this case multiple operations on the same string.
A Solution for This Particular Example
You can easily use regexprep to do this for you. You can pass a cell array of the expressions to match with a corresponding cell array of the replacement values.
regexprep('abc', {'a', 'b', 'c'}, {'1', '2', '3'});
%// '123'
For your specific example, you would do something like:
regexprep(myString, {'\(\)', ',', '"'}, {'[]', '.', ''})
And as an example:
myString = 'This, is a () "string"';
regexprep(myString, {'\(\)', ',', '"'}, {'[]', '.', ''})
%// 'This. is a [] string'
If you don't want to worry about escaping all of the expressions to be regex-compatible, you can use regexptranslate to do that for you.
expressions = regexptranslate('escape', {'()', ',', '"'});
regexprep(myString, expressions, {'[]', '.', ''});
Say you want function foo to work like this:
foo(Variable,Parameter1,Value1);
foo(Variable,Parameter1_1,Value1,Parameter2,Value2,...);
then using recursion:
function[Variable]=FooBar(Variable,varargin)
N=nargin-1; %\\ Count the input parameters
if N>=2
Parameter=varargin{1};
Value=varargin{2};
% Process the first Parameter-value pair
Variable=FooBar(Variable,varargin{3:N}); %\\ Cut first Parameter-Value pair off and pass the rest to foo again
end
This approach allows you to use chain of single parameters, pairs, triplets, quadruplets, etc.
In this perticullar example the pairs are executed as LIFO stack and last unpaired Parameter is ignored. You can also add some conditions to implement foo(IN,Parameter1,Value1,Modifier,Parameter2,Value2,...) and many other properties...
For your perticullar example:
function[MyString]=FooBar(MyString,varargin)
N=nargin-1; %\\ Count the input parameters
if N>=2
Parameter=varargin{1};
Value=varargin{2};
MyString=regexprep(MyString,Parameter,Value)
MyString=FooBar(MyString,varargin{3:N});%\\ Cut first Parameter-Value pair off and pass the rest to foo again
end
Examples:
>> myString='This, is a () "string"';
FooBar(myString,'()','[]','"','',',','.')
ans = This. is a [] string
>> myString='This, is a ("string")';
FooBar(myString,'()','[]','"','',',','.')
ans = This. is a (string)
>> myString='This, is a ("string")';
FooBar(myString,'(','[',')',']','"','',',','.')
ans = This. is a [string]
As already said by #Suever your example can be solved by regexprep and #thewaywewalk has hinted that there is no "general" soluction for all function calls.
Note I do not advocate this as a good way to code -> but its a quirky question and thus here is a suitable quirky solution....
There is lots of reason why you shouldn't do this - namely a nightmare to debug but you could in theory do this with an "intelligent" self calling function...
% Create your own function which takes the following inputs:
% fHandle - function handle to the function of choice
% property - your starting variable
% varargin - a cell array (or single var) of variables to
% pass into the fHandle on each call
% see examples below...
function output = multipleCalls ( fHandle, property, varargin )
% call your primary function using feval and your inputs
% with the 1st group of inputs from the 1st varargin
if iscell ( varargin{1} )
output = feval ( fHandle, property, varargin{1}{:} );
else
output = feval ( fHandle, property, varargin{1} );
end
% remove the varargin variable which has just been used.
varargin(1) = [];
% are they aremore multiple call?
if ~isempty ( varargin )
% if so self call to apply the subsequent calls.
output = multipleCalls ( fHandle, output, varargin{:} );
end
end
% modifying your example to use this method:
multipleCalls( #strrep, 'This, is a () "string"', { '()', '[]' }, { ',', '.' }, { '"', '' } )
% Its probably a longer command and is it any clearer -> probably not...
% Here is another example:
% Create a silly anonymous function
sillyFunction = #(a,b) a + b
% Then you can use it in the same way:
% Where 0 is what you start with and then
% each time you want to add 1, then 2, then 3 and finally 4
multipleCalls ( sillyFunction, 0, 1, 2, 3, 4 )

Assuming many variables at once

I'm trying to set up the following constraints:
assume(E1A::integer,E2A::integer,...,E2B::integer,...,E3C::integer)
additionally(E1A>=0,E2A>=0,...,E3C>=0)
additionally(E1A<=3,E2A<=3,...,E3C<=3)
is there any way to do this without typing out all the terms E1A, E2A,...,E3C? I tried doing
for i from 0 to 3 do (assume(EiA::integer)) end do
as a shortcut, but Maple didn't like that, presumably because it didn't view the i as an indexing variable.
You can form names by concatenation.
restart:
assume( seq( cat(`E`,i,`A`)::integer, i=1..3 ) );
And now, to test,
[ seq( cat(`E`,i,`A`), i=1..3 ) ]:
map( about, % ):
Originally E1A, renamed E1A~:
is assumed to be: integer
Originally E2A, renamed E2A~:
is assumed to be: integer
Originally E3A, renamed E3A~:
is assumed to be: integer
You can also nest seq, eg,
restart:
assume( seq( seq( cat(`E`,i,abc)::integer, i=1..3), abc=[A,B,C] ) );
[ seq( seq( cat(`E`,i,abc), i=1..3), abc=[A,B,C] ) ]:
map( about, % ):
With the elementwise operator and the concatenation operator you can get all your assuming down to one line:
assume(E||(1..3)||A ::~ AndProp(integer, RealRange(0,3)));

Removing specific elements from matrix

I want to remove a (*) asterisk from my matrix and write out that matrix to a text file and the remaining elements will be concatenated to each other without a space or any kind of delimiters. I wrote this code
for b = 1 : length(out7num_r7_nt_back)
if ~(out7num_r7_nt_back(b) == '*')
out7num_r7_back(b) = '';
end
end
disp(out7num_r7_nt_back);
dlmwrite('my_data.txt',out7num_r7_nt_back, '');
I got this error message:
??? Index of element to remove exceeds matrix dimensions.
You can use a vectorized boolean index, replacing the loop as follows:
out7num_r7_nt_back = out7num_r7_nt_back(out7num_r7_nt_back(b) ~= '*');
That should be much faster as well.
Value of upper bound of for loop (length(out7num_r7_nt_back)) gets evaluated only once!
Say you have '*ab' in a variable. Loop will count to 3 (length of variable). Inside the loop when program erases '*', you'll get 'ab' which is of length 2. Since loop is iterating to 3, program will try to access out7num_r7_nt_back(3) which is out of bounds.
You could remove characters while going backwards:
...
for b = length(out7num_r7_nt_back) : -1 : 1
...
But you should prefer vectorized approach because it's faster and cleaner to write.