I test the code
L:=[2,1];
sum('a||b*L[1]', 'b' = 1 .. 2);
It returns a1*L[1]+a2*L[1], but I expect to get a1*2+a2*2 after evaluation of L[1].
Any ideas?
Thanks.
EDIT:
I have one further question. Here's the test code:
L := [2, 1]
test := proc (i) local a1; a1 := 1; add(a || b*L[i], b = 1 .. 2) end proc
test(1);
will result
2 a1 + 2 a2
without evaluating a1 which is a local variable defined in function test.
I expect to get 2*1+2*a2. Any further idea?
Your first line is just an equation, with =, and not an actual assignment with :=. So you weren't doing an assignment to L.
And the uneval quotes are misapplied, in the sum call, and wrap too much.
You could also use add instead of sum, to rely on the special evaluation rules of add and thus get rid of the need for the uneval quotes.
> L:=[2,1];
L := [2, 1]
> add(cat(a,b)*L[1], b = 1 .. 2);
2 a1 + 2 a2
> add((a||b)*L[1], b = 1 .. 2);
2 a1 + 2 a2
> sum('a||b'*L[1], 'b' = 1 .. 2);
2 a1 + 2 a2
> sum('cat(a,b)'*L[1], 'b' = 1 .. 2);
2 a1 + 2 a2
Related
can comeone help to understand in MAtlab this:
k=2
n = (0:-1:-4)+k
the result; 2 1 0 -1 -2
how it works?
You are dealing with a colon operator and a vectorized sum at the same time. Let's split the problem into smaller, stand-alone problems:
In Matlab, if you add or subtract between a scalar value to a matrix, the arithmetic operation is performed on all the elements of the matrix, in a vectorized way. Example:
A = [1 2; 3 4]; % 2-by-2 matrix
S1 = A + 2 % output: S1 = [3 4; 5 6]
B = [1 2 3 4] % 1-by-5 matrix, also called column vector
S2 = B - 5 % output: S2 = [3 4 5 6]
The column operator in Matlab can be used in many situation: indexing, for iterations and vector creation. In your case, its purpose is the third one and it's syntax is START(:STEP):END. The default STEP, if not specified, is 1. The START and END parameters are never exceeded. Example:
A = 1:5 % output: A = [1 2 3 4 5]
B = -2.5:2.5:6 % output: B = [-2.5 0 2.5 5]
C = 1:-1:-5 % output: C = [1 0 -1 -2 -3 -4 -5]
D = -4:-2:0 % output: D = []
In all the programming languages, an operator precedence criterion is defined so that a one-liner calculation that uses multiple operators is atomized into smaller calculations that respect the given priority, unless parentheses are used to redefine the default criterion... just like in common maths. Example
A = 2 * 5 + 3 % output: A = 13
B = 2 * (5 + 3) % output: B = 16
Let's put all this together to provide you an explaination:
n = (0:-1:-4) + k
% vector creation has parentheses, so it's executed first
% then, the addition is executed on the result of the first operation
Let's subdivide the calculation into intermediate steps:
n_1 = 0:-1:-4 % output: n_1 = [0 -1 -2 -3 -4]
n_2 = n_1 + k % output: n_2 = [2 1 0 -1 -2]
n = n_2
Want to see what happens without parentheses?
n = 0:-1:-4+k % output: n = [0 -1 -2]
Why? Because the addition has priority over the colon operator. It's like writing n = 0:-1:(-4+k) and adding k to the END parameter of the colon operator. Let's subdivide the calculation into intermediate steps:
n_1 = -4 + k % output: n_1 = -2
n_2 = 0:-1:n_1 % output: n_2 = [0 -1 -2]
n = n_2
Basic Matlab syntax, you're dealing with range operators. There are two patterns:
[start]:[end]
and
[start]:[step]:[end]
Patterns like this result in arrays / vectors / "1D matrices".
In your example, you will get a vector first, stepping through the numbers 0 to -4 (step == -1). Then, you are adding k == 2 to all numbers in this vector.
octave:1> k = 2
k = 2
octave:2> n = (0:-1:-4)+k
n =
2 1 0 -1 -2
octave:3> 0:-1:-4
ans =
0 -1 -2 -3 -4
The parenthesizes expression determines an array. The the first number there is the first element, the second is the step and the last one is the last element. So the parenthesizes returns 0 -1 -2 -3 -4. Next we add k=2 to each element that results in 2 1 0 -1 -2
I have a vector of integers and I want to convert it into one number.For example:
h = [1 2 4 3]; % after conversion res= 1243
k = [ 0 0 0 0]; % after conversion res=0000
l = [0 0 2 1]; % after conversion res=0021
I tried to use this method
b = [1 2 4 3];
res= str2num(strrep(num2str(b'), ' ', ''))
This method works fine when there is no zeros at start or end of the vector. But when there is zeros at end or start, str2num is removing them. For example, for vector k, res=0. For vector l, res=21.
How can I keep the zeros at the start and end?
At least for Octave, you can use a vectorized sprintf to print each array element into a string.
>> a = sprintf('%d', [0 0 1 2 3 4 0 0])
a = 00123400
very likely the same code would work too for MATLAB. Unfortunately I can't test it right now.
The easiest certainly is to convert your numbers directly to characters by offsetting them according to the ASCII-character table with 48:
char(h + 48)
char(k + 48)
char(l + 48)
If your input is a matrix (what I'd recommend) you additionally need to cellstr to convert the character matrix to a cell array of strings:
h(1,:) = [1 2 4 3];
h(2,:) = [0 0 0 0];
h(3,:) = [0 0 2 1];
out = cellstr( char(h + 48) )
You can make use of num2str() and regular expressions, regexprep(), to achieve the result.
s1 = num2str(h)
s2 = num2str(k)
s3 = num2str(l)
The array is directly converted into a string and results in the following output.
s1 = 1 2 4 3
s2 = 0 0 0 0
s3 = 0 0 2 1
Now, we can use regular expressions to find white spaces and replace it with ''
s1 = regexprep(s1,'\s+', '')
s2 = regexprep(s2,'\s+', '')
s3 = regexprep(s3,'\s+', '')
This produces the following result.
s1 = 1243
s2 = 0000
s3 = 0021
In 16b you can use the new string class. The string constructor will convert the numeric array to a string array of the same dimensions. Join will concatenate the elements together.
>> b = [1 2 4 3];
>> string(b).join('')
ans =
string
"1243"
h = [1 2 4 3];
k = [0 0 0 0];
l = [0 0 2 1];
strrep(num2str(h), ' ', ''); % this will return '1234'
strrep(num2str(k), ' ', ''); % this will return '0000'
strrep(num2str(l), ' ', ''); % this will return '0021'
I have the following array: A = [2 7 8 9 10] and I'm looking for a way to group its subsequent elements, so to get a result like B = [1 2; 4 7], where the first column returns the number of subsequent elements, and the second the value of the first element.
How do you suggest to approach the problem?
Try this:
idx = find([[0 diff(A)] ~= 1 1]);
B = [diff(idx); A(idx(1:end-1))].';
The logic is this:
You're interested to know when a subsequent sequence starts. You could use the diff function to calculate the difference between each element and the previous one, like this:
>> A = [2 7 8 9 10]
>> diff(A)
ans =
5 1 1 1
We want to focus on values different than 1 (because they are within a sequence). The 5, in this case, represents the start of the 7,8,9,10 sequence. Also, the first element always start a sequence. We may "force" this by adding a 0 to the response, like this:
>> [0 diff(A)]
ans =
0 5 1 1 1
Now, we need to get the numbers different than 1:
>> [0 diff(A)] ~= 1
ans =
1 1 0 0 0
As we want to know the length of the sequence, it would be interesting to know the end of the last sequence. For that, we add a 1 in the end:
>> [[0 diff(A)] ~= 1 1]
ans =
1 1 0 0 0 1
Now we use find to get the indexes of the 1's:
>> idx = find([[0 diff(A)] ~= 1 1])
ans =
1 2 6
It tells us we have two sequences: the first one starts on 1 and ranges from 1..2-1, and the second one starts on 2 and ranges from 2..6-1. If we do a diff of idx, we get the lenghts:
>> diff(idx)
ans =
1 4
To get the values, we index A using idx (ignoring the last value):
>> A(idx(1:end-1))
ans =
2 7
The last line just combines this into a row matrix, and transposes it:
>> B = [diff(idx); A(idx(1:end-1))].'
ans =
1 2
4 7
What's the idiomatic way to detect sequences of x times the same object (or an object with a specific matching parameter) in an OrderedCollection or Array?
E.g. does the Array contain 10 times the number 5 in a row?
I like Uko's answer and would like to provide a different solution which addresses the "matching parameter" part of your question. In SequenceableCollectiondefine:
contains: m consecutiveElementsSatisfying: block
| n i |
self isEmpty ifTrue: [^m = 0].
n := self size - m + 1.
i := 1.
[i <= n] whileTrue: [| j |
(block value: (self at: i)) ifTrue: [
j := 2.
[j <= m and: [block value: (self at: i + j - 1)]]
whileTrue: [j := j + 1].
j > m ifTrue: [^true]].
i := i + 1].
^false
Now, for example the two following expressions would evaluate to true
#(2 1 1 1 2) contains: 3 consecutiveElementsSatisfying: [:e | e = 1]
#(2 1 0 1 2) contains: 3 consecutiveElementsSatisfying: [:e | e squared = e]
Note: If you want the startingAt: n version of this method just initialize i := n instead of i := 1 just before the main loop.
EDIT:
And, of course, we can complete the protocol with the following method in SequenceableCollection:
contains: m consecutiveTimes: anObject
^self contains: m consecutiveElementsSatisfying: [:e | e = anObject]
And the example:
#(2 1 1 1 2) contains: 3 consecutiveTimes: 1
Getting the sequences of repeating objects is as simple as:
({ 1. 1. 2. 2. 2. 5. 5. 3. 9. 9. 9. 9. } as: RunArray) runs
=> #(2 3 2 1 4)
If you want to test if there is a run satisfying specific constraints, you can do something like the following:
meetsConstraint := false.
({ 1. 1. 2. 2. 2. 5. 5. 3. 9. 9. 9. 9. } as: RunArray) runsAndValuesDo: [:run :value |
meetsConstraint := (value = 9 and: [run > 3])].
If you want to test for a certain property of an object instead of object equality, you can easily create a RunArray of this property by doing a collect: on it.
So the generalized solution would look something like this:
SequenceableCollection >> containsRunOf: anElement withAtLeast: nElements
(self as: RunArray) runsAndValuesDo: [:run :value |
(value = anElement and: [run >= nElements]) ifTrue: [^ true]].
^ false
And then:
({ 'aa'. 'bb'. 'c'. 'ddd'. } collect: [:each | each size])
containsRunOf: 2 withAtLeast: 3
=> false
I'd say that you have to follow a pattern like this:
(collectionToTest
indexOfSubCollection: (
Array
new: numberOfRepetitions
withAll: desiredObject)
startingAt: 1
) isZero not
Maybe I don't know some of useful methods in Pharo, but if you define the ones like:
SequenceableCollection >> indexOfSubCollection: aSubCollection
^ aSubCollection indexOfSubCollection: aSubCollection startingAt: 0
SequenceableCollection >> containsSubCollection: aSubCollection
^ (aSubCollection indexOfSubCollection: aSubCollection) isZero not
Object >> asArrayOf: aLength
^ Array new: aLength withAll: self
then the definition can be flattened into:
collectionToTest containsSubCollection:
(desiredObject asArrayOf: numberOfRepetitions)
or for your example:
anArray containsSubCollection: (5 asArrayOf: 10)
P.S. I'm not sure about the method names. Maybe inArrayOf: can be better then asArrayOf: and so on.
I have an array: A B AB BAB ABBAB BABABBAB ... The number of each term of the array is base on the Fibonacci number.Put the n-th string and the n+1-th string together, then producing the n+2-th string,eg.BABABBAB = BAB + ABBAB.
Then is the 10^16-th letter is A or B?
Let f[n] be the nth fibonacci number.
Assume we want to find the value at position x in the string obtained by concatenating f[1], f[2], ..., f[n].
Find the lowest k such that f[1] + f[2] + ... + f[k] >= x. So position x belongs to word that has f[k] characters (at least in the concatenation it does. But since all words are made up from a and b, we'll try to reduce the problem to just those two).
To find the position corresponding to x in the term f[k], subtract f[1] + ... + f[k - 1] from x.
if k = 1 print a, if k = 2 print b, else go to step 4.
if f[k - 2] < x, then the position we're looking for is in the word corresponding to (with length) f[k - 1]. Subtract 1 from k and f[k - 2] from x and go to step 3.
Else, the position we're looking for is in the word corresponding to f[k - 2]. Subtract 2 from k, leave x unchanged and go to step 3.
This doesn't require generating the actual words, just their lengths, which are the basic fibonacci numbers.
Worked example
- note that I'm only using the actual words for illustration purposes, they are not needed.
n f[n] corresponding word
1 1 a
2 1 b
3 2 ab
4 3 bab
5 5 abbab
6 8 bababbab
Concatenating all these we get: ababbababbabbababbab. Let's ask ourselves what's at position 10 (it's b).
1. f[1] + f[2] + f[3] + f[4] + f[5] >= 10, so k = 5
2. x = 10, f[1] + f[2] + f[3] + f[4] = 7, so subtract 7 from x, giving x = 3
3'. k isn't 1 or 2, skip this.
4'. f[k - 2 = 3] = 2 < x. k = 4, x = 1
3''. still ignoring this.
4'' f[k - 2 = 2] = 1 >= x. k = 2, x = 1
3'''. k = 2, print 'b'.
please don't take this answer too serious:
i never was good and math and this sounds like this task should be too heavy to calculate without a freaky algorithm, so my solution would be to simply have a guess. to choose between A and B, i would write a very simple programm like this in php to print out the first 15 or 20 "lines":
<?php
$var1 = "B";
$var2 = "A";
for($i=3;$i<=15;$i++){
$tmp = $var2;
$var2 = $var1;
$var1 = $tmp.$var1;
echo $i." ".$var1."<br>";
}
echo strlen(implode('',explode('B',$var1)));
echo "<br>";
echo strlen(implode('',explode('A',$var1)));
?>
the result shows there are always less As (38%) than Bs (62%) - so the chance to be right when guessing B aren't that bad.