Matlab: Having trouble with this code regarding arrays - matlab

Here is the question:
The file upcs.txt contains a list of UPC codes that were scanned in a grocery
store. Each line should, ideally, contain 12 digits corresponding to a single product. Read
the contents of the file and store the entries into an m x 12 sized numeric array named
codes, where m is the number of valid lines in the le. Lines that have less or more than
12 digits should be discarded. Some lines with 12 digits may have digits that were not
correctly scanned, which were replaced by the letter X'. These missing digits should be
represented in the array codes by the integer-1'. After processing the file, print the total
number of lines read, the number of lines discarded, and the number of lines correctly
processed and stored in codes.
upcs.txt:
X9096X082489
921642004330
810905023006
733554287763
413527622XX1
287X35871528
100093334850
764491079X90
1537X8886614
086755751640
860053705316
980098819206
038356338621
577577248178
82825685985
684580785580
736657539753
71113617151
935014271064
702345843488
58316491755
110118383664
333841856254
996003013296
495258095746
4457870230
684104168936
522784039910
6504512835
699553963094
853110488363
554147120089
Here is my code so far:
fid = fopen('upcs.txt');
mat = [];
if fid == -1
disp('File open was not successful')
else codes = {};
while feof(fid) == 0
aline = fgetl(fid);
num = strtok(aline);
codes = [codes; num]
end;
[m n] = size(codes)
discard = 0
for i = 1:m
len = length (codes(i))
if len ~= 12
codes = [];
discard = discard + 1
else
char(codes(i))
codes = strrep(codes, 'X', '-1')
end
end
codes
end
The trouble I am having is that I don't know how to delete the codes that have less or more than 12 digits in my code.

clear;clc;
fid = fopen('upcs.txt','r');
if fid == -1
error('File open was not successful');
end
C = textscan(fid,'%s');
C = C{1};
all_codes_num = size(C,1);
codes_discarded_num = 0;
codes_missed_digit_num = 0;
codes_correct_num = 0;
codes = [];
for i = 1:all_codes_num
one_code = C{i};
if length(one_code) == 12
x_flag = 0;
code_tmp = zeros(1,12);
for j = 1:12
if one_code(j) == 'X' || one_code(j) == 'x'
code_tmp(j) = -1;
x_flag = 1;
else
code_tmp(j) = str2num(one_code(j));
end
end
if x_flag == 1
codes_missed_digit_num = codes_missed_digit_num +1;
end
codes = [codes;code_tmp];
elseif length(one_code) ~= 12
codes_discarded_num = codes_discarded_num + 1;
end
end
all_codes_num
codes_discarded_num
codes_with_x = codes_missed_digit_num
correct_codes_without_x = all_codes_num - codes_discarded_num - codes_with_x
codes: have all the correct codes and also 12-length codes with missing data which has been replaced with '-1'. This is a m*12 numeric matrix. Each row is a code.
all_codes_num: the number of all the lines we have read
codes_discarded_num: the number of all the codes which have more or less than 12 chars
codes_with_x: the number of 12-length codes which have missing digits.
correct_codes_without_x: the number of 12-length codes which have digits only.
In the codes, I assume that in the 'upcs.txt', each line is a code.

Related

Index exceeds matrix dimentions erro in matlab

This is part of my script:
fid = fopen([directory '001/listing.txt'],'r');
tline = fgetl(fid);
ii = 0;
while (tline ~= -1)
ii = ii + 1;
year(ii) = str2num(tline(11:14));
month(ii) = str2num(tline(15:16));
day(ii) = str2num(tline(17:18));
hour(ii) = str2num(tline(20:21));
min(ii) = str2num(tline(22:23));
sec(ii) = str2num(tline(24:25));
tline = fgetl(fid);
end
fclose(fid);
I keep getting the error "Index exceeds matrix dimensions". Can someone help me here?
Sometimes tline is less than 25 characters long.
My guess is that you have some blank lines in your file that doesn't cause fgetl to return -1 but an empty string instead.
Put an if just after while to skip empty lines:
if (length(tline) == 0)
continue
end
If you still have problems, change the == 0 part for <25 to make sure all lines you process are at least 25 characters long.

