How to fill an empty character array? - arrays

I'm trying decode an array of 1's and 0's using variable length coding. For example, if the string is [1 0 1 1], and A = [1 0] and B = [1 1], my program should give me a string something like: ['A', 'B'].
I first created an empty character array x = repmat(char(0),1,10)
But now when I detect a code word using a for loop and if statements, how do I add the character to this array x? Would it display the characters in the decoded string?

First of all, pre-defining the length of x is unnecessary in MATLAB because the language allows you resize arrays on-the-fly. That being said, preallocation is a sometimes a good idea because it will run faster.
Assuming you want to preallocate the length of x, you can assign a character to an element in x directly:
% Preallocate x
x = repmat(char(0),1,10);
% Assign a character to x
x(1) = 'A';
Where you can replace the 1 with any element in the array.
The challenge with this is that you need to keep track of where you are at in this preallocated array. If you already wrote characters to positions 1, 2, and 3, you need to know that the next assignment will write to the 4th element of x: x(4) = ....
A more elegant solution might be the following:
x = [];
if foundLetter
x(end) = 'A';
end
This adds the letter A to the end of the pre-defined character array x. It doesn't require that you preallocate the length of x.

You can index the character array x just as you would an array of doubles.
x(1) = 'A'; %Assign the char 'A' to the first element of x
.
.
.
x(10) = 'B'; %Assign the char 'B' to the tenth element of x
Here is a short example of what you would like to do.
clear decodedMsg
% define a dictionary between codes and corresponding characters
code{1,1} = 'A'; code{1,2} = '11';
code{2,1} = 'B'; code{2,2} = '101';
code{3,1} = 'C'; code{3,2} = '100';
% declare a sample message, corresponds to ABCBA
msg = [1 1 1 0 1 1 0 0 1 0 1 1 1];
%keeps track of the number of matches found, used to add to decodedMsg
counter = 1;
% get length of message and use to iterate through the msg
N = length(msg);
buffer = []; %must declare buffer if you are to use (end + 1) indexing later on
for i = 1:N
buffer(end + 1) = msg(i); %add the next msg value to the buffer
strBuf = strrep(num2str(buffer),' ',''); %convert buffer into string, e.x. [1 0 1] => '101'
findMatch = ismember(code(:,2),strBuf); %findMatch contains a 1 if a match is found
if any(findMatch) %if any element in findMatch is 1
decodedMsg(counter) = code{findMatch,1};%use that element to index a char in code cell array
counter = counter + 1; %increment counter since another code was found
buffer = []; %reset buffer for next string of 1s and 0s
end
end

Related

Why is my function not deleting all numbers?

