Author Topic: In ObjectARX or C++ (Challenge) Summation  (Read 6728 times)

0 Members and 1 Guest are viewing this topic.

LE

  • Guest
In ObjectARX or C++ (Challenge) Summation
« on: January 18, 2007, 09:50:22 PM »
This is an extention taken from the AutoLisp forum, here:

http://www.theswamp.org/index.php?topic=14535.0

Quote
Return the sum of values for each class.

-i.e.
 (summation '(("one" 1) ("two" 2) ("three" 3)))
 > one = 1
   two = 2
   three = 3

Further, return the sum of values for each class if there are several instances of each class.
-i.e.
 (summation '(("one" 1) ("two" 2) ("three" 3)
                     ("one" 4) ("two" 5) ("three" 6)
                     ("one" 7) ("two"  8 ) ("three" 9)) )

 > one = 12
   two = 15
   three = 18


Here is one function to do that:

Code: [Select]
//9:53 PM 1/17/2007 by LE
static int ads_getvalues(void)
{
struct resbuf *pArgs = acedGetArgs();
int rCode, val, ad;
CString strKey;
map<CString, int> stringIntMap;
map<CString, int>::const_iterator it;
while (pArgs != NULL)
{
rCode = pArgs->restype;
if (rCode == RTSTR)
{
strKey = pArgs->resval.rstring;
pArgs = pArgs->rbnext;
val = pArgs->resval.rint;
it = stringIntMap.find(strKey);
if (it == stringIntMap.end())
ad = 0;
else
{
ad = (*it).second;
stringIntMap.erase((*it).first);
}
val = val + ad;
stringIntMap.insert(make_pair(strKey, val));
}
pArgs = pArgs->rbnext;
}
if (!stringIntMap.empty())
{
acutPrintf(_T("\nNumber of items on the list are [%d]"), stringIntMap.size());
acutPrintf(_T("\nPairs values are: \n"));
for (it = stringIntMap.begin(); it != stringIntMap.end(); ++it)
acutPrintf(_T("\n[Key: %s = %d]"), (*it).first, (*it).second);
stringIntMap.clear();
acutPrintf(_T("\n"));
}
return (RSRSLT) ;
}


LE

  • Guest
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #1 on: January 18, 2007, 09:57:23 PM »
Here is the same function, but with more control, of knowing if the argument is a list of lists and the appropriates values.

The function return a list with the results.

Code: [Select]
static int ads_getvalues(void)
{
resbuf *pArgs = acedGetArgs();
int rCode, val, ad;
CString strKey;
map<CString, int> stringIntMap;
map<CString, int>::const_iterator it;
while (pArgs != NULL)
{
if (pArgs && pArgs->restype == RTLB &&
pArgs->rbnext && pArgs->rbnext->restype == RTSTR &&
pArgs->rbnext->rbnext && pArgs->rbnext->rbnext->restype == RTSHORT &&
pArgs->rbnext->rbnext->rbnext && pArgs->rbnext->rbnext->rbnext->restype == RTLE)
{
pArgs = pArgs = pArgs->rbnext;
strKey = pArgs->resval.rstring;
pArgs = pArgs->rbnext;
val = pArgs->resval.rint;
it = stringIntMap.find(strKey);
if (it == stringIntMap.end())
ad = 0;
else
{
ad = (*it).second;
stringIntMap.erase((*it).first);
}
val = val + ad;
stringIntMap.insert(make_pair(strKey, val));
}
pArgs = pArgs->rbnext;
}
if (!stringIntMap.empty())
{
resbuf *rbRet = acutBuildList(RTLB, RTNONE), *rb = rbRet;
for (it = stringIntMap.begin(); it != stringIntMap.end(); ++it)
{
rb->rbnext = acutBuildList(RTLB, RTNONE);
rb = rb->rbnext;
rb->rbnext = acutBuildList(RTSTR, (*it).first, RTNONE);
rb = rb->rbnext;
rb->rbnext = acutBuildList(RTSHORT, (*it).second, RTNONE);
rb = rb->rbnext;
rb->rbnext = acutBuildList(RTLE, RTNONE);
rb = rb->rbnext;
}
rb->rbnext = acutBuildList(RTLE, RTNONE);
stringIntMap.clear();
acedRetList(rbRet);
acutRelRb(rbRet);
}
return (RSRSLT) ;
}

From:
Quote
Command: !lst
(("one" 1) ("two" 2) ("three" 3) ("one" 4) ("two" 5) ("three" 6) ("one" 7)
("two" 8 ) ("three" 9) ("one" 1) ("two" 2) ("three" 3) ("one" 4) ("two" 5)
("three" 6) ("one" 7) ("two" 8 ) ("three" 9) ("one" 1) ("two" 2) ("ten" 3)
("six" 4) ("ten" 5) ("four" 6) ("six" 7) ("ten" 8 ) ("four" 9))

To:
Quote
Command: (getvalues lst)
(("four" 15) ("one" 25) ("six" 11) ("ten" 16) ("three" 36) ("two" 32))
« Last Edit: January 19, 2007, 12:11:12 PM by LE »