Have to convert Integer to binary

I'm writing a user-defined function to convert integers to binary. The largest number that could be converted with the function should be a binary number with
16 1 s. If a larger number is entered as d, the function should display an error
message. With my code, I'm trying to add the numbers 0 or 1 to my vector x based on the remainder, then I want to reverse my final vector to display a number in binary. Here's what I have:
function [b] = bina(d)
% Bina is a function that converts integers to binary
x = [];
y = 2;
in = d/2;
if d >=(2^16 -1)
fprintf('This number is too big')
else
while in > 1
if in >= 1
r = rem(in,y);
x = [x r]
end
end
end
end
As you insist on a loop:
x = [];
y = 2;
in = d;
if d >=(2^16 -1)
fprintf('This number is too big')
else
ii = 1;
while in > 0
r = logical(rem(in,y^ii));
x = [r x];
in = in - r*2^(ii-1);
ii = ii+1;
end
end
b = x;
You had the right ideas, but you need to update the variables in your while-loop with every iteration. This is mainly in, where you need to subtract the remainder. And just store the binary remainders in your variable x.
You can check your result with
x = double( dec2bin(d, 16) ) - 48
You could also use a for loop, by pre-calculating the number of iterations with
find( d < 2.^(1:16),1)
and then
if d >=(2^16 -1)
fprintf('This number is too big')
else
for ii = 1:find( d < 2.^(1:16),1)
r = logical(rem(in,y^ii));
x = [r x];
in = in - r*2^(ii-1)
end
end

Solving a wordsearch puzzle in matlab

Posting the entirety of my code in the hope somebody can help me debug this crap. Really hoping to reach a conclusion soon because I've been toying with this for way too long.
I have here a function extract which is passed a grid of integers which represent letters (i.e A=1,Z=26) from my wordsearch function. Given a direction and a target word which is represented by a row vector of ints, it should iterate through the grid to find where the first letter exists and move in all directions from here for length of the word and extract the word e.g. if we are looking for [14, 5, 9, 2] and 14 is first positioned at (4,4) we should end up at (4,8).
The word is then compared in the search function and if it matches the target word, a line is drawn from first letter to the last on an image of the actual wordsearch.
I know my if and for loops are off in some places but I'm finding it difficult to correct my code so that it works. Help! One thing in particular I'm having difficulty with is controlling flow so that if after checking all directions from a square containing the first letter, the next instance of that letter is evaluated. Where would it be best to do this?
Code has lots of errors as it is and could do with a couple of pointers telling me where it needs altering or cleaning up.
%//A function to find a word in a grid.
function test = extract(grid, direction, target)
%//switch through different cases that allow us to move to any adjacent cell to the current
switch upper(direction)
case 1
rowdir = -1;
coldir = 0;
case 2
rowdir = -1;
coldir = 1;
case 3
rowdir = 0;
coldir = 1;
case 4
rowdir = 1;
coldir = 1;
case 5
rowdir = 1;
coldir = 0;
case 6
rowdir = 1;
coldir = -1;
case 7
rowdir = 0;
coldir = -1;
case 8
rowdir = -1;
coldir = -1;
end
[i, j] = size(grid);
len = length(target);
[row,column] = find(target(1)==grid); %//find the letter of the word we are looking for in grid
%//row and column of last letter having moved in a particular direction
rowN = row + (len-1) * rowdir;
colN = column + (len-1) * coldir;
%//trying to say here to only move in a particular direction if we don't go out of bounds.
%//not sure I've succeeded
if (rowN > 1) | (rowN < i) | (colN > 1) | (colN < j)
testword = []; %empty array created
for index = 1:len
index_1 = index-1;
%//on loop get the letter in adjacent cell for direction we have moved
word = grid(row + (index_1 * rowdir), column + (index_1 * coldir));
testword{index} = word; %//letters are appended to create word for which we compare.
%//get co-ords of start letter. change to pixel co-ordinates so we can evaluate on image
wordstart = [(row*30)-15, (column*30)-15 ];
wordend = [((row + (len-1 * rowdir))*30)-15, ((column + (len-1 * coldir))*30)-15];
end
else
word = '';
end
x1 = wordstart(1);
x2 = wordend(1);
y1 = wordstart(2);
y2 = wordend(2);
test = [ word , [x1,x2] , [y1,y2]]; %//only way I could think of to get all of these as outputs
end
%//test is the image we want to evaluate on
%//words is the list of words
function trial1 = wordsearch(test, words)
imagesc(test);
colormap(gray);
hold on;
grid = %//grid is a 15x15 matrix
[row, column] = size(grid);
for iword = 1 : length(words)
target = char(words(iword)) - 'a' + 1;
for i = 1:row
for j = 1:column
for direction_num = 1:8 %//for each direction
direction = directions(direction_num, :);
testword = extract(grid,direction,target);
if testword(1)==target %//if word we have extracted equals the target word
%//draw_line function takes x co-ordinates and y co-ordinates and plots line.
draw_line(testword(2),testword(3),testword(4),testword(5));
end
end
end
end
end
hold off;
end
#Dan
My extract function now looks like:
[i, j] = size(grid);
len = length(target);
[row,column] = find(target(1)==grid);
for ii = 1:length(row)
start_row = row(ii);
start_column = column(ii);
rowN = start_row + len-1 * rowdir;
colN = start_column + len-1 * coldir;
if (rowN > 1) || (rowN < i) || (colN > 1) || (colN < j)
testword = [];
for index = 1:len
index_1 = index-1;
word = grid(start_row + (index_1 * rowdir), start_column + (index_1 * coldir));
testword{index} = word;
wordstart = [(start_row*30)-15, (start_column*30)-15 ];
wordend = [((start_row + (len-1 * rowdir))*30)-15, ((start_column + (len-1 * coldir))*30)-15];
end
else
end
end
What would I put as an else statement to check the word if previous in that particular direction takes you out of bounds?
for iword = 1 : length(words)
target = char(words(iword)) - 'a' + 1;
for i = 1:row
for j = 1:column
for direction_num = 1:8 %//for each direction
For every word, you are looping through every element in the grid (i.e. the i and j loops) but you don't actually ever use these i or j values. So those two loops do nothing! This is because you seems to do all of that inside your extract function. So drop those two loops, they are wasting an inordinate amount of time.
Inside your extract function, you have a line [row,column] = find.... This will find ALL the possible starting points. So you actually need to loop through either of those somewhere. So instead of your if (rowN > 1) | (rowN < i) | (colN > 1) | (colN < j) I would suggest something more like:
for ii = 1:length(row)
start_row = row(ii);
start_column = column(ii);
%// And now re-use your code, but swap out all your row for start_row and your column for start_column
.
.
.
end
That is the loop that will go through each of the possible starting letters.

