matlabif-statementfile-iowhile-looplow-level-io

Inventory Restock with MATLAB (Low-Level I/O)


It's that time again where I/Os are confusing me. In this case, my goal is to write a function that takes in a .txt file of inventory items and another .txt file of price and outputs the total cost of restocking the items, as well as a .txt file that has the original inventory data and the amount of items needed to be restocked. For example:

Inventory Data:

Buns #50 #63
Burgers #32 #55
Ketchup #6 #10
Hotdogs #4 #35
Mustard #7 #8

Note: The header is included in the .txt file and there will always be five items to restock

My output file should read as:

Inventory Data:

Buns #50 #63
Burgers #32 #55
Ketchup #6 #10
Hotdogs #4 #35
Mustard #7 #8


Restocking Data:

Buns #63 #13
Burgers #55 #23
Ketchup #10 #4
Hotdogs #35 #31
Mustard #8 #1

and my output total should be 271 because

Prices:

Buns $2
Burgers $5
Ketchup $1
Hotdogs $4
Mustard $2

Amro was kind enough to help me figure out how to pull out the lines I need, and how to subtract my Needed from what I have. Now my last struggle (and the last hurdle I need to overcome before I can better personalize the problem), is figuring out how to write a final that outputs the original data, as well as the restocking data. It has to look like the test case

 function[restock_cost] = inventory2(file, prices)

%// Reads both files
fh = fopen(file, 'rt');
C = textscan(fh, '%s', 'Delimiter','');
inventory = C{1};
fclose(fh);
Original = C{:};
Original = char(Original);

fh2 = fopen(prices, 'rt');
D = textscan(fh2, '%s', 'Delimiter','');
prices = D{1};
fclose(fh2);

%// Breaks up inventory data
inventory(1) = [];
x = regexp(inventory, '(\w+) #(\d+) #(\d+)', 'tokens', 'once');
x = vertcat(x{:});
itemName = x(:,1);
itemHave = str2double(x(:,2));
itemNeeded = str2double(x(:,3));
itemName = char(itemName);


%// Determines what needs to be restocked and how much is needed
Restock = itemNeeded - itemHave;

%// Breaks up price info
prices(1) = [];
x = regexp(prices, '(\w+) \$(\d+)', 'tokens', 'once');
x = vertcat(x{:});
item = x(:,1);
prices = str2double(x(:,2));

%// Finds the price
restock_cost = sum((Restock .* prices));

%// gets the business name
[name, ~] = strtok(file,'_');

%// Finds the size of Original(may help)
[r,c] = size(Original);
[r2,c2] = size(itemName);
[r3,c3] = size(itemNeeded);

%// Starts to write my output file.
fh2 = fopen([name '_RestockingData.txt'], 'wt');
fprintf(fh2, 'Inventory Data: \n');
fprintf(fh2, '\n');

for i = 2:r %// Don't want the header included
    fprintf(fh2, Original(i,1:c));
    fprintf(fh2,'\n');
end
fprintf(fh2, '\n');
fprintf(fh2,'\n');
fprintf(fh2, 'Restocking Data: \n');
fprintf(fh2,'\n');

for j = 1:r2
    fprintf(fh2, itemName(j,1:c2));
    fprintf(fh2,' #%d ', itemNeeded(j));
    fprintf(fh2, '#%d', Restock(j));
    fprintf(fh2,'\n');
end

end

This is close, but I need it to output the restocking data with only a single space inbetween the item name and the numbers. Instead it's giving me:

Inventory Data: 

Chips #40 #100    
Lettuce #80 #90   
Cheese #22 #60    
Tortillas #65 #100
Tomatoes #40 #70  



Restocking Data: 

Chips     #100 #60
Lettuce   #90 #10
Cheese    #60 #38
Tortillas #100 #35
Tomatoes  #70 #30

I've also tried this:

Restock_Data = {};
Restock_Data = [Restock_Data, {itemName, itemNeeded, Restock}];
Restocking = {Restock_Data};
Kill_Cell = [{Restocking}];

for j = 1:r2

    fprintf(fh2, Restock_Data(j));
    fprintf(fh2,'\n');
end

I need to convert my cell into some other form, but indexing it (As you can see in Kill_Cell) isn't working. end

That should be everything. Here are notes given to me just in case:

Notes: 
   - All inventory numbers will have a # in front of them 
   - All the prices will have a $ in front of them and will always be a
     full dollar amount.
   - When creating the new output every item should be seperated by a space
       Ex. 'Chips #5 #2'
   - There will always be 5 items to stock.
   - If your output file is not EXACTLY the same as the solution txt file,
     then you will receive 0 credit for it.

Solution

  • Here is one way to use textscan to read the inventory file:

    fid = fopen('inventory.txt', 'rt');
    C = textscan(fid, '%s #%d #%d', 'HeaderLines',1, 'CollectOutput',true);
    fclose(fid);
    

    The data parsed:

    >> C
    C = 
        {5x1 cell}    [5x2 int32]
    
    >> C{1}
    ans = 
        'Buns'
        'Burgers'
        'Ketchup'
        'Hotdogs'
        'Mustard'
    
    >> C{2}
    ans =
              50          63
              32          55
               6          10
               4          35
               7           8
    

    You could also read the file simply as a cell-array of string lines (I've used this in my previous answers to your questions):

    fid = fopen('inventory.txt', 'rt');
    C = textscan(fid, '%s', 'Delimiter','');
    C = C{1};
    fclose(fid);
    

    The result in this case:

    >> C
    C = 
        'Inventory Data:'
        'Buns #50 #63'
        'Burgers #32 #55'
        'Ketchup #6 #10'
        'Hotdogs #4 #35'
        'Mustard #7 #8'
    

    EDIT:

    Like I've showed, first we read the files as a cell array of strings (lines of text):

    % read both files
    fid = fopen('inventory.txt', 'rt');
    C = textscan(fid, '%s', 'Delimiter','');
    inventory = C{1};
    fclose(fid);
    
    fid = fopen('prices.txt', 'rt');
    C = textscan(fid, '%s', 'Delimiter','');
    prices = C{1};
    fclose(fid);
    

    Next we use regular expressions to match patterns in the text:

    % parse inventory data
    inventory(1) = [];
    x = regexp(inventory, '(\w+) #(\d+) #(\d+)', 'tokens', 'once');
    x = vertcat(x{:});
    itemName = x(:,1)
    itemHave = str2double(x(:,2))
    itemNeeded = str2double(x(:,3))
    
    % parse prices data
    prices(1) = [];
    x = regexp(prices, '(\w+) \$(\d+)', 'tokens', 'once');
    x = vertcat(x{:});
    item = x(:,1)
    price = str2double(x(:,2))
    

    Finally you can apply your logic to restock inventory, and print the required output...