Opps. Overlooked a condition. Output has 60 obs, they contains some duplicated key, But This will be easy to handle at all.
data temp(drop=i ); do i=100 to int(sqrt(99999)); x=i**2; a1=int(x/10000); a2=mod(int(x/1000),10); a3=mod(int(x/100),10); a4=mod(int(x/10),10); a5=mod(x,10); output; end; run; data want(keep=a: b: c:); if 0 then set temp; declare hash ha1(dataset:'temp',ordered: 'a'); declare hiter hi1('ha1'); ha1.definekey('x'); ha1.definedata('a1','a2','a3','a4','a5'); ha1.definedone(); if 0 then set temp(rename=(a1-a5=b1-b5)); declare hash ha2(dataset:'temp(rename=(a1-a5=b1-b5))',ordered: 'a'); declare hiter hi2('ha2'); ha2.definekey('x'); ha2.definedata('b1','b2','b3','b4','b5'); ha2.definedone(); if 0 then set temp(rename=(a1-a5=c1-c5)); declare hash ha3(dataset:'temp(rename=(a1-a5=c1-c5))',ordered: 'a'); declare hiter hi3('ha3'); ha3.definekey('x'); ha3.definedata('c1','c2','c3','c4','c5');; ha3.definedone(); length k _count _k 4; declare hash ha(ordered: 'a'); declare hiter hi('ha'); ha.definekey('k'); ha.definedata('k','_count'); ha.definedone(); declare hash _ha(ordered: 'a'); declare hiter _hi('_ha'); _ha.definekey('_k'); _ha.definedata('_k'); _ha.definedone(); array _x{*} a: b: c:; do while(hi1.next()=0); do while(hi2.next()=0); do while(hi3.next()=0); do i=1 to dim(_x); _k=_x{i};_ha.replace(); end; if _ha.num_items eq 5 then do; do j=1 to dim(_x); k=_x{j}; rc=ha.find(); if rc=0 then do; _count=_count+1; ha.replace();end; else do; _count=1; ha.add(); end; end; do while(hi.next()=0); if k ne _count then _rc=_ha.remove(key: _count); end; end; if _ha.num_items =0 then output; _ha.clear();ha.clear(); end; end; end; run; x y z 12321 12544 55225 12321 33124 34225 12321 34225 33124 12321 44521 55225 12321 52441 55225 12321 55225 12544 12321 55225 44521 12321 55225 52441 12544 12321 55225 12544 12544 34225 12544 34225 12544 12544 34225 44521 12544 34225 52441 12544 44521 34225 12544 52441 34225 12544 55225 12321 13225 13225 33124 13225 33124 13225 13225 33124 33124 33124 12321 34225 33124 13225 13225 33124 13225 33124 33124 33124 13225 33124 33124 34225 33124 34225 12321 33124 34225 33124 34225 12321 33124 34225 12544 12544 34225 12544 44521 34225 12544 52441 34225 33124 12321 34225 33124 33124 34225 44521 12544 34225 44521 44521 34225 44521 52441 34225 52441 12544 34225 52441 44521 34225 52441 52441 44521 12321 55225 44521 12544 34225 44521 34225 12544 44521 34225 44521 44521 34225 52441 44521 44521 34225 44521 52441 34225 44521 55225 12321 52441 12321 55225 52441 12544 34225 52441 34225 12544 52441 34225 44521 52441 34225 52441 52441 44521 34225 52441 52441 34225 52441 55225 12321 55225 12321 12544 55225 12321 44521 55225 12321 52441 55225 12544 12321 55225 44521 12321 55225 52441 12321
Ksharp
OK. I also got it. The following is completed code. It is really not easy.
data temp(drop=i ); do i=100 to int(sqrt(99999)); x=i**2; a1=int(x/10000); a2=mod(int(x/1000),10); a3=mod(int(x/100),10); a4=mod(int(x/10),10); a5=mod(x,10); output; end; run; data want(keep=a: b: c:); if 0 then set temp; declare hash ha1(dataset:'temp',ordered: 'a'); declare hiter hi1('ha1'); ha1.definekey('x'); ha1.definedata('a1','a2','a3','a4','a5'); ha1.definedone(); if 0 then set temp(rename=(a1-a5=b1-b5)); declare hash ha2(dataset:'temp(rename=(a1-a5=b1-b5))',ordered: 'a'); declare hiter hi2('ha2'); ha2.definekey('x'); ha2.definedata('b1','b2','b3','b4','b5'); ha2.definedone(); if 0 then set temp(rename=(a1-a5=c1-c5)); declare hash ha3(dataset:'temp(rename=(a1-a5=c1-c5))',ordered: 'a'); declare hiter hi3('ha3'); ha3.definekey('x'); ha3.definedata('c1','c2','c3','c4','c5');; ha3.definedone(); length k _count _k 4; declare hash ha(ordered: 'a'); declare hiter hi('ha'); ha.definekey('k'); ha.definedata('k','_count'); ha.definedone(); declare hash _ha(ordered: 'a'); declare hiter _hi('_ha'); _ha.definekey('_k'); _ha.definedata('_k'); _ha.definedone(); array _x{*} a: b: c:; do while(hi1.next()=0); do while(hi2.next()=0); do while(hi3.next()=0); do i=1 to dim(_x); _k=_x{i};_ha.replace(); end; if _ha.num_items eq 5 then do; do j=1 to dim(_x); k=_x{j}; rc=ha.find(); if rc=0 then do; _count=_count+1; ha.replace();end; else do; _count=1; ha.add(); end; end; do while(hi.next()=0); if k ne _count then _rc=_ha.remove(key: _count); end; end; if _ha.num_items =0 then output; _ha.clear();ha.clear(); end; end; end; run; data x; set want; length x y z $ 10; x=cats( of a:); y=cats( of b:); z=cats( of c:); keep x y z; run; data xx(drop=i j); set x; array a{*} $ 32 x y z; do i=1 to dim(a)-1; do j=i+1 to dim(a); if a{i} eq a{j} then delete; end; end; run; data xx;set xx;k+1;run; data xxx(keep=x y z ); if _n_ eq 1 then do; if 0 then set xx(rename=(x=_x y=_y z=_z)); declare hash ha(dataset:'xx(rename=(x=_x y=_y z=_z))' ); declare hiter hi('ha'); ha.definekey('k'); ha.definedata('k','_x','_y','_z'); ha.definedone(); end; set xx; flag=0; rc=hi.first(); do while(rc=0); s=catx(' ',of x y z _x _y _z); a=count(s,strip(x)); b=count(s,strip(y)); c=count(s,strip(z)); if a eq 2 and b eq 2 and c eq 2 then do;flag=1; _k=k; end; rc=hi.next(); rx=ha.remove( key : _k ); end; if flag then output; run;
Ksharp
Very nice KSharp, glad you liked it.
Your code will complete it comprable time with the other methods I can actually run (no SAS/OR or SAS/IML here).
By changing you seed data to a more limited set that fits the end result better the runtime improves dramatically:
data temp;
array a[5];
do i=100 to 236;
x=i**2;
do d=1 to dim(a);
a
end;
if max(of a
do; j+1;
call symput('vmax',j);
output;
end;
end;
keep x a1-a5;
run;
You are actually still missing the 6th condition to weed the 7 results you have down to a single answer. I missed this clue myself at first.
PC SAS 9.1.3, no SAS/OR (otherwise PROC CLP constraint programming would be fun to play with in addition to PROC OPTMODEL). Can't vouch for efficiency, but it works.
%let r1= 100;
%let r2= 316;
data soln(keep=c1-c3 dUsedOnce);
do i = &r1 to &r2; *--- generate combinations;
c1 = put( i*i, z5. );
do j = i+1 to &r2;
c2 = put( j*j, z5. );
do k = j+1 to &r2; *--- using i+1 and j+1 generates lower triangular only;
c3 = put( k*k, z5. );
link Chkit; *--- check this combination;
end;
end;
end;
return;
Chkit:
length c1-c3 $ 5 str15 $ 15;
array digit[10] $ d1-d10 ('1','2','3','4','5','6','7','8','9','0');
array used[10] u1-u10;
array freq[10] f1-f10;
str15 = cat( c1, c2, c3 );
do d = 1 to 10; *--- calc freq and used indicator;
freq
used
if freq
end;
if sum(of used
do d = 1 to 10;
if used
if freq
if used[freq
do p = 1 to d-1; *--- if p is used, must be different # of times;
if used
> 0 then if freq
= freq
end;
end;
end;
output;
return;
run;
proc sql;
select * from soln group by dUsedOnce having count(*)=1;
quit;
Hats off to PROC FCMP, very nice approach. Never used it, so I learned something valuable out of this.:smileygrin:
Message was edited by: DLing (minor cleanup)
I rewrote again trying to just shorten the program to a single datastep. I cheated a little by just seeding the 9 numbers to the nbr array, with a few additional loops it could be simulated to calculate then I guess.
data _null_;
array nbr[9] (12321 12544 13225 33124 34225 35344 44521 52441 55225);
array nfreq[5];
array freq[5];
length u $256;
retain u '';
array kfreq[5];
do i=1 to comb(9,3);
call allcomb(i,3,of nbr
yes=0;
do ii=1 to 5;
nfreq[ii]=length(compress(cats(of nbr1-nbr3),ii,'k'));
freq[ii]=nfreq[ii];
if nfreq[ii] ne ii then yes+1;
if nfreq[ii]=1 then k=ii;
end;
call sortn(of nfreq
if yes=5 and cats(of nfreq
do;
do j=1 to 5;
if freq
end;
do kk=1 to 5;
kfreq[kk]=length(compress(u,kk,'k'));
if kfreq[kk]=1 then call symput('k',kk);
end;
output;
end;
end;
proc print noobs; var nbr1-nbr3; where k=&k;
run;
Updated, had an error in original posting;
Yes. My result is same as RobPratt's which get all seven possible solution. I like it.
I prefer to ignore the sixth clue, only consider these five conditions, That is the reason why we need computer.
Actually I learn a lot from this task. It really promoted my coding skill a lot.
Ksharp
Glad you liked it Ksharp. You should check out my new post about creating a text cipher.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.