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.
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
For me, it would be logical that rules 7 (-512),10 (-64) and 14 (-4) were hit as those sum up to -580.
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
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).
OMG!
Well, that's what can come from not being a native speaker. Corrected it.
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;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.
Find more tutorials on the SAS Users YouTube channel.