I know halirutan's answer is intended only as a simple example but I believe it is worth noting that it is inefficient for the specific operation that he illustrates.
One could directly write RandomInteger[1, 30]
but that has no "loop" condition and is therefore inapplicable. What I show below may also be inapplicable, but hopefully it is still of interest.
The inefficiency in step
is the use of Append
to collect results, a method which becomes very slow on long lists due to reallocation. The most general efficient method is Sow
and Reap
. For example:
step2[n_] := If[RandomInteger[] === 1, Sow @ RandomInteger[]; n + 1, n]
Reap[NestWhile[step2, 0, # < 20 &]][[2, 1]]
{1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1}
Timing compared to the original:
NestWhile[step, {{}, 0}, Length[First[#]] < 50000 &] // AbsoluteTiming // First
Reap[NestWhile[step2, 0, # < 50000 &]][[2, 1]] // AbsoluteTiming // First
3.4944061
0.1248003
The timing difference is less with short lists and greater with long ones due to different computational complexity.
You may have noticed that my method does not return the number of loops completed as does haliruten's. I left this out for simplicity but it could be achieved like this at the cost of some memory:
Reap[Length@NestWhileList[step2, 0, # < 20 &]]
{47, {{0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1}}}
Or without more memory but slightly more time and code:
step3[{iter_, n_}] :=
{iter + 1, If[RandomInteger[] === 1, Sow @ RandomInteger[]; n + 1, n]}
Reap[First @ NestWhile[step3, {0, 0}, Last@# < 20 &]]
{35, {{1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1}}}
Or with explicit iterator variables:
step4[___] := (j++; If[RandomInteger[] === 1, i++; RandomInteger[], ## &[]])
Block[{i = 0, j = 0},
{NestWhileList[step4, 0, i < 20 &], j}
]
{{0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1}, 45}
NestWhile
will be useful $\endgroup$