Adding Arrays of Digits as if They Represented Numbers - arrays

I have the following problem. Suppose I have to arrays X and Y whose entries consist of integers in the range 0 through 9 like
X = [1 2 3]
Y = [7 0 9]
I want to think of these arrays as being the digits of base-10 numbers, so X represents the number 123 and Y represents the number 709. I want to write a program which outputs the digits of the sum of these integers. So in the example given, it should output the array
Z = [8 3 2]
since 123 + 709 = 832. For the sake of this question it suffices to assume that X and Y have the same length, i.e., that the numbers they represent have the same number of digits. While I am doing this, I also want to keep track of carries which were performed during the addition. So in the example, I'd also want to output
C = [0 0 1]
which represents that I had to carry a 1 when I added the digits 9 + 3 = 12, but that the additions of the digits in other positions went through without carries. So my main question is
Does anyone know of a simple way to achieve this goal using MATLAB?
So far, what I've come up with is the following code which is given the two numbers as X and Y
clear all; clc;
C = zeros(1, length(X));
for j=length(X):-1:1
if X(j) + Y(j) > 9
C(j) = 1;
end
Z(j) = mod(X(j) + Y(j), 10);
if j < length(X)
if Z(j) + C(j+1) < 9
Z(j) = Z(j) + C(j+1);
else
Z(j) = mod(Z(j) + C(j+1), 10);
C(j) = 1;
end
end
end
if C(1) == 1
Z = [1 Z];
end
Z
C
The problem is that the code only works sometimes. For example, it has no problem working through the example I gave above, that 123 + 709 = 832 with a "carry array" of [0 0 1]. But the input X = 52514 and Y = 41525 does not yield the correct results. So my follow up question is
Does anyone see the bug in the code above/how can I fix it?

You need to change the line
if Z(j) + C(j+1) < 9
to
if Z(j) + C(j+1) <= 9
Then it should work.

You can take advantage of dec2base, str2num and num2str functions:
function StackOverflow
x = [1 2 3];
y = [4 5 6];
numX = DigitsToNum(x);
numY = DigitsToNum(y);
digits = NumToDigits(numX+numY);
disp(digits);
end
function digits = NumToDigits(x)
digits = double( dec2base(x,10) - '0');
end
function num = DigitsToNum(x)
st = strrep(num2str(x),' ','');
num = str2num(st); %#ok<ST2NM>
end
Another way to implement the two functions above:
function digits = NumToDigits(x)
digits = [];
while x > 0
digits(end+1) = mod(x,10); %#ok<AGROW>
x = floor(x/10);
end
end
function num = DigitsToNum(x)
baseMult = power(10,0: (numel(x)-1));
num = sum( baseMult.*x );
end

Related

Finding number(s) that is(are) repeated consecutively most often

Given this array for example:
a = [1 2 2 2 1 3 2 1 4 4 4 5 1]
I want to find a way to check which numbers are repeated consecutively most often. In this example, the output should be [2 4] since both 2 and 4 are repeated three times consecutively.
Another example:
a = [1 1 2 3 1 1 5]
This should return [1 1] because there are separate instances of 1 being repeated twice.
This is my simple code. I know there is a better way to do this:
function val=longrun(a)
b = a(:)';
b = [b, max(b)+1];
val = [];
sum = 1;
max_occ = 0;
for i = 1:max(size(b))
q = b(i);
for j = i:size(b,2)
if (q == b(j))
sum = sum + 1;
else
if (sum > max_occ)
max_occ = sum;
val = [];
val = [val, q];
elseif (max_occ == sum)
val = [val, q];
end
sum = 1;
break;
end
end
end
if (size(a,2) == 1)
val = val'
end
end
Here's a vectorized way:
a = [1 2 2 2 1 3 2 1 4 4 4 5 1]; % input data
t = cumsum([true logical(diff(a))]); % assign a label to each run of equal values
[~, n, z] = mode(t); % maximum run length and corresponding labels
result = a(ismember(t,z{1})); % build result with repeated values
result = result(1:n:end); % remove repetitions
One solution could be:
%Dummy data
a = [1 2 2 2 1 3 2 1 4 4 4 5 5]
%Preallocation
x = ones(1,numel(a));
%Loop
for ii = 2:numel(a)
if a(ii-1) == a(ii)
x(ii) = x(ii-1)+1;
end
end
%Get the result
a(find(x==max(x)))
With a simple for loop.
The goal here is to increase the value of x if the previous value in the vector a is identical.
Or you could also vectorized the process:
x = a(find(a-circshift(a,1,2)==0)); %compare a with a + a shift of 1 and get only the repeated element.
u = unique(x); %get the unique value of x
h = histc(x,u);
res = u(h==max(h)) %get the result

Syntax understanding in task with matlab

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

Convert vector of numbers to string without removing the zeros at start and end

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'

Create all possible Mx1 vectors from an Nx1 vector in MATLAB

I am trying to create all possible 1xM vectors (word) from a 1xN vector (alphabet) in MATLAB. N is > M. For example, I want to create all possible 2x1 "words" from a 4x1 "alphabet" alphabet = [1 2 3 4];
I expect a result like:
[1 1]
[1 2]
[1 3]
[1 4]
[2 1]
[2 2]
...
I want to make M an input to my routine and I do not know it beforehand. Otherwise, I could easily do this using nested for-loops. Anyway to do this?
Try
[d1 d2] = ndgrid(alphabet);
[d2(:) d1(:)]
To parameterize on M:
d = cell(M, 1);
[d{:}] = ndgrid(alphabet);
for i = 1:M
d{i} = d{i}(:);
end
[d{end:-1:1}]
In general, and in languages that don't have ndgrid in their library, the way to parameterize for-loop nesting is using recursion.
[result] = function cartesian(alphabet, M)
if M <= 1
result = alphabet;
else
recursed = cartesian(alphabet, M-1)
N = size(recursed,1);
result = zeros(M, N * numel(alphabet));
for i=1:numel(alphabet)
result(1,1+(i-1)*N:i*N) = alphabet(i);
result(2:M,1+(i-1)*N:i*N) = recursed; % in MATLAB, this line can be vectorized with repmat... but in MATLAB you'd use ndgrid anyway
end
end
end
To get all k-letter combinations from an arbitrary alphabet, use
n = length(alphabet);
aux = dec2base(0:n^k-1,n)
aux2 = aux-'A';
ind = aux2<0;
aux2(ind) = aux(ind)-'0'
aux2(~ind) = aux2(~ind)+10;
words = alphabet(aux2+1)
The alphabet may consist of up to 36 elements (as per dec2base). Those elements may be numbers or characters.
How this works:
The numbers 0, 1, ... , n^k-1 when expressed in base n give all groups of k numbers taken from 0,...,n-1. dec2base does the conversion to base n, but gives the result in form of strings, so need to convert to the corresponding number (that's part with aux and aux2). We then add 1 to make the numbers 1,..., n. Finally, we index alphabet with that to use the real letters of numbers of the alphabet.
Example with letters:
>> alphabet = 'abc';
>> k = 2;
>> words
words =
aa
ab
ac
ba
bb
bc
ca
cb
cc
Example with numbers:
>> alphabet = [1 3 5 7];
>> k = 2;
>> words
words =
1 1
1 3
1 5
1 7
3 1
3 3
3 5
3 7
5 1
5 3
5 5
5 7
7 1
7 3
7 5
7 7
use ndgrid function in Matlab
[a,b] = ndgrid(alphabet)

Fibonacci string array

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.

Resources