error with "The matrix MSG in ENCODE must have K columns"

im working on a video steganography using LSB technique..im using traffic.avi and xylophone.mpg as the cover medium and when im using the licence.txt file (in the attach file) to encode into the video it runs well however when im using a short messsage for the input text it shows an error which is
"The matrix MSG in ENCODE must have K columns." and sometimes when use short text it gives error "msg is too long to encode"
i have no idea what does this 2 set of coding means and how to edit the code to make it possible to encode a short msg...below this is some of the code that i guess relate to this problem
num2add = 80-length(msg); % Number of spaces to add to end of MSG.
if num2add < 0, error('This message is too long to encode.'), end
newmsg = [msg,repmat(' ',1,num2add)]; % 80 chars always encoded.
msgmat = dec2bin(newmsg)-48; % Each row is a bin. rep. of an ascii char.
and also this coding
if m_msg == 1
type_flag = 2; % binary vector
[msg, added] = vec2mat(msg, k);
elseif m_msg ~= k
error('comm:encode:InvalidMatrixColumnSize','The matrix MSG in ENCODE must have K columns.');
BELOW THIS IS THE FULL ENCODE CODING continue after the first part of the above coding!
B = pic1(:,:,1); [piclngth pichght] = size(B); % Choose the first page.
dim1 = piclngth-2; dim2 = pichght-3; keyb = key(end:-1:1);
rows = cumsum(double(key));
columns = cumsum(double(keyb)); % Coord pairs for KEY (rows,columns)
A = zeros(dim1,dim2); % This matrix will house the hiding points.
A = crtmtrx(A,rows,columns,dim1,dim2,key);
idx = find(A==1); % This same index will be used for pic matrix.
for vv = 1:80 % This is the encoder.
for uu = 1:8
if msgmat(vv,uu)==1;
if rem(B(idx(uu+8*(vv-1))),2)==0
if(frame==1)
disp('some pixel value of original frame');
B(idx(uu+8*(vv-1)))
end
B(idx(uu+8*(vv-1))) = B(idx(uu+8*(vv-1)))+1;
if(frame==1)
disp('some pixel value of stegno video frame');
B(idx(uu+8*(vv-1)))
end
end
elseif rem(B(idx(uu+8*(vv-1))),2)==1
if(frame==1)
disp('some pixel value of original frame');
B(idx(uu+8*(vv-1)))
end
B(idx(uu+8*(vv-1))) = B(idx(uu+8*(vv-1)))-1;
if(frame==1)
disp('some pixel value of stegno video frame');
B(idx(uu+8*(vv-1)))
end
end
end
end
global newpic;
newpic = pic1; newpic(:,:,1) = B;
f(frame) = im2frame(newpic);
end
frameRate = get(vidObj,'FrameRate');
movie2avi(f,'stegano_video.avi','compression','None', 'fps', 20);
success = 1;
function A = crtmtrx(A,rows,columns,dim1,dim2,key)
% Creates the matrix used to find the points to hide the message.
jj = 1; idx = 1;
while 640 > length(idx) % Need 560 points to hide 80 characters.
for ii = 1:length(rows)
if rows(ii) < dim1
rows(ii) = rem(dim1,rows(ii))+1;
else
rows(ii) = rem(rows(ii),dim1)+1;
end
if columns(ii) < dim2
columns(ii) = rem(dim2,columns(ii))+1;
else
columns(ii) = rem(columns(ii),dim2)+1;
end
A(rows(ii),columns(ii)) = 1;
end
rows = jj*cumsum(double(columns))+round(dim2/2); % Each pass is diff.
columns = jj*cumsum(double(rows))+round(dim1/2);
if jj > ceil(640/length(key))+2 % Estimate how many iters. needed.
idx = find(A==1);
end
jj = jj+1;
end
this is some of the input text and the right one is the encypted txt
The code that triggers the error is pretty clear:
num2add = 80-length(msg); % Number of spaces to add to end of MSG.
if num2add < 0, error('This message is too long to encode.'), end
So basically you will get the error as soon as there are more than 80 characters in msg. I am not sure whether the 80 is meaningfull, you can try to increase it but that may break something else.