I made a function that will find any digits in an array and remove them. Here's my code:
int noNums (char *a) {
int i;
int deleteInd;
for (i = 0; (i < MAX_NAME_SZ) && (a[i] != '\0'); i++) {
if ((a[i] >= '0') && (a[i] <= '9')) {
deleteInd = i;
memmove (&a[deleteInd], &a[deleteInd + 1], strlen (a) - deleteInd);
}
}
}
If a number is by itself in the char array, then it is removed, no problem. However, if there are consecutive numbers in the array, then only every other digit will be deleted?
If my char array has
w12345678
then the array is changed to
w2468
instead of
w
Any ideas?
After you do the memmove(), the next element is now in the index of the element you just deleted. But your loop will do i++, so you won't check that index again. As a result, whenever there are two digits in a row, you skip the second one.
One way to fix this is to loop from the end of the array to the beginning, instead of from the beginning to the end.
Another way is to do i-- after doing the memmove(), to counteract the i++ that the loop will do.
if (isdigit(a[i]) {
deleteInd = i;
memmove (&a[deleteInd], &a[deleteInd + 1], strlen (a) - deleteInd);
i--;
}
BTW, you should use isdigit() to test whether a character is a digit.
Have you noticed that you are deleting the first digit then skipping one?
When iterating through the array, you start at position 0 and incrementing. When you delete a digit, you alter the string index.
i = 0 (char = w)
Index: 012345689
string: w12345678
i = 1 (char = 1)
Index: 012345689
string: w2345678
i = 2 (char = 3)
Index: 012345689
string: w2345678
Essentially, you are shifting the string over whenever you delete your character.
Don't increment i when you delete a character.
Note that deleteInd is not needed in your code, you could use i directly.
This is not an answer — Barmar's is — but both this and OP's other question shows they could use a fresh look into how to modify character arrays in place.
This is written in the hopes that this is useful to others learning C as well.
Elements, or sequences of elements, can be removed from an array efficiently, using a simple loop over its contents.
The key is to keep two indexes: one for the next element (or elements) to be examined, and one for the last element stored (or the next position to store to).
For example, to remove digits in an array, one can use the following pseudocode function:
Function removedigits(array, length):
Let i = 0 # Index of next element to examine, "input"
Let o = 0 # Position of next element to store, "output"
While (i < length):
If (array[i] is not a digit):
Let array[o] = array[i]
Let o = o + 1
End If
Let i = i + 1
End While
# For a string, we'll also want to terminate the array
# at o, because the rest of it contains garbage (old contents):
Let array[o] = '\0'
End Function
When dealing with sequences, it may be useful to keep multiple indexes. For example, to remove duplicate lines, one might use the following function:
Function removeduplicatelines(array):
Let i = 0 # Next position in the array to be examined
Let o = 0 # Next position in the array to store to
Let ostarted = 0 # Index at which the last line stored started at
# Loop over each input line:
While (array[i] != '\0'):
# Find the length of this line. It can end with a newline
# or at the end of the string. The newline is not included.
Let ilen = 0
While (array[i + ilen] != '\n' && array[i + ilen] != '\0'):
Let ilen = ilen + 1
End While
# If the already stored line is of different length
# (the +1 is for the newline, as it is not included in ilen)
# or if it does not match the input line, store input line.
If (ostarted + ilen + 1 != o || memcmp(array + ostarted, array + i, ilen) != 0):
# The lengths or content differs. Store the line.
# Copy ilen characters, starting at array[i],
# to array[o] onwards.
# Because the array parts do not overlap,
# we can safely use memcpy() here.
memcpy(array + o, array + i, ilen)
# It is now the last stored line.
Let ostarted = o
Let o = o + ilen
# If there is a newline following the line,
# store that too.
If (array[i + ilen] == '\n'):
Let array[o] = '\n'
Let o = o + 1
End If
Else:
# It is the same line again. Do not store.
End If
# Proceed to the next input line.
Let i = i + ilen
# Because the newline was not included in ilen,
# skip it if there is one.
If (array[i] == '\n'):
Let i = i + 1
End If
End While
# After index o, the array may contain old contents;
# so terminate the string at index o.
Let array[o] = '\0'
End Function
Note that memcmp() returns zero, if the ilen characters starting at array + ostarted match those starting at array + i.
This approach works, if we know o never exceeds i; that is, that we never overwrite array contents we haven't examined yet. But do note that o is allowed to be equal to i, as that just means we overwrite the same character we just examined, making no actual change in the array.
If we wanted to modify the function so that it skips empty lines, we add a new while loop before the existing one, to remove any leading newlines:
While (array[i] == '\n'):
Let i = i + 1
End While
and, to remove any empty lines, we modify the last part within the while loop into
# Because the newline was not included in ilen,
# skip it (and any additional newlines) if there is one.
While (array[i] == '\n'):
Let i = i + 1
End While
Finally, do note that the above removeduplicatelines() is very careful about not appending a newline after the last line, if there isn't one in the array to begin with.

Finding the size of the longest sequence of consecutive numbers in a random array of size 1xn using matlab

I would like to find the size of the longest sequence of consecutive numbers in a random array of size 1xn using Matlab. I know that there are two ways to do this: 1) using a loop and 2) using Matlab functions e.g. find, but I am unsure about how to do this without using both?
E.G. [1 2 3 5 8 9 10 11 12 13 14 17]
The longest sequence in this would be 10 11 12 13 14, which would be of size 5.
I tried this but it doesn't work:
function [start, finish] = longest(sequence)
x = diff(t)==1;
f = find([false,x]~=[x,false]);
g = find(f(2:2:end)-f(1:2:end-1)>=N,1,'first');
Your variables don't match, but assuming that all(t == sequence) you are on the right track. You want to distinguish between the start of each run and the end by doing a second diff.
% Mark all sequences
x = diff(sequence) == 1;
% Take the second derivative to find the edges
xx = diff([false, x, false]);
% This gives matched pairs of indexes for each block
initial = find(xx == 1);
final = find(xx == -1);
% Get the block length
blockLength = final - initial;
% Get the max length
[~, idx] = max(blockLength);
% Return the indices
start = initial(idx);
finish = final(idx);
The result on your test gives start = 5, finish = 11. If you want to also return the block length, replace the ~ with your variable name

