BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
ilikesas
Barite | Level 11

Hi,

 

I am trying to replicate a math problem (for more info see the 4 min video https://www.youtube.com/watch?v=m4CjXk_b8zo)

 

I am doing a loop for numbers 1 to 10. For each number, if it is even then it becomes number/2, and if it is odd then it becomes 3*number+1. I stop the loop for each number when the number becomes 4, and then I go to the next number.

For each number I want to count how many steps until the number becomes 4.  

 

 

 

Here is my code:

 

data problem;
do i = 1 to 10;
count = 0;
number = i;
  do while (number ne 4);
    if mod(number,2) = 0 then number = number/2;
    else number = 3*number +1;
    count = count +1;
    output; 
   end;
end;
run;           

I get the result that I want, but the output gives me all the steps for each i. Is it possible to get only the last step for each i?

 

 

Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions
ilikesas
Barite | Level 11

Strictly speaking, you are right that according to the video the number always reduced to 4 when the process was done in a supercomputer. 

To summarize for future readers, the solution is the one given by KSharp. It is basically what I did but the "output" is placed in a different stage which allows to output only the last iteration for each i:

 

data problem;
do i = 1 to 10;
count = 0;
number = i;
  do while (number ne 4);
    if mod(number,2) = 0 then number = number/2;
    else number = 3*number +1;
    count = count +1;
   end;
   output;
end;
run;  

Please note that the remark of Astounding is very important in that the code can potentally run an infinite loop if for a certain i the number never reaches 4, so in such a case it would be safe to modify the do while statement into a do statement such as "do k=1 to 5000 while (number ne 4);"

View solution in original post

10 REPLIES 10
mkeintz
PROC Star

This program does what you ask, and write out the numeric sequence for each starting point:

 

data _null_;

  do I=1 to 10;

    count=0;

    put "Start=" I @;

    do N=I by 0 until (N=4);

      if mod(N,2)=0 then N=N/2;

      else N=1+3*N;

      put +(-1)',' N @;

      count+1;

    end;

    put  +3 count=;

  end;

run;

 

 

Sorry - misread your post.  I think you want the next_to_last value of N before N=4, and as you said you don't want the sequence:

 

data want (keep=START next_to_last count);

  do START=1 to 10;

    count=0;

    do N=START by 0 until (N=4);

      if mod(N,2)=0 then N=N/2;

      else N=1+3*N;

      count+1;

      next_to_last=coalesce(lag(n),start);

    end;

    put start= count= next_to_last=;

    output;

  end;

run;

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
ilikesas
Barite | Level 11

Hi mkeintz,

 

thanks for the code, I didn't know that so much computation can be done with PUT.

 

Your first code does actually give the result that my code gets, its just that I want to have the last (and not before last) iteration for each i.

 

Thanks!

mkeintz
PROC Star
Then I don't understand what you mean by "the last iteration"? Since by definition of the problem the last iteration is N=4.
--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Astounding
PROC Star

You already got the right suggestion, moving the OUTPUT statement.  Here's one more, just on general principles.  

 

Your DO WHILE loop is dangerous.  What if the logic never arrives at NUMBER=4?  In theory, at least, you could be writing an infinite loop.  It would be safer to have two ways that the loop might end, such as:

 

do k=1 to 5000 while (number ne 4);

mkeintz
PROC Star

It's not dangerous in this case.  According to the youtube videa every starting number up to 2**60 has been test and will ultimately arrive at 1  (and the next step would be 4).

 

MK

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Astounding
PROC Star

Don't take this seriously, but ...

 

You heard it on the internet, so it must be true?

mkeintz
PROC Star

In the case of this video,which reviewed the history of this problem, I am confident of the assertion - even though it was reported on the internet.

 

MK

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
ilikesas
Barite | Level 11

Strictly speaking, you are right that according to the video the number always reduced to 4 when the process was done in a supercomputer. 

To summarize for future readers, the solution is the one given by KSharp. It is basically what I did but the "output" is placed in a different stage which allows to output only the last iteration for each i:

 

data problem;
do i = 1 to 10;
count = 0;
number = i;
  do while (number ne 4);
    if mod(number,2) = 0 then number = number/2;
    else number = 3*number +1;
    count = count +1;
   end;
   output;
end;
run;  

Please note that the remark of Astounding is very important in that the code can potentally run an infinite loop if for a certain i the number never reaches 4, so in such a case it would be safe to modify the do while statement into a do statement such as "do k=1 to 5000 while (number ne 4);"

Ksharp
Super User

I like idea of @Astounding . Safety first. If any problem occurred in the code of LOOP ,that would lead to infinite iterative, you have to stop sas session by hand, that doesn't sound good .

Ksharp
Super User
data problem;
do i = 1 to 10;
count = 0;
number = i;
  do while (number ne 4);
    if mod(number,2) = 0 then number = number/2;
    else number = 3*number +1;
    count = count +1;
   end;
   output;
end;
run;  

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 10 replies
  • 3322 views
  • 8 likes
  • 4 in conversation