turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Find a Community

- Home
- /
- SAS Programming
- /
- Base SAS Programming
- /
- output last iteration for i in a do loop

Topic Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

11-21-2016 09:27 PM - edited 11-21-2016 09:28 PM

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!

Accepted Solutions

Solution

11-21-2016
11:43 PM

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to mkeintz

11-21-2016 11:42 PM

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);"

All Replies

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to ilikesas

11-21-2016 09:49 PM - edited 11-21-2016 10:24 PM

**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**;

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to mkeintz

11-21-2016 10:50 PM

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!

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to ilikesas

11-21-2016 11:02 PM

Then I don't understand what you mean by "the last iteration"? Since by definition of the problem the last iteration is N=4.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to ilikesas

11-21-2016 10:36 PM

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);

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Astounding

11-21-2016 11:00 PM

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

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to mkeintz

11-21-2016 11:02 PM

Don't take this seriously, but ...

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

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Astounding

11-21-2016 11:15 PM

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

Solution

11-21-2016
11:43 PM

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to mkeintz

11-21-2016 11:42 PM

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);"

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to mkeintz

11-21-2016 11:10 PM

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 .

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to ilikesas

11-21-2016 10:53 PM

```
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;
```