Loop/n plus one half
From Rosetta Code
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Quite often one needs loops which are run "n+1/2" times, i.e. in the last iteration one executes only part of the loop body. The goal of this task is to demonstrate the best way to do this.
Write a loop which writes the comma-separated list
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
using separate output statements for the number and the comma.
Contents |
[edit] Ada
with Ada.Text_Io; use Ada.Text_Io; with Ada.Integer_Text_Io; use Ada.Integer_Text_Io; procedure Loop_And_Half is I : Positive := 1; begin loop Put(Item => I, Width => 1); exit when I = 10; Put(", "); I := I + 1; end loop; New_Line; end Loop_And_Half;
[edit] ALGOL 68
main:(
FOR i FROM 1 WHILE
print(i);
# WHILE # i < 10 DO
print(", ")
OD;
print(new line)
)
[edit] BASIC
Works with: FreeBASIC version 0.20
Works with: RapidQ
DIM i AS INTEGER FOR i=1 TO 10 PRINT i; IF i=10 THEN EXIT FOR PRINT ", "; NEXT i
[edit] C++
#include <iostream> int main() { for (int i = 1; ; i++) { std::cout << i; if (i == 10) break; std::cout << ", "; } std::cout << std::endl; return 0; }
[edit] ColdFusion
With tags:
<cfloop index = "i" from = "1" to = "10">
#i#
<cfif i EQ 10>
<cfbreak />
</cfif>
,
</cfloop>
With script:
<cfscript>
for( i = 1; i <= 10; i++ )
{
writeOutput( i );
if( i == 10 )
{
break;
}
writeOutput( ", " );
}
</cfscript>
[edit] D
for (int i = 1; ; i++) { writef(i); if (i == 10) break; writef(", "); } writefln();
[edit] E
A typical loop+break solution:
var i := 1
while (true) {
print(i)
if (i >= 10) { break }
print(", ")
i += 1
}
Using the loop primitive in a semi-functional style:
var i := 1
__loop(fn {
print(i)
if (i >= 10) {
false
} else {
print(", ")
i += 1
true
}
})
[edit] Forth
: comma-list ( n -- ) dup 1 ?do i 1 .r ." , " loop . ;
: comma-list ( n -- )
dup 1+ 1 do
i 1 .r
dup i = if leave then \ or DROP UNLOOP EXIT to exit loop and the function
[char] , emit space
loop drop ;
: comma-list ( n -- )
1
begin dup 1 .r
2dup <>
while ." , " 1+
repeat 2drop ;
[edit] Fortran
Works with: Fortran version 90 and later
DO i = 1, 10
IF (i /= 10) THEN
WRITE (*, "(I1,A)", ADVANCE="NO") i, ", "
ELSE
WRITE (*, "(I2)") i
END IF
END DO
[edit] Haskell
loop :: IO ()
loop = mapM_ action [1 .. 10]
where action n = do
putStr $ show n
putStr $ if n == 10 then "\n" else ", "
It is, however, arguable whether mapM_ counts as a loop.
[edit] Java
public static void main(String[] args) { for (int i = 1; ; i++) { System.out.print(i); if (i == 10) break; System.out.print(", "); } System.out.println(); }
[edit] MAXScript
for i in 1 to 10 do
(
format "%" i
if i == 10 then exit
format "%" ", "
)
[edit] Make
NEXT=`expr $* + 1`
MAX=10
RES=1
all: 1-n;
$(MAX)-n:
@echo $(RES)
%-n:
@-make -f loop.mk $(NEXT)-n MAX=$(MAX) RES=$(RES),$(NEXT)
Invoking it
|make -f loop.mk MAX=10 1,2,3,4,5,6,7,8,9,10
[edit] OCaml
let last = 10 in for i = 1 to last do print_int i; if i <> last then print_string ", "; done; print_newline();
let ints = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] in let str_ints = List.map string_of_int ints in print_string (String.concat ", " str_ints ^ "\n") ;
[edit] Pascal
program numlist(output); var i: integer; begin for i := 1 to 10 do begin write(i); if i <> 10 then write(', ') end; writeln; end.
[edit] Perl
foreach $i (1..11) { print $i; last if $i == 10; print ', '; } print "\n";
[edit] Pop11
lvars i;
for i from 1 to 10 do
printf(i, '%p');
quitif(i = 10);
printf(', ', '%p');
endfor;
printf('\n', '%p');
[edit] Python
myOutput = [] for i in xrange(1, 11): myOutput.append(i) if i == 10: break myOutput.append(", ") print ''.join(myOutput)
Note: this example uses the Python idiom of building a string as a list and joining the parts together (on an empty string) which is generally far more efficient than instantiating new strings at every step along the way. (Strings are immutable so each expression using "some string" + "some other string" is building new objects rather than appending to existing ones).
[edit] Scheme
It is possible to use continuations:
(call-with-current-continuation (lambda (esc) (do ((i 1 (+ 1 i))) (#f) (display i) (if (= i 10) (esc (newline))) (display ", "))))
But usually making the tail recursion explicit is enough:
(let loop ((i 0)) (display i) (if (= i 10) (newline) (begin (display ", ") (loop (+ 1 i)))))
[edit] SNUSP
@\>@\>@\>+++++++++<!/+. >-?\# digit and loop test | | \@@@+@+++++# \>>.<.<</ comma and space | \@@+@@+++++# \@@@@=++++#
[edit] Tcl
proc range {from to} {
if {$to>$from} {concat [range $from [incr to -1]] $to}
}
join [range 1 10] ,
= 1,2,3,4,5,6,7,8,9
[edit] UnixPipes
The last iteration is handled automatically for us when there is no element in one of the pipes.
yes \ | cat -n | head -n 10 | paste -d\ - <(yes , | head -n 9) | xargs echo
[edit] V
[loop
[ [10 =] [puts]
[true] [dup put ',' put succ loop]
] when].
Using it
|1 loop =1,2,3,4,5,6,7,8,9,10

