Calcite | Level 5

## Working out data set based on rule scoring

Hi - please bear with me here.

I have a 3rd party data source that provides us data based on specific conditions an order has hit. We do not know which conditions were hit so cannot analyse any data. Within the data, we do get a score set and i have managed to give each condition its own score based on bits:

 Rule Weight 1 -32768 2 -16384 3 -8192 4 -4096 5 -2048 6 -1024 7 -512 8 -256 9 -128 10 -64 11 -32 12 -16 13 -8 14 -4 15 -2 16 -1

The idea is, that if the score is -580, there are only 3 rules it could possibly be (7,10,14), or -65535 it would have hit all 16 - so we can then know which rules were hit.

My question is: Is there a way of coding into sas a way to work out which rules were hit? Working it out manually for each score would take an age.

I hope i have explained myself? Any help is much appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions
Super User

## Re: Working out data set based on rule scoring

See my take:

``````data rules;
infile datalines dlm='09'x dsd;
input rulenumber rulevalue;
datalines;
1	-32768
2	-16384
3	-8192
4	-4096
5	-2048
6	-1024
7	-512
8	-256
9	-128
10	-64
11	-32
12	-16
13	-8
14	-4
15	-2
16	-1
;
run;

data have;
input value;
datalines;
-580
;
run;

data want;
if _n_ = 1
then do;
array rules {16} _temporary_;
do i = 1 to 16;
set rules;
rules{i} = rulevalue;
end;
end;
set have;
_val = value;
length rules_hit \$100;
do i = 1 to dim(rules);
put _val=;
put rules{i}=;
if _val <= rules{i}
then do;
rules_hit = catx(',',rules_hit,put(i,2.));
_val = _val - rules{i};
end;
end;
keep value rules_hit;
run;

proc print data=want noobs;
run;``````

Result:

```value    rules_hit

-580    7,10,14
```
6 REPLIES 6
Super User

## Re: Working out data set based on rule scoring

For me, it would be logical that rules 7 (-512),10 (-64) and 14 (-4) were hit as those sum up to -580.

Calcite | Level 5

## Re: Working out data set based on rule scoring

Correct - i was looking at the wrong numbers!
Super User

## Re: Working out data set based on rule scoring

See my take:

``````data rules;
infile datalines dlm='09'x dsd;
input rulenumber rulevalue;
datalines;
1	-32768
2	-16384
3	-8192
4	-4096
5	-2048
6	-1024
7	-512
8	-256
9	-128
10	-64
11	-32
12	-16
13	-8
14	-4
15	-2
16	-1
;
run;

data have;
input value;
datalines;
-580
;
run;

data want;
if _n_ = 1
then do;
array rules {16} _temporary_;
do i = 1 to 16;
set rules;
rules{i} = rulevalue;
end;
end;
set have;
_val = value;
length rules_hit \$100;
do i = 1 to dim(rules);
put _val=;
put rules{i}=;
if _val <= rules{i}
then do;
rules_hit = catx(',',rules_hit,put(i,2.));
_val = _val - rules{i};
end;
end;
keep value rules_hit;
run;

proc print data=want noobs;
run;``````

Result:

```value    rules_hit

-580    7,10,14
```
PROC Star

## Re: Working out data set based on rule scoring

As @Kurt_Bremser has demonstrated, it's easy enough for a computer to calculate all the possibilities.  While I disagree with his choice of variable names (ruleshit), here is what might be a simpler way:

data combos;

array rule {16};

do rule1=0, -32768;

do rule2=0, -16384;

do rule3=0, -8192;

do rule4=0, -4096;

do rule5=0, -2048;

do rule6=0, -1024;

do rule7=0, -512;

do rule8=0, -256;

do rule9=0, -128;

do rule10=0, -64;

do rule11=0, -32;

do rule12=0, -16;

do rule13=0, -8;

do rule14=0, -4;

do rule15=0, -2;

do rule16=0, -1;

total = sum(of rule1-rule16);

length rules_hit \$ 40;

rules_hit = ' ';

do k=1 to 16;

if rule{k} ne 0 then rules_hit = catx(',' , rules_hit, k);

end;

output;

end; end; end; end; end;

end; end; end; end; end;

end; end; end; end; end;

end;

keep total rules_hit;

run;

This allows you to sort and merge with your scores (or perhaps some other form of look-up).

Super User

## Re: Working out data set based on rule scoring

OMG!

Well, that's what can come from not being a native speaker. Corrected it.

## Re: Working out data set based on rule scoring

You can easily extract the rule numbers by examining the bit string of the positive value of value.  Here I do it as a 16 byte character variable.

``````data have;
input value;
bitvalue = put(-value,binary16.);
f=findc(bitvalue,'1',1);
length ruleshit \$64;
do while(f);
ruleshit = catx(', ',ruleshit,f);
f = f + 1;
f=findc(bitvalue,'1',f);
end;
drop f;
datalines;
-580
-321
-0
-512
-65535
;;;;
run;``````

Discussion stats
• 6 replies
• 624 views
• 1 like
• 4 in conversation