LE

  • Guest
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #2 on: January 19, 2007, 01:25:41 PM »
And the updated code is here:

Code: [Select]
static int ads_summation(void)
{
[color=green]// get the arguments for the function
// they are pass to the linked list
// using acedGetArgs()[/color]
resbuf *pArgs = acedGetArgs();
[color=green]// variables used for the addition calcs[/color]
long val, ad;
[color=green]// variable to hold the string key
// ("stringkey" longvalue)[/color]
CString strKey;
[color=green]// prepare of the map to hold pairs of
// CString and int (this could be long)[/color]
map<CString, int> stringIntMap;
[color=green]// prepare the iterator that will be used
// to iterate our map[/color]
map<CString, int>::const_iterator it;
[color=green]// walk the linked list of resbuf structures
// making sure is not empty or we are at the
// end of the list[/color]
while (pArgs != NULL)
{
[color=green]// we make a condition to review the type of values
// and make sure it is a list of lists in the form of:
// (list (list stringkey shortvalue) ... )
// the "(" is equal to RTLB and ")" equal to RTLE
// those values are defined in the adscodes.h header
// that comes in the ARX SDK
//
// first we avoid the first "list begins" and just
// take care of the nested lists
//
// then first we make sure there is valid our list
// and the first item is equal to "list begins"[/color]
if (pArgs && pArgs->restype == RTLB &&
[color=green]// and make sure there is a second item
// and it is a string[/color]
pArgs->rbnext && pArgs->rbnext->restype == RTSTR &&
[color=green]// and there is a third item and it is a short value[/color]
pArgs->rbnext->rbnext && pArgs->rbnext->rbnext->restype == RTSHORT &&
[color=green]// and there is a fourth value and it is the end of a list[/color]
pArgs->rbnext->rbnext->rbnext && pArgs->rbnext->rbnext->rbnext->restype == RTLE)
{
[color=green]// the conditions were passed
// now grab the returned values
// and pass them into our variables
//
// first we move the link list one position ahead
// this is the RTLB, we don't need that[/color]
pArgs = pArgs = pArgs->rbnext;
[color=green]// now we are in the string key position
// and pass the value to the variable[/color]
strKey = pArgs->resval.rstring;
[color=green]// we move another position ahead on the link list[/color]
pArgs = pArgs->rbnext;
[color=green]// we are there and get the short value for the variable[/color]
val = pArgs->resval.rint;
[color=green]// now using the find() function, we check if
// the stringkey is already in our map[/color]
it = stringIntMap.find(strKey);
[color=green]// going to the end of our map
// and see if have an element[/color]
if (it == stringIntMap.end())
[color=green]// is not there in the map
// let's make the variable ad = 0[/color]
ad = 0;
else
{
[color=green]// it was in on our map
// let's grab the value from the
// second position on the pair[/color]
ad = (*it).second;
[color=green]// then erase the previous value
// from the map, by just calling
// erase() and using the first item of the pair[/color]
stringIntMap.erase((*it).first);
}
[color=green]// we have here our new values
// that are added and place into our
// variable ad[/color]
val = val + ad;
[color=green]// then we insert the pair into our map
// using insert() and make_pair()[/color]
stringIntMap.insert(make_pair(strKey, val));
}
[color=green]// we move ahead into the link list[/color]
pArgs = pArgs->rbnext;
}
[color=green]// the walk on the link list is done
// we check if the map is not empty[/color]
if (!stringIntMap.empty())
{
[color=green]// we start to build the returned link list to autolisp
// and requires to be in the form of:
// (list (list string long) ... )
// we use acutBuildList() and add the "(" to the begin of
// the list
// and we make another auxiliar resbuf "rb" to walk and add
// the values into the returned list[/color]
resbuf *rbRet = acutBuildList(RTLB, RTNONE), *rb = rbRet;
[color=green]// we use for() and iterate all over the map[/color]
for (it = stringIntMap.begin(); it != stringIntMap.end(); ++it)
{
[color=green]// we open a new list with "("[/color]
rb->rbnext = acutBuildList(RTLB, RTNONE);
[color=green]// walk one step ahead[/color]
rb = rb->rbnext;
[color=green]// and add the string value[/color]
rb->rbnext = acutBuildList(RTSTR, (*it).first, RTNONE);
[color=green]// walk one step ahead[/color]
rb = rb->rbnext;
[color=green]// and add the long value[/color]
rb->rbnext = acutBuildList(RTLONG, (*it).second, RTNONE);
[color=green]// walk one step ahead[/color]
rb = rb->rbnext;
[color=green]// and add the closing of the list ")"[/color]
rb->rbnext = acutBuildList(RTLE, RTNONE);
[color=green]// re asign the link list[/color]
rb = rb->rbnext;
}
[color=green]// we are at the end of the link list
// and we add the last ")"[/color]
rb->rbnext = acutBuildList(RTLE, RTNONE);
[color=green]// clear our map[/color]
stringIntMap.clear();
[color=green]// return the list to autolisp[/color]
acedRetList(rbRet);
[color=green]// release the link list[/color]
acutRelRb(rbRet);
}
return (RSRSLT);
}
« Last Edit: January 23, 2007, 11:26:57 AM by LE »