Scala: Shift elements in an Array

I'm getting used to the various data structures in Scala and I've noticed that this function (contrived example), which is supposed to move every character in the mutable array to the right by one, has no effect on the array:
def shiftRight(str: String): Array[Char] = {
val chars = str.toCharArray
for(i <- chars.length - 1 until 0) chars(i) = chars(i - 1)
chars
}
println(shiftRight("ABCD").mkString)
which produces the result
ABCD
not the expected
AABC
Default step for range is one. See class Range here and implicit that gets you to it here.
Instead of
for(i <- chars.length - 1 until 0)...
you need:
for(i <- chars.length - 1 until 0 by -1)...

Creating an array with characters and incrementing numbers

Pretty simple problem, I want to create an array with char in a for loop.
code:
a = [1:5];
arr = [];
for i = 1:length(a)
arr(i) = ['f_',num2str(i)]
end
I am getting error:
In an assignment A(I) = B, the number of elements in B and I must be the same.
all i want is an array:
[f_1 f_2 f_3....]
This is because arr(i) is a single element, while ['f:', num2str(i)] contain three characters. Also, for i = 1:length(1) doesn't really make sense, since length(1) is guaranteed to be 1. I guess you wanted for i = 1:length(a). If that's the case I suggest you substitute length with numel and i with ii.
The better way to create the array you want is using sprintf like this:
sprintf('f_%i\n',1:5)
ans =
f_1
f_2
f_3
f_4
f_5
Or possiblby:
sprintf('f_%i ',1:5)
ans =
f_1 f_2 f_3 f_4 f_5
I guess this is what you really wanted:
for ii = 1:5
arr{ii} = ['f_', num2str(ii)];
end
arr =
'f_1' 'f_2' 'f_3' 'f_4' 'f_5'
Or simpler:
arr = arrayfun(#(n) sprintf('f_%i', n), 1:5, 'UniformOutput', false)
The last two can be indexed as follows:
arr{1}
ans =
f_1
You can also do (same result):
str = sprintf('f_%i\n', 1:5);
arr = strsplit(str(1:end-1), '\n')
If you're doing this to create variable names, then please don't. Use cells or structs instead.

What is the simplest way to access array (not vector) element from middle to outermost?

I want to create a game, which monster is aligned from left to right horizontally, the order of monsters has other logical meaning (e.g.: the appearing sequence), but I want to play some effects which starts from the middle monster
the array, for example, for odd number size array:
int[] a=new int[]{1,2,3,4,5};
the access sequence is 3,2,4,1,5 (or 3,4,2,5,1)
for even number size array:
int[] a=new int[]{1,2,3,4,5,6};
the access sequence is 3,4,2,5,1,6 or (4,3,5,2,6,1)
If it is in something like vector in c++, it will be:
std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
a.push_back(5);
while(a.size()>0){
printf("%d\n",a[a.size()/2]);
a.erase(a.begin()+a.size()/2);
}
which the output is
3
4
2
5
1
But I want an algorithm which is suitable to be used in array, which the position of element cannot be changed,
I tried something like:
int a[]={1,2,3,4,5};
for(int i=a.size()/2;i>=0 && i<a.size();i=XXXX){
printf("%d\n",a[i]);
}
which XXXX is the update statement, which I still don't know what should it be.
In fact, I don't know if my init value and condition statement in for loop is correct. I even don't know if it can be done by a single loop.
Ok, I know I can have a temp vector and then copy the index to do that, but I also want to know if it can be done in a single for loop without any temp vector or array.
Can anyone help (or is there another simple algorithm to do that?)?
This is an answer for the edited question that is language-agnostic and wants a single function to display the elements in the stated order.
First, chose a "middle" index.
var i = Math.floor((a.length-1)/2);
Then alternate right and left moving outwards incrementally until either edge of the array is encountered.
To facilitate this, start with a variable d = 0 which will be the distance from the middle element. This d will be updated like so upon each iteration
d += -(2*d) + (d > 0 ? 0 : 1);
with the below update pattern:
0, 1, -1, 2, -2, ...
If the middle index is 2 in array [1,2,3,4,5], then applying a[i + d] will result in
3, 4, 2, 5, 1
I hope this is what you are looking for.
Here is a JavaScript implementation:
var a = [1,2,3,4,5,7,8];
var i = Math.floor((a.length-1)/2);
for (var d = 0; i+d >= 0 && i+d < a.length;) {
// Print out the value
console.log(a[i + d]);
// Outward-moving logic
d += -(2*d) + (d > 0 ? 0 : 1);
}
or if you want this all in the for-loop like you've tried in your question, you can do this:
var a = [1,2,3,4,5,7,8];
var i = Math.floor((a.length-1)/2);
for (var d = 0; i+d >= 0 && i+d < a.length; d += -(2*d) + (d > 0 ? 0 : 1)) {
console.log( a[i + d] ); // print the value
}
Result on [1,2,3,4,5] (odd-length array):
3 4 2 5 1
Result on [1,2,3,4,5,6,7,8] (even-length array):
4 5 3 6 2 7 1 8
Demo: JSBin
An algorithm to list the elements from innermost to outermost is to pull off the last and first entries (pop and shift) in the array in alternation until no elements are left, then reverse the list of what you have pulled off. This works for odd and even-length arrays naturally.
For example,
1,2,3,4,5,6
1,2,3,4,5 6
2,3,4,5 6,1
2,3,4 6,1,5
3,4 6,1,5,2
3 6,1,5,2,4
6,1,5,2,4,3
3,4,2,5,1,6 // Reversed list from above
and
1,2,3,4,5
1,2,3,4 5
2,3,4 5,1
2,3 5,1,4
3 5,1,4,2
5,1,4,2,3
3,2,4,1,5 // Reversed list from above
You can use this above algorithm to create an index map array which you can use to access your main array in the order you requested. For example:
// Start with an array of indices
// from 0..arr.length-1
0,1,2,3,4
0,1,2,3 4
1,2,3 4,0
1,2 4,0,3
2 4,0,3,1
4,0,3,1,2
2,1,3,0,4 // Reversed list from above
Then you have a mapping array
int[] arr = new int[]{1,2,3,4,5};
int[] map = new int[]{2,1,3,0,4};
which you can use to access your main array, for example
arr[map[0]]; // returns 3
Edit: Added Java implementation and demo.
public static int[] creatIndexMap(int length) {
// Create a deque so elements can be removed from both ends
Deque<Integer> tmp = new LinkedList<Integer>();
for(int i = 0; i < length; i++) {
tmp.add(i);
}
// In alternation remove the last and first entries of tmp
// and add them in reverse order to the map array
int[] map = new int[length];
int index = length-1;
while (!tmp.isEmpty()) {
// Remove last element
map[index--] = (int) tmp.removeLast();
// Remove first element
if(!tmp.isEmpty()) {
map[index--] = (int) tmp.removeFirst();
}
}
return map;
}
Demo: IDEOne

Resources