Re: Teaching new tricks to an old dog (C++ -->Ada)

From: Ioannis Vranos (ivr_at_remove.this.grad.com)
Date: 03/22/05


Date: Tue, 22 Mar 2005 22:03:40 +0200

Georg Bauhaus wrote:

> Hm. Searching a *map* of entries at numeric keys is different
> from scanning an array of values and counting occurences. What
> are you trying to do here?

Just using the appropriate available container. :-)

> The std::vector is missing an instantiation argument which adds
> the guarantee that no index value is outside the range
> -800_000..12_000_000;

vector provides method at() that performs range checking. Also if you
want a vector that has signed integer subscripts or even floating point,
you can easily write one. However this does not "feel" C++ whose built
in arrays always store elements from index 0 and upwards.

> std::map<int, double> is a different beast entirely, with
> unknown size. Consider Vector ( -47..600);
>
> (How do you make a subrange of double, which is missing from
> your example.)

Do you mean like this?

#include <map>
#include <iostream>

int main()
{
    using namespace std;

    map<double, double> id;

    id[-400.1]= 7.1;

    id[-2500.6]= -1;

    id[10.43]= 9;

    id[-300.65]= 7.1;

    unsigned counter= 0;

    for(map<double, double>::const_iterator p= id.begin(); p!=id.end(); ++p)
    {
        if(p->second== 7.1)
        {
            cout<<"7.1 was found at index "<<p->first<<"\n";

            ++counter;
        }
    }

    cout<<"\n7.1 was found "<<counter<<" times in total.\n";
}

C:\c>temp
7.1 was found at index -400.1
7.1 was found at index -300.65

7.1 was found 2 times in total.

C:\c>

You can also check the entire range if you want. Here the previous style
along with your full-range (expensive) style:

#include <map>
#include <iostream>

int main()
{
    using namespace std;

    map<int, double> id;

    id[-400]= 7.1;

    id[-2500]= -1;

    id[10]= 9;

    id[-300]= 7.1;

    unsigned counter= 0;

    for(map<int, double>::const_iterator p= id.begin(); p!=id.end(); ++p)
    {
        if(p->second== 7.1)
        {
            cout<<"7.1 was found at index "<<p->first<<"\n";

            ++counter;
        }
    }

    cout<<"\n7.1 was found "<<counter<<" times in total.\n\n\n";

    // Checks *each* range from -2500 to 10
    counter=0;
    for(int i= -2500; i<10; ++i)
    {
         if(id[i]== 7.1)
         {
             cout<<"7.1 was found at index "<<i<<"\n";

             ++counter;
         }
     }

     cout<<"\n7.1 was found "<<counter<<" times in total.\n";
}

"for(int i= -2500; i<10; ++i)" can also be written as

for(int i= id.begin()->first; i<(--id.end())->first; ++i)

if you want this kind of abstraction. But better abstraction is the
iterator approach and the *best* the count family which (iterator and
count family) work with *all* containers.

These are bullet-proof code approaches.

> Imagine an array shared between a number of threads. The program's
> task is to count the number of occurences of a particular value
> in the array. Examples:
> 1) A shop has 10 unique doors (use an enum).

We can use whatever I like, perhaps strings. What is wrong with "Door 1"
etc? :-)

> For each door 4 states
> can be measured: open/closed, van/no van at the door.

OK, this sounds easy. What do you think? Since you want an array:

#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>

class Door
{
     bool open, van;

     public:
         Door(){ open= van= true; }

         bool IsOpen() const { return open; }
         bool IsClosed() const { return !open; }
         bool IsVan() const { return van; }
         bool IsNoVan() const { return !van; }

         Door &SetOpen() { open= true; return *this; }
         Door &SetClosed() { open= false; return *this; }
         Door &SetVan() { van= true; return *this; }
         Door &SetNoVan() { van= false; return *this; }
};

class CheckOpen
{
     bool open, van;

     public:
         CheckOpen(bool isopen, bool isvan):open(isopen), van(isvan) {}

         bool operator() (const Door &arg)
         {
             return open== arg.IsOpen() && van== arg.IsVan();
         }
};

int main()
{
     using namespace std;

     vector<Door> doors(10);

     doors[4].SetOpen().SetNoVan();

     unsigned counter= count_if(doors.begin(), doors.end(),
                                              CheckOpen(true, false));

     cout<<"Counted "<<counter<<" occurrences.\n";
}

C:\c>temp
Counted 1 occurrences.

C:\c>

> 2) A 5-player team, each team is identified by number drawn from a fixed
> set of team numbers. An array (an array, not some other data
> structure) measures the number of players from each team present in
> a room. Count the number of odd-team players in a room.

This is easy too. I do not get your point. This can be done with arrays
as also with other containers. Why should we be restricted to one type
of container?

> I hope these example illustrate some points. They are not meant to
> trigger a discussion as to whether an array is the best data
> structure for everything. (Note that it might be necessary to read
> values from the array/Vector using random access in O(1), and to
> store and replace values in O(1), another reason to use an array.)

OK.

>> In C++ you can create whatever you want. Even a container with
>> abstract conceptual features (you are limited only by your imagination).
>
>
> You can do that using assembly language or SmallTalk, whatever.
> I think this was not the point, but I should have Richard Riehle's
> message speak for itself.

I am not talking about assembly. It is not difficult to write a
container getting a signed integer as a subscript and have range checking.

> For example, look here, and reconsider the programming task as
> originally stated:
>
>>> Yes, I know you can do this in C++, but
>>> from my
>>> perspective, it is not nearly as easy, expressive, or readable.

I think it is probably more and at least the same. That said, I like Ada
somewhat. :-)

-- 
Ioannis Vranos
http://www23.brinkster.com/noicys


Relevant Pages

  • Re: Ada Popularity: Comparison of Ada/Charles with C++ STL (and Perl)
    ... array), although every array may have semantics of container. ... for this reason containers shouldn't be all treated as abstract arrays, ... >> for wrapped type's iterators with wrappers for wrapped type's iterators' ... wrapper for containers here... ...
    (comp.lang.ada)
  • Re: Teaching new tricks to an old dog (C++ -->Ada)
    ... > from scanning an array of values and counting occurences. ... if you want this kind of abstraction. ... count family) work with *all* containers. ...
    (comp.lang.cpp)
  • Internals and complexity of types, containers and algorithms
    ... I am new to python and I miss some understanding of the internals ... of some types and containers. ... Is a dict a tree or a hash array and what is the ...
    (comp.lang.python)
  • Re: Teaching new tricks to an old dog (C++ -->Ada)
    ... >> from scanning an array of values and counting occurences. ... not about functions operating on containers. ... The compiler won't tell you that there is something wrong ... given a language that allows the enum as a basis for the construction ...
    (comp.lang.ada)
  • Re: Teaching new tricks to an old dog (C++ -->Ada)
    ... >> from scanning an array of values and counting occurences. ... not about functions operating on containers. ... The compiler won't tell you that there is something wrong ... given a language that allows the enum as a basis for the construction ...
    (comp.lang.cpp)