LE

  • Guest
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #3 on: January 19, 2007, 03:36:40 PM »
It will be interesting to know or do this std::map implementation with C#.... but how?.. I'll try that.

LE

  • Guest
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #4 on: January 19, 2007, 03:56:35 PM »
It will be interesting to know or do this std::map implementation with C#.... but how?.. I'll try that.

Appears to be with this: System.Collections.Generic.Dictionary in .NET 2.0

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6940
  • AKA Daniel
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #5 on: January 19, 2007, 05:23:38 PM »
Hi Luis
you can also look at
System.Collections.Hashtable
and lists using
System.Collections.Generic.KeyValuePair
I have an example here http://www.theswamp.org/index.php?topic=14495.0

LE

  • Guest
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #6 on: January 19, 2007, 10:42:41 PM »
Here is the first step, next is the map part... at least I know how to step into the buffer as I did it with ARX....

Code: [Select]
[LispFunction("Summation")]
//static public ResultBuffer summation(ResultBuffer args)
static public void summation(ResultBuffer args)
{
    Document doc = acadApp.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    //ResultBuffer res = new ResultBuffer();
    Dictionary<string, long> openWith = new Dictionary<string, long>();
    IEnumerator it = args.GetEnumerator();
    while (it.MoveNext())
    {
        TypedValue val = (TypedValue)it.Current;
        // ignore start or end of list
        short RTLB = 5016, RTLE = 5017;
        if (val.TypeCode == RTLB || val.TypeCode == RTLE)
        {
        }
        else
        {
            string s;
            s = string.Format("\nKeyType {0} StringValue {1}", val.TypeCode, val.Value);
            // string-key
            ed.WriteMessage(s);

            it.MoveNext();
            val = (TypedValue)it.Current;
            // short-value
            s = string.Format("\nKeyType {0} ShortValue {1}", val.TypeCode, val.Value);
            ed.WriteMessage(s);

        }
    }
    //return res;
}

Returns on the command line:

Quote
Command: (summation lst)
KeyType 5005 StringValue one
KeyType 5003 ShortValue 1
KeyType 5005 StringValue two
KeyType 5003 ShortValue 2
KeyType 5005 StringValue three
KeyType 5003 ShortValue 3
KeyType 5005 StringValue one
KeyType 5003 ShortValue 4
KeyType 5005 StringValue two
KeyType 5003 ShortValue 5
KeyType 5005 StringValue three
KeyType 5003 ShortValue 6
KeyType 5005 StringValue one
KeyType 5003 ShortValue 7
KeyType 5005 StringValue two
KeyType 5003 ShortValue 8
KeyType 5005 StringValue three
KeyType 5003 ShortValue 9

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6940
  • AKA Daniel
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #7 on: January 19, 2007, 11:13:15 PM »
... at least I know how to step into the buffer as I did it with ARX....

You can also change your resultbuffer to an array or list

Code: [Select]
TypedValue[] value = args.AsArray();
List<TypedValue> lisplist = new List<TypedValue>(args.AsArray());

LE

  • Guest
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #8 on: January 20, 2007, 01:30:19 PM »
... at least I know how to step into the buffer as I did it with ARX....

You can also change your resultbuffer to an array or list

Code: [Select]
TypedValue[] value = args.AsArray();
List<TypedValue> lisplist = new List<TypedValue>(args.AsArray());

Thank you Daniel.


I see the lack of interest (with a few exemptions) on these type of solutions, well I see that as something normal here, I'll continue on my own.... the topic is now close, thanks to ALL.

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9261
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #9 on: January 20, 2007, 10:47:48 PM »
What do you mean `Lack of interest'? I'm still trying to figure out the first one...
“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #10 on: January 20, 2007, 11:57:14 PM »
Quote
.. (with a few exemptions)

I'm exempt :-) , I just don't understand the code yet.


.. John, there is a statute of limitations on Luis's posts, you must reply in 24 hours or they self destruct.


... Luis, I learn from all your posts .. thanks.
« Last Edit: January 21, 2007, 12:05:23 AM by Kerry Brown »
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

LE

  • Guest
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #11 on: January 21, 2007, 01:07:10 PM »
What do you mean `Lack of interest'? I'm still trying to figure out the first one...

If you want to understand the algorithm and the usage of each of the functions, I have added descriptions to my previous posted function, here:

http://www.theswamp.org/index.php?topic=14600.msg176311#msg176311


HTH.

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9261
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #12 on: January 21, 2007, 01:48:41 PM »
What do you mean `Lack of interest'? I'm still trying to figure out the first one...

If you want to understand the algorithm and the usage of each of the functions, I have added descriptions to my previous posted function, here:

http://www.theswamp.org/index.php?topic=14600.msg176311#msg176311


HTH.

yes that helps a lot. Thank you.
“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6940
  • AKA Daniel
Re: In ObjectARX or C++ (Challenge) Summation
« Reply #13 on: January 21, 2007, 05:40:08 PM »
That’s nice Luis.
Commenting the code is one thing I really need to do a better job at when posting examples.