Thread: Algorithm Questions

  1. #1
    Registered User
    Join Date
    Dec 2004
    Posts
    45

    Algorithm Questions

    Here's my task
    I have a file filled with sales info each line in the text file is a different sale done by a different Sales Person which is denoted by a 2 char code as in 'r1'. But sale people repeat and there's no foreknowlege how many sales people there will be and of course no knowledge how many sales each will have... Well I need to parse out each unique sales person and the # sales each has and at the end a total of all sales.

    My algorithm:
    pull out each unique SalesPerson's ID
    add to map/set???
    cycle input file through map/set counting qty of each ID(sales)
    output each id and associated sales with each
    total of count of all sales


    Not quite sure how to do this or if I have it all together some suggestions would help alot..

  2. #2
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    Here's some code of what I had so far it doesn't compile because of what data I sent through...

    Code:
    int TsrGrouper(string inSource2)
    /*Searches given file and tallys up each TSR's sales in a formatted report 
    by month*/
    
    {
        ifstream source(inSource2.c_str());
        string line;
        int x=0;
        char *Tsrmap[16];
        while (getline(source,line))
        {
            //cout<<line.substr(513,2)<<"  ";
            if (!Tsrmap[line.substr(513,2)])
                Tsrmap[line.substr(513,2)] = true;
    
            for (Tsrmap[x],x>15,x++){
                cout<<"  "<<Tsrmap[x]<<endl;
            }
        }
        
    
        return 0;
    }
    I was trying to add one of each ID to the map and then I would cycle through the file again and make a counter for each ID to get a count of sales.. Need some clues on how to use this or maybe an array I know that map doesn't allow Tsrmap[line.subtring(513,2)]
    because it has to refer to a int but there is a way right???

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    hmm, seems to me you need a little refresher on C++ before going much further. but basically, the steps I would suggest would be:

    1) begin with a container of sales-persons records.
    2) read each sale into a container of sale-transactions.
    3) to obtain sales by person implement:

    Code:
    for each salesperson {
     total = 0
     for each transaction {
      if transaction.salesperson == salesperson {
       add to total
       }
      }
     output the sales for this person
     }
    4) for total sales of course, just run through all transactions and accumulate the total.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    I was reading up on containers when I came across this example would this be able to be converted over to my problem?? I know that I have to change the multiset to something other than char but not sure I would be able to use char* or string. Again my Saleperson Id's are two characters long. This code runs as is. Is this modifiable to my task?
    Code:
    #include "stdafx.h"
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <functional>
    #include <set>
    #include <string>
    #include <map>
    using namespace std;
    
    
    
    int main()
    /*Searches given file and tallys up each TSR's sales in a formatted report 
    by month*/
     {
        multiset<char> ms1;
        
        // Load set1 using the insert method.
        string s1("now is the time for all good men to come ");
        s1.append("to the aid of their country");
    
        ms1.insert(s1.begin(),s1.end());    // Arguments are a pair of iterators
    
        string letters("abcdefghijklmnopqrstuvwxyz");
    
        // count returns the number of keys in the multiset
        // equal to the given value
        for (int i = 0; i < letters.length(); i++) {
            cout << letters[i] << ": " << ms1.count(letters[i]) << endl;
        }
    
      
        cout << "ms1 has " << ms1.size() << " elements" << endl;
        return 0;
    
    }

  5. #5
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Try taking a look into std::map.

    i.e.
    std::map< std::string, std::list<Sale> >

    That way, you can do something like:
    Code:
    std::map< std::string, std::list<Sale> > mapOfSales
    
    mapOfSales["r1"].push_back(Sale("boots", "$500"));
    ...
    
    //For each salesman/saleswoman:
    for(std::map< std::string, std::list<Sale> >::iterator mapIt = mapOfSales.begin();
       mapIt != mapOfSales.end(); ++mapIt)
    {
       //Display the ID of this particular salesman
    
       //For each sale he/she made:
       for(std::list<Sale>::iterator listIt = (*mapIt).begin();
          listIt != (*mapIt).end(); ++listIt)
       {
          //Display the details of the sale
       }
    }
    Otherwise, you might like to look into a std::multimap, though I haven't had experience with them.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  6. #6
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    **Didn't want to edit my post, because that would kill the indentation in the code and I'm too lazy to fix it..

    Made a mistake, everywhere you see (*mapIt), it should actually be (mapIt->second).

    If you just want the number of sales, you can do:
    Code:
    std::map<std::string, int> theMap;
    ...
    //each time you come across a sale by "r1":
    (theMap["r1"])++;
    ...
    for(std::map<std::string, int>::iterator mapIt = theMap.begin(); mapIt != theMap.end(); ++mapIt)
       std::cout << mapIt->first << " made " << mapIt->second << " sales.\n";
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  7. #7
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    Here's what I got in terms of data to use

    The sales person's id is at location (513,2) on a line. Each line is a sale.
    I need to bring in one person's ID and count how many lines(sales) that ID has. Then go to the next ID making sure that the previous ID's don't equal the present one.
    And then out put something like this
    Report for December
    TSR(sales person) Orders
    r1 8
    r2 9
    f3 15
    t2 12
    g2 7
    t3 11
    r2 14
    y1 19

    Total 95

    No other data of the source file is needed just the id and how many sales each ID got.

  8. #8
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>making sure that the previous ID's don't equal the present one.
    I don't get it, why does it matter what the previous ID was?

    Go through my second example, you can very very easily adapt it to your needs. In fact, the part that I've written should work pretty much without change; all you need to do is to put the code into a loop where you read a line, get the salesperson's ID, and increase their 'sales' count. Then, the last bit of code in my example will print the table for you, pretty much exactly as you said. The loop you've already got written (the one you posted originally) is about 75% there already.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  9. #9
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    After I sent up my last post I saw your last reply but I'm still having problems with loading the map has to be a char*??

    Here's my code I'm trying
    Code:
    std::map<std::string, int> theMap;
    while (getline(source,line))
    {
        
        theMap.insert(line.substr(513,2));
    }
    
    //each time you come across a sale by "r1":
    (theMap["r1"])++;
    
    for(std::map<std::string, int>::iterator mapIt = theMap.begin(); mapIt != theMap.end(); ++mapIt)
       std::cout << mapIt->first << " made " << mapIt->second << " sales.\n";
    
        return 0;
    }
    With this modified would I be able to cycle through each salesperson to output each ID's sales and then total up everything at the end?
    Thanks again for all the help

  10. #10
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    >>making sure that the previous ID's don't equal the present one.
    I don't get it, why does it matter what the previous ID was?

    What I mean is that the ID repeats and when that ID repeats wouldn't it just count how many times that ID exists all over again?

  11. #11
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    This is the error I get with using
    theMap.insert(line.substr(513,2));

    :\Documents and Settings\tbixler\Desktop\parser\TSR Reports\TSR Reports.cpp(48) : error C2664: 'struct std:air<class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std:air<class std::ba
    sic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int>,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct s
    td::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::iterator,bool> __thiscall
    std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::insert(const
    struct std:air<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int> &)' : cannot convert parameter 1 from 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' to
    'const struct std:air<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int> &'
    Reason: cannot convert from 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' to 'const struct std:air<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,i
    nt>'
    No constructor could take the source type, or constructor overload resolution was ambiguous

    Sorry for the length of the errror ....

  12. #12
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    This is the error I get with using theMap.insert(line.substr(513,2));
    Yes, insert() takes a std:pair<key_type, value_type>, in this case std:pair<std::string, int>. What's convenient though, is that the [] operator automagically inserts a new key/value pair into the map if one doesn't already exist with the same key. So when you reach this line:
    Code:
    (theMap[line.substr(513,2)])++;
    If the ID/count pair weren't already inserted into the map, then it will automatically be inserted here, and then the value will be incremented. Also, I'm not 100% sure about this, but I believe it will initialize count to 0 when it is inserted (I ran a test and it initialized it to 0, but it might have just been because of debugging stuff the compiler added). So instead of doing an insert(), just put the ++ line in there.

    In case it doesn't initialize it to 0 though, you can do this to ensure that it does what you want:
    Code:
    std::map<...>::iterator it = theMap.find(line.substr(523,2));
    if(it == theMap.end()) //If no entries counted yet
       theMap[line.substr(523,2)] = 1; //Then add it, and initialize it to a count of 1
    else
       (it->second)++; //Otherwise, increase the counter.
    Just to note, (a map's iterator)->first is the 'key' of the pair, in this case the std::string that you use as the 'index', while ->second is the 'value' of the pair, in this case the int counter.

    If you have any questions about how it all works, feel free to ask (I don't know how much of this you already know and understand, you seem to know a fair bit, so I won't explain unless you don't understand).

    Hope this helps! :)
    Last edited by Hunter2; 01-28-2005 at 01:38 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  13. #13
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    Here's what i ended up with:

    Code:
    TsrGrouper(string inSource2)
    /*Searches given file and tallys up each TSR's sales in a formatted report 
    by month*/
     {
        ifstream source(inSource2.c_str());
        string line;
        int total=0;
        std::map<std::string, int> theMap;
        while (getline(source,line))
        {
        
            theMap[line.substr(513,2)]++;
        }
        for(std::map<std::string, int>::iterator mapIt = theMap.begin(); mapIt != theMap.end(); ++mapIt)
        {
            cout << mapIt->first << " made " << mapIt->second << " sales.\n";
            total+=mapIt->second;
        
        }
        cout<<"Total Sales: "<<total<<endl;
        return 0;
    }
    It works great I added the total sales to make sure no lines were missed so the counts for the files should be right.
    Thanks alot I wasn't quite sure how the code was coming out till it actually ran... Automagically!!!
    Thanks again.

  14. #14
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Always glad to help. I hope you really learned how it all works, because maps are a little confusing at first, but they're a very powerful tool to keep in your backyard when you need them
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A very long list of questions... maybe to long...
    By Ravens'sWrath in forum C Programming
    Replies: 16
    Last Post: 05-16-2007, 05:36 AM
  2. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  3. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  4. a simple algorithm and questions
    By ustuzou in forum C++ Programming
    Replies: 0
    Last Post: 02-18-2002, 11:12 AM