Loops/N plus one half: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|SNUSP}}: oops, pasted to wrong task)
Line 302:
when there is no element in one of the pipes.
yes \ | cat -n | head -n 10 | paste -d\ - <(yes , | head -n 9) | xargs echo
 
=={{header|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

Revision as of 19:13, 26 September 2008

Task
Loops/N plus one half
You are encouraged to solve this task according to the task description, using any language you may 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.

Ada

<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; </ada>

ALGOL 68

main:(
  FOR i FROM 1 WHILE
    print(i);
# WHILE # i < 10 DO
    print(", ")
  OD;
  print(new line)
)

BASIC

Works with: FreeBASIC version 0.20
Works with: RapidQ

<qbasic> DIM i AS Integer

FOR i=1 TO 10

   PRINT i;
   IF i=10 THEN EXIT FOR
   PRINT ", ";

NEXT i </qbasic>


C++

<cpp>

  1. include <iostream>

int main() {

 for (int i = 1; ; i++)
 {
   std::cout << i;
   if (i == 10)
     break;
   std::cout << ", ";
 }
 std::cout << std::endl;
 return 0;

}</cpp>

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>

D

<d>for (int i = 1; ; i++) {

 writef(i);
 if (i == 10) break;
 writef(", ");

} writefln();</d>

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


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 ;

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

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.

Java

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

} </java>

MAXScript

for i in 1 to 10 do
(
    format "%" i
    if i == 10 then exit
    format "%" ", "
)

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

OCaml

<ocaml>let last = 10 in for i = 1 to last do

 print_int i;
 if i <> last then
   print_string ", ";

done; print_newline();</ocaml>

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

Pascal

<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. </pascal>

Perl

<perl> foreach $i (1..11) {

   print $i;
   last if $i == 10;
   print ', ';

} print "\n"; </perl>

Pop11

lvars i;
for i from 1 to 10 do
    printf(i, '%p');
    quitif(i = 10);
    printf(', ', '%p');
endfor;
printf('\n', '%p');

Python

<python> myString = "" for i in xrange(1, 11):

   myString += str(i)
   if i == 10:
       break
   myString += ", "

print myString </python>

Scheme

It is possible to use continuations: <scheme>(call-with-current-continuation

(lambda (esc)
  (do ((i 1 (+ 1 i))) (#f)
    (display i)
    (if (= i 10) (esc (newline)))
    (display ", "))))</scheme>

But usually making the tail recursion explicit is enough: <scheme>(let loop ((i 0))

 (display i)
 (if (= i 10)
     (newline)
     (begin
       (display ", ")
       (loop (+ 1 i)))))</scheme>

SNUSP

@\>@\>@\>+++++++++<!/+.  >-?\#  digit and loop test
 |  |  \@@@+@+++++# \>>.<.<</    comma and space
 |  \@@+@@+++++#      
 \@@@@=++++#

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

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

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