Matlab Muliple delimiter removing during import

I am struggling with a problem and want a easy way around. I have a big array of data where I have some vector values as ( 1.02 1.23 3.32) format. I want it as 1.02 1.23 3.32 in a tabular form. The problem here is that there are two types of delimiter '(' and ')'.
can anyone help in writing a code for this? I have something like this:
filename = 'U.dat';
delimiterIn = '(';
headerlinesIn = 0;
A = textscan(filename,delimiterIn,headerlinesIn);
But one thing is that it only have one delimiter "(" and it does not work either.
Nishant
If your text file looks something like this:
(1 2 3) (4 5 6)
(7 8 9) (10 11 12)
You can read it in as strings and convert it to a cell array of vectors like this:
% read in file
clear all
filename = 'delim.txt';
fid = fopen(filename); %opens file for reading
tline = fgets(fid); %reads in a line
index = 1;
%reads in all lines until the end of the file is reached
while ischar(tline)
data{index} = tline;
tline = fgets(fid);
index = index + 1;
end
fclose(fid); %close file
% convert strings to a cell array of vectors
rowIndex = 1;
colIndex = 1;
outData = {};
innerStr = [];
for aCell = data % for each entry in data
sline = aCell{1,1};
for c = sline % for each charecter in the line
if strcmp(c, '(')
innerStr = [];
elseif strcmp(c, ')')
outData{rowIndex,colIndex} = num2str(innerStr);
colIndex = colIndex + 1;
else
innerStr = [innerStr, c];
end
end
rowIndex = rowIndex + 1;
colIndex = 1;
end
outData