[fpc-pascal] best method: multiple three state options in a decision tree

waldo kitty wkitty42 at windstream.net
Wed Jan 22 22:23:58 CET 2014


On 1/22/2014 12:12 PM, Lukasz Sokol wrote:
[...]
> If you insist on using bits.... define them:

it isn't that i'm insisting on using them... more the way that my linear mind 
sees them... i'm trying to change this if it affords me better code that is 
easier to read, understand and modify...

> const
>    OptionAmmMin = $0001;
>    OptionAmmMinMax = $0002;
>    OptionAmmMax = $0004; // and so on

this is pretty much already being done by the code using SetBIT and GetBIT

> then do
>
> if Options and (OptionAmmMin and ... ) then

this is where the CASE "decision tree" comes in with each CASE having the 
necessary if/then filtering of the data record at hand...

> I would have thought, that having an array of TOption like I wrote, would
> ensure the exclusivity.
> And having the array dynamic, you can check for its size, then write some clever code to use it ;)

it may very well but as i wrote, i cannot visualize it in my mind's eye :(

>> yes, i've basically been ignoring mmNone because all the bits are off so we just skip over it in the ANDing code
>>
>>> If there is a lot of options, but not always consecutive - so there would be a lot more of mmNone's
>>> than significant states (IOW the data is sparse) -
>>
>> yes, with what i have done, there are 1023 valid combination... 1024
>> if we count all options off (or mmNone)... that's out of 32767
>> combinations where the majority are invalid... it is no wonder, with
>> 1023 combinations, that i got lost/confused with my first attempt
>> using if/then/else and while trying to manually implement the bitmap
>> CASE code...
>
> If you count permutations (so combinations not repeating) you'd have 120 valid ones...?
> http://easycalculation.com/statistics/permutation-combination.php
> do I understand that correctly?

there are 1023 permutations of the 32767 possible... that means that i have to 
have 1023 (1024 counting no options set) case selectors... each with their 
specific if/then to check the current data record for a match...

>> [...]
>>
>> i think i should be able to use one routine for both input selection
>> and output filtering... done by pass the bitmap and the routine to be
>> used... that'll save having to worry about editing in more than one
>> place when things change... i just gotta figure out how to pass the
>> routine to use...>
>> would something like:
>>
>>    procedure runCase(var bitMap:word; whichProcedure: pointer);
>>
>> called with
>>
>>    runCase(SelectBits, at addItem);
>>
>>    runCase(FilterBits, at writeoutput);
>>
>> be the way to do this??
>>
>> sometimes my linear procedural mind really gets in the way :/
>>
>
> Huh, well a lot of micro-management goes on here;

possibly ;)  but i don't know...

> What if you did it like:
>
> - define the valid bit masks (permutations?) at the start, dynamically

humm... my tool that generates the CASE statement does something like this... i 
might be able to adapt it... /BUT/ i still have to match the data records with 
the current permutation selected when the program is executed... don't i??

eg:
     myprogram --optionA=-1,145 --optionD=30,40

on execution, GetOption('optionA') loads the values from the optionA command 
line parameter... any value less than zero means to ignore that "slot"... all 
other numbers are valid...

the above "--optionA=-1,145" results in the optionA_MAX bit being set (00000000 
00000010) and storing the value of 145 in optA_MAX...

the above "--optionD=30,40" results in the optionD_MINMAX bit (00000010 
00000000), storing the value of 30 in optD_MIN, and storing the value of 40 in 
optD_MAX...

ANDing the bitmasks together we have 00000010 00000010 which is 514 in 
decimal... this is the case selector value used later for output filtering (and 
future input selecting)...

then the program loads all of the data records it finds in all of the default 
files... currently this is some 30000 records from some 80+ files updated 
nightly... as the data is loaded, it is merged and updated so there are no 
duplicates records and all records have the most current, by date and time, 
information in them...

after all the merging and updating, we start with the first record and run 
through all of them writing them to the output file... if there are no options 
specified on the command line, then all the records are written... in this 
example, only the records matching the values given for the two options will be 
written to the output file... currently, that's

    514 : begin // 00000010 00000010
            if (Rec^.optA <= optA_MAX) and
               (Rec^.optD >= optD_MIN) and (Rec^.optD <= optD_MAX) then
              writeoutput;
          end;

if you can explain to me how using the arrays would work so that i can visualize 
it like the above, then i can try to implement it... however, i can't see any 
way to bypass the huge CASE statement and its IF comparisons of the data in each 
record... how would using the arrays allow me to do that?

> - associate the procedures (their pointers) to jump to with the valid bit masks in a new data type
> (- do you REALLY have that many procedures ? Or are they somewhat repeating themselves ?)

it will be only two procedures IF i can do it like that... it should be easier 
to use one CASE procedure of the existing ~8000 lines for both (future) input 
selection of matching data records and for (current) output filtering of 
matching data records...

so what i was actually asking is if using a pointer is the proper item for 
passing the procedure to use and is @procA how i would specify that in the call 
to the procedure...

> - then just walk the array of [bit mask, proc pointer] records and jump to pointers supplied if matching?
>
> No ifs, no buts, treat the Options as a bitmask if such is its purpose?
>
> Just a thought,

i really am trying to visualize your suggested methods ;)

-- 
NOTE: No off-list assistance is given without prior approval.
       Please keep mailing list traffic on the list unless
       private contact is specifically requested and granted.



More information about the fpc-pascal mailing list