BookmarkSubscribeRSS Feed
Ksharp
Super User

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

Ksharp
Super User

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

FriedEgg
SAS Employee

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=substrn(x,d,1);

  end;

  if max(of a

  • )<=5 and min(of a
  • )>0 then
  •    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.

    DLing
    Obsidian | Level 7

    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 = countc( str15, digit );
            used = ( freq > 0 );
            if freq = 1 then dUsedOnce = digit;
        end;
        if sum(of used

  • ) ~= 5 then return;            *--- use 5 different digits;

  •     do d = 1 to 10;
            if used then do;                         *--- if d is used;
                if freq = d then return;             *--- not used its own # of times;
                if used[freq] = 0 then return;       *--- freq is used;
                do p = 1 to d-1;                        *--- if p is used, must be different # of times;
                    if used

    > 0 then if freq

    = freq then return;
                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)

    FriedEgg
    SAS Employee

    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

  • )='12345' then
  •    do;

        do j=1 to 5;

         if freq=1 then u=cats(of u j);

        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;

    Ksharp
    Super User

    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

    FriedEgg
    SAS Employee

    Glad you liked it Ksharp.  You should check out my new post about creating a text cipher.

    http://communities.sas.com/thread/31296?tstart=0

    SAS Innovate 2025: Register Now

    Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
    Sign up by Dec. 31 to get the 2024 rate of just $495.
    Register now!

    How to Concatenate Values

    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.

    SAS Training: Just a Click Away

     Ready to level-up your skills? Choose your own adventure.

    Browse our catalog!

    Discussion stats
    • 21 replies
    • 5962 views
    • 10 likes
    • 6 in conversation