;
;       Read a file line by line for DBL version 4
;
        RECORD

LINE,   A100

PROC
;-----------------------------------------------
        OPEN (1,I,"FILE.TXT")      [ERR=NOFIL]
        DO FOREVER
           BEGIN
                READS (1,LINE,EOF) [ERR=EREAD]
           END
EOF,    CLOSE 3

        GOTO CLOS

;------------------------------------------------
NOFIL,  ;Open error...do something
        GOTO CLOS

EREAD,  ;Read error...do something
        GOTO CLOS

CLOS,   STOP


$ open input input.txt
$ loop:
$  read /end_of_file = done input line
$  goto loop
$ done:
$ close input


   procedure ReadFileByLine;
   var
      TextFile: text;
      TextLine: String;
   begin
      Assign(TextFile, 'c:\test.txt');
      Reset(TextFile);
      while not Eof(TextFile) do
         Readln(TextFile, TextLine);
      CloseFile(TextFile);
   end;


\util.g
proc nonrec main() void:
    /* first we need to declare a file buffer and an input channel */
    file() infile;
    channel input text in_ch;

    /* a buffer to store the line in is also handy */
    [256] char line;
    word counter;  /* to count the lines */

    /* open the file, and exit if it fails */
    if not open(in_ch, infile, "input.txt") then
        writeln("cannot open file");
        exit(1)
    fi;

    counter := 0;

    /* readln() reads a line and will return false once the end is reached */
    /* we pass in a pointer so it stores a C-style zero-terminated string,
     * rather than try to fill the entire array */
    while readln(in_ch; &line[0]) do
        counter := counter + 1;
        writeln(counter:5, ": ", &line[0])
    od;

    /* finally, close the file */
    close(in_ch)
corp


import system'io;
import extensions;
import extensions'routines;

public program()
{
    File.assign:"file.txt".forEachLine(printingLn)
}


  defmodule FileReader do
    # Create a File.Stream and inspect each line
    def by_line(path) do
      File.stream!(path)
        |> Stream.map(&(IO.inspect(&1)))
	|> Stream.run
      end

    def bin_line(path) do
    # Build the stream in binary instead for performance increase
      case File.open(path) do
        # File returns a tuple, {:ok,file}, if successful
        {:ok, file} ->
	  IO.binstream(file, :line)
	    |> Stream.map(&(IO.inspect(&1)))
	    |> Stream.run
	# And returns {:error,reason} if unsuccessful
	{:error,reason} ->
	# Use Erlang's format_error to return an error string
	  :file.format_error(reason)
      end
    end
  end


-module( read_a_file_line_by_line ).

-export( [into_list/1] ).

into_list( File ) ->
        {ok, IO} = file:open( File, [read] ),
        into_list( io:get_line(IO, ''), IO, [] ).

into_list( eof, _IO, Acc ) -> lists:reverse( Acc );
into_list( {error, _Error}, _IO, Acc ) -> lists:reverse( Acc );
into_list( Line, IO, Acc ) -> into_list( io:get_line(IO, ''), IO, [Line | Acc] ).


PROGRAM LETTURA

EXCEPTION
    FERROR%=TRUE        ! si e' verificata l'eccezione !
    PRINT("Il file richiesto non esiste .....")
END EXCEPTION

BEGIN
    FERROR%=FALSE
    PRINT("Nome del file";)
    INPUT(FILE$)      ! chiede il nome del file
    OPEN("I",1,FILE$) ! apre un file sequenziale in lettura
      IF NOT FERROR% THEN
         REPEAT
           INPUT(LINE,#1,CH$)   ! legge una riga ....
           PRINT(CH$)           ! ... la stampa ...
         UNTIL EOF(1)           ! ... fine a fine file
      END IF
      PRINT
    CLOSE(1)          ! chiude il file
END PROGRAM


constant cmd = command_line()
constant filename = cmd[2]
constant fn = open(filename,"r")
integer i
i = 1
object x
while 1 do
    x = gets(fn)
    if atom(x) then
        exit
    end if
    printf(1,"%2d: %s",{i,x})
    i += 1
end while
close(fn)


open System.IO

[<EntryPoint>]
let main argv =
    File.ReadLines(argv.[0]) |> Seq.iter (printfn "%s")
    0


"path/to/file" utf8 [ [ readln dup [ print ] when* ] loop ] with-file-reader


class Main
{
  Void main ()
  {
    File (`data.txt`).eachLine |Str line|
    {
      echo ("Line: $line")
    }
  }
}


4096 constant max-line

: third ( A b c -- A b c A )
  >r over r> swap ;

: read-lines ( fileid -- )
  begin  pad max-line third read-line throw
  while  pad swap  ( fileid c-addr u )  \ string excludes the newline
         2drop
  repeat 2drop ;


      INTEGER ENUFF		!A value has to be specified beforehand,.
      PARAMETER (ENUFF = 2468)	!Provide some provenance.
      CHARACTER*(ENUFF) ALINE	!A perfect size?
      CHARACTER*66 FNAME	!What about file name sizes?
      INTEGER LINPR,IN		!I/O unit numbers.
      INTEGER L,N		!A length, and a record counter.
      LOGICAL EXIST		!This can't be asked for in an "OPEN" statement.
      LINPR = 6			!Standard output via this unit number.
      IN = 10			!Some unit number for the input file.
      FNAME = "Read.for"	!Choose a file name.
      INQUIRE (FILE = FNAME, EXIST = EXIST)	!A basic question.
      IF (.NOT.EXIST) THEN		!Absent?
        WRITE (LINPR,1) FNAME		!Alas, name the absentee.
    1   FORMAT ("No sign of file ",A)	!The name might be mistyped.
        STOP "No file, no go."		!Give up.
      END IF				!So much for the most obvious mishap.
      OPEN (IN,FILE = FNAME, STATUS = "OLD", ACTION = "READ")	!For formatted input.

      N = 0		!No records read so far.
   10 READ (IN,11,END = 20) L,ALINE(1:MIN(L,ENUFF))	!Read only the L characters in the record, up to ENUFF.
   11 FORMAT (Q,A)		!Q = "how many characters yet to be read", A = characters with no limit.
      N = N + 1			!A record has been read.
      IF (L.GT.ENUFF) WRITE (LINPR,12) N,L,ENUFF	!Was it longer than ALINE could accommodate?
   12 FORMAT ("Record ",I0," has length ",I0,": my limit is ",I0)	!Yes. Explain.
      WRITE (LINPR,13) N,ALINE(1:MIN(L,ENUFF))	!Print the record, prefixed by the count.
   13 FORMAT (I9,":",A)		!Fixed number size for alignment.
      GO TO 10			!Do it again.

   20 CLOSE (IN)	!All done.
      END	!That's all.


' FB 1.05.0 Win64

Open "input.txt" For Input As #1
Dim line_ As String
While Not Eof(1)
  Line Input #1, line_  '' read each line
  Print line_           '' echo it to the console
Wend
Close #1
Print
Print "Press any key to quit"
Sleep


for line = lines["file:yourfile.txt"]
   println[line]


Public Sub Main()
Dim hFile As File
Dim sLine As String

hFile = Open "../InputText.txt" For Input

While Not Eof(hFile)
  Line Input #hFile, sLine
  Print sLine
Wend

End


ReadByLines := function(name)
	local file, line, count;
	file := InputTextFile(name);
	count := 0;
	while true do
		line := ReadLine(file);
		if line = fail then
			break;
		fi;
		count := count + 1;
	od;
	CloseStream(file);
	return count;
end;

# With [http://www.ibiblio.org/pub/docs/misc/amnesty.txt amnesty.txt]
ReadByLines("amnesty.txt");
# 384


[indent=4]
/*
   Read file line by line, in Genie

   valac readFileLines.gs
   ./readFileLines [filename]
*/

init

    fileName:string
    fileName = (args[1] is null) ? "readFileLines.gs" : args[1]
    var file = FileStream.open(fileName, "r")
    if file is null
        stdout.printf("Error: %s did not open\n", fileName)
        return

    lines:int = 0
    line:string? = file.read_line()
    while line is not null
        lines++
        stdout.printf("%04d %s\n", lines, line)
        line = file.read_line()


package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
)

func init() {
	log.SetFlags(log.Lshortfile)
}

func main() {
	// Open an input file, exit on error.
	inputFile, err := os.Open("byline.go")
	if err != nil {
		log.Fatal("Error opening input file:", err)
	}

	// Closes the file when we leave the scope of the current function,
	// this makes sure we never forget to close the file if the
	// function can exit in multiple places.
	defer inputFile.Close()

	scanner := bufio.NewScanner(inputFile)

	// scanner.Scan() advances to the next token returning false if an error was encountered
	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}

	// When finished scanning if any error other than io.EOF occured
	// it will be returned by scanner.Err().
	if err := scanner.Err(); err != nil {
		log.Fatal(scanner.Err())
	}
}


new File("Test.txt").eachLine { line, lineNumber ->
    println "processing line $lineNumber: $line"
}


main = do
  file <- readFile "linebyline.hs"
  mapM_ putStrLn (lines file)


procedure main()
f := open("input.txt","r") | stop("cannot open file ",fn)
while line := read(f)
close(f)
end


cocurrent 'linereader'

  NB. configuration parameter
  blocksize=: 400000

  NB. implementation
  offset=: 0
  position=: 0
  buffer=: ''
  lines=: ''

  create=: monad define
    name=: boxxopen y
    size=: 1!:4 name
    blocks=: 2 <@(-~/\)\ ~. size <. blocksize * i. 1 + >. size % blocksize
  )

  readblocks=: monad define
     if. 0=#blocks do. return. end.
     if. 1<#lines do. return. end.
     whilst. -.LF e.chars do.
       buffer=: buffer,chars=. 1!:11 name,{.blocks
       blocks=: }.blocks
       lines=: <;._2 buffer,LF
     end.
     buffer=: _1{::lines
  )

  next=: monad define
    if. (#blocks)*.2>#lines do. readblocks'' end.
    r=. 0{::lines
    lines=: }.lines
    r
  )


import java.io.BufferedReader;
import java.io.FileReader;

/**
 * Reads a file line by line, processing each line.
 *
 * @author  $Author$
 * @version $Revision$
 */
public class ReadFileByLines {
    private static void processLine(int lineNo, String line) {
        // ...
    }

    public static void main(String[] args) {
        for (String filename : args) {
            BufferedReader br = null;
            FileReader fr = null;
            try {
                fr = new FileReader(filename);
                br = new BufferedReader(fr);
                String line;
                int lineNo = 0;
                while ((line = br.readLine()) != null) {
                    processLine(++lineNo, line);
                }
            }
            catch (Exception x) {
                x.printStackTrace();
            }
            finally {
                if (fr != null) {
                    try {br.close();} catch (Exception ignoreMe) {}
                    try {fr.close();} catch (Exception ignoreMe) {}
                }
            }
        }
    }
}


var fs = require("fs");

var readFile = function(path) {
    return fs.readFileSync(path).toString();
};

console.log(readFile('file.txt'));


/* Read by line, in Jsish */
var f = new Channel('read-by-line.jsi');
var line;

while (line = f.gets()) puts(line);
f.close();


open("input_file","r") do f
    for line in eachline(f)
      println("read line: ", line)
    end
end


// version 1.1.2

import java.io.File

fun main(args: Array<String>) {
    File("input.txt").forEachLine { println(it) }
}


local(f) = file('foo.txt')
handle => {#f->close}
#f->forEachLine => {^
    #1
    '<br>' // note this simply inserts an HTML line break between each line.
^}


filedialog "Open","*.txt",file$
if file$="" then end
open file$ for input as #f
while not(eof(#f))
    line input #f, t$
    print t$
wend
close #f


fp = xtra("fileIO").new()
fp.openFile(_movie.path & "input.txt", 1)
fileSize = fp.getLength()
repeat while TRUE
  str = fp.readLine()
  if str.char[1] = numtochar(10) then delete char 1 of str
  if the last char of str = numtochar(13) then delete the last char of str
  put str
  if fp.getPosition()>=fileSize then exit repeat
end repeat
fp.closeFile()


command readFileLineByLine
    local tFile, tLines, startRead
    put "/usr/share/dict/words" into tFile
    open file tFile for text read
    put true into startRead
    repeat until it is empty and startRead is false
        put false into startRead
        read from file tFile for 1 line
        add 1 to tLines
    end repeat
    close file tFile
    put tLines
end readFileLineByLine


filename = "input.txt"
fp = io.open( filename, "r" )

for line in fp:lines() do
    print( line )
end

fp:close()


Module checkit {
      \\ prepare a file
      document a$
      a$={First Line
            Second line
            Third Line
            }
      Save.Doc a$, "checkthis.txt", 0  ' 0 for UTF-16LE
      Flush
      Open "checkthis.txt" For Wide Input as #F
      While not Eof(#f) {
            Data Seek(#f)
            Line Input #F, b$
            Print  b$
      }
      Close #f
      Dim  Index()
      \\ copy stack to index(), flush stack
      Index()=Array([])
      \\ change base to base 1
      Dim  Base 1, Index(len(index()))
      Open "checkthis.txt" For Wide Input as #F
            Seek#F, Index(2)
            Line Input #F, b$
            Print b$  ' print second line
      Close #f
      \\ prepare Ansi file
      Print "Ansi File"
      Save.Doc a$, "checkthis.txt",  1033  ' we use specific locale
      Flush \\ flush the stack to get indexes
      oldlocale=locale
      locale 1033
      \\ no Wide clause
      Open "checkthis.txt" For  Input as #F
      While not Eof(#f) {
            Data Seek(#f)
            Line Input #F, b$
            Print  b$
      }
      Close #f
      Dim  Index()
      \\ copy stack to index(), flush stack
      Index()=Array([])
      \\ change base to base 1
      Dim  Base 1, Index(len(index()))
      Open "checkthis.txt" For Input as #F
            Seek#F, Index(2)
            Line Input #F, b$
            Print b$  ' print second line
      Close #f
      locale oldlocale
}
checkit


path := "file.txt":
while (true) do
	input := readline(path):
	if input = 0 then break; end if:
	#The line is stored in input
end do:


strm=OpenRead["input.txt"];
If[strm=!=$Failed,
  While[line=!=EndOfFile,
    line=Read[strm];
    (*Do something*)
  ]];
Close[strm];


  fid = fopen('foobar.txt','r');
  if (fid < 0)
	printf('Error:could not open file\n')
  else
	while ~feof(fid),
		line = fgetl(fid);
                %% process line %%
	end;
        fclose(fid)
  end;


/* Read a file and return a list of all lines */

readfile(name) := block(
   [v: [ ], f: openr(name), line],
   while stringp(line: readline(f)) do v: endcons(line, v),
   close(f),
   v
)$


:- module read_a_file_line_by_line.
:- interface.

:- import_module io.

:- pred main(io::di, io::uo) is det.

:- implementation.

:- import_module int, list, require, string.

main(!IO) :-
    io.open_input("test.txt", OpenResult, !IO),
    (
        OpenResult = ok(File),
        read_file_line_by_line(File, 0, !IO)
    ;
        OpenResult = error(Error),
        error(io.error_message(Error))
    ).

:- pred read_file_line_by_line(io.text_input_stream::in, int::in,
    io::di, io::uo) is det.

read_file_line_by_line(File, !.LineCount, !IO) :-
    % We could also use io.read_line/3 which returns a list of characters
    % instead of a string.
    io.read_line_as_string(File, ReadLineResult, !IO),
    (
        ReadLineResult = ok(Line),
        !:LineCount = !.LineCount + 1,
        io.format("%d: %s", [i(!.LineCount), s(Line)], !IO),
        read_file_line_by_line(File, !.LineCount, !IO)
    ;
        ReadLineResult = eof
    ;
        ReadLineResult = error(Error),
        error(io.error_message(Error))
    ).


/**
 Read a file line by line, in Neko
 <doc>
Tectonics:
   nekoc readfile.neko
   neko readfile [filename]
</doc>
*/

var stdin = $loader.loadprim("[email protected]_stdin", 0)()
var file_open = $loader.loadprim("[email protected]_open", 2)
var file_read_char = $loader.loadprim("[email protected]_read_char", 1)

/* Read a line from file f into string s returning length without any newline */
var NEKO_MAX = 1 << 29
var strsize = 256
var NEWLINE = 10
var readline = function(f) {
    var s = $smake(strsize)
    var len = 0
    var ch
    var file_exception = false
    while true {
        try ch = file_read_char(f) catch problem { file_exception = problem; break; }
        if ch == NEWLINE break;
        if $sset(s, len, ch) == null break; else len += 1

        if len == strsize - 1 {
            strsize *= 2
            if strsize > NEKO_MAX $throw("Out of string space for readline")
            var t = s
            s = $smake(strsize)
            $sblit(s, 0, t, 0, $ssize(t))
        }
    }
    if $istrue(file_exception) $rethrow(file_exception)
    return $ssub(s, 0, len)
}

var infile
var cli = $loader.args[0]
if cli == null infile = stdin
else {
    cli = $string(cli)
    try infile = file_open(cli, "r")
    catch problem $print(problem, " Can't open ", cli, "\n")
}
if infile == null $throw("Can't open " + cli)

var str
while true {
    try {
        str = readline(infile)
        $print(":", str, ":\n")
    } catch a break;
}


/* NetRexx */
options replace format comments java crossref symbols nobinary

parse arg inFileName .

if inFileName = '' | inFileName = '.' then inFileName = './data/dwarfs.json'
lines = scanFile(inFileName)
loop l_ = 1 to lines[0]
  say l_.right(4)':' lines[l_]
  end l_

return

-- Read a file and return contents as a Rexx indexed string
method scanFile(inFileName) public static returns Rexx

  fileLines = ''
  do
    inFile = File(inFileName)
    inFileScanner = Scanner(inFile)
    loop l_ = 1 while inFileScanner.hasNext()
      fileLines[0] = l_
      fileLines[l_] = inFileScanner.nextLine()
      end l_
    inFileScanner.close()

  catch ex = FileNotFoundException
    ex.printStackTrace
  end

  return fileLines


(set 'in-file (open "filename" "read"))
(while (read-line in-file)
       (write-line))
(close in-file)


for line in lines "input.txt":
  echo line


bundle Default {
  class ReadFile {
    function : Main(args : String[]) ~ Nil {
      f := IO.FileReader->New("in.txt");
      if(f->IsOpen()) {
        string := f->ReadString();
        while(f->IsEOF() = false) {
          string->PrintLine();
          string := f->ReadString();
        };
        f->Close();
      };
    }
  }
}


NSString *path = [NSString stringWithString:@"/usr/share/dict/words"];
NSError *error = nil;
NSString *words = [[NSString alloc] initWithContentsOfFile:path
                                               encoding:NSUTF8StringEncoding error:&error];


let () =
  let ic = open_in "input.txt" in
  try
    while true do
      let line = input_line ic in
      print_endline line
    done
  with End_of_file ->
    close_in ic


: readFile(fileName)
  | line | File new(fileName) forEach: line [ line println ] ;


FILE *f = fopen(name, "r");
if (!f) {
	pari_err(openfiler, "input", name);
}
while(fgets(line, MAX_LINELEN, f) != NULL) {
	// ...
}


(* Read a text-file line by line *)
   program ReadFileByLine;
   var
      InputFile,OutputFile: text;
      TextLine: String;
   begin
      Assign(InputFile, 'testin.txt');
      Reset(InputFile);
      Assign(OutputFile, 'testout.txt');
      Rewrite(OutputFile);
      while not Eof(InputFile) do
    begin
         ReadLn(InputFile, TextLine);
     (* do someting with TextLine *)
         WriteLn(OutputFile, TextLine)
      end;
      Close(InputFile);
      Close(OutputFile)
   end.


open(my $fh, '<', 'foobar.txt')
    || die "Could not open file: $!";
while (<$fh>)
{ # each line is stored in $_, with terminating newline
  # chomp, short for chomp($_), removes the terminating newline
    chomp;
    process($_);
}
close $fh;


constant fn = open(command_line()[2],"r")
integer lno = 1
object line
while 1 do
    line = gets(fn)
    if atom(line) then exit end if
    printf(1,"%2d: %s",{lno,line})
    lno += 1
end while
close(fn)
{} = wait_key()


include ..\Utilitys.pmt

argument 1 get "r" fopen var f

true
while
    f fgets number? if drop f fclose false else print true endif
endwhile


<?php
$file = fopen(__FILE__, 'r'); // read current file
while ($line = fgets($file)) {
    $line = rtrim($line);      // removes linebreaks and spaces at end
    echo strrev($line) . "\n"; // reverse line and upload it
}


go =>
  FD = open("unixdict.txt"),
  while (not at_end_of_stream(FD))
    Line = read_line(FD),
    println(Line)
  end,
  close(FD),
  nl.


(in "foobar.txt"
   (while (line)
      (process @) ) )


read: procedure options (main);
   declare line character (500) varying;

   on endfile (sysin) stop;

   do forever;
      get edit (line)(L);
   end;
end read;


$reader = [System.IO.File]::OpenText($mancorfile)
try {
	do {
		$line = $reader.ReadLine()
		if ($line -eq $null) { break }
		DoSomethingWithLine($line)
	} while ($TRUE)
} finally {
	$reader.Close()
}


FileName$ = OpenFileRequester("","foo.txt","*.txt",0)

If ReadFile(0, FileName$)          ; use ReadFile instead of OpenFile to include read-only files
  BOMformat = ReadStringFormat(0)  ; reads the BOMformat (Unicode, UTF-8, ASCII, ...)
  While Not Eof(0)
    line$ = ReadString(0, BOMformat)
    DoSomethingWithTheLine(Line)
  Wend
  CloseFile(0)
EndIf


with open("foobar.txt") as f:
    for line in f:
        process(line)


conn <- file("notes.txt", "r")
while(length(line <- readLines(conn, 1)) > 0) {
    cat(line, "\n")
}


(define (read-next-line-iter file)
	   (let ((line (read-line file 'any)))
	     (unless (eof-object? line)
	       (display line)
	       (newline)
	       (read-next-line-iter file))))
(call-with-input-file "foobar.txt" read-next-line-iter)


$Include "Rapidq.inc"
dim file as qfilestream

if file.open("c:\A Test.txt", fmOpenRead) then
    while not File.eof
        print File.readline
    wend
else
    print "Cannot read file"
end if

input "Press enter to exit: ";a$


/*REXX program   reads  and  displays  (with a count)  a file,  one line at a time.     */
parse arg fID .                                  /*obtain optional argument from the CL.*/
if fID==''  then exit 8                          /*Was no fileID specified?  Then quit. */
say center(' displaying file: ' fID" ", 79, '═') /*show the name of the file being read.*/
call linein fID, 1, 0                            /*see the comment in the section header*/
say                                              /* [↓]  show a file's contents (lines).*/
     do #=1  while lines(fID)\==0                /*loop whilst there are lines in file. */
     y= linein(fID)                              /*read a line and assign contents to Y.*/
     say y                                       /*show the content of the line (record)*/
     end   /*#*/
say                                              /*stick a fork in it,  we're all done. */
say center(' file '   fID   " has "   #-1   ' records.', 79, '═')     /*show rec count. */
call lineout  fID                                /*close the input file  (most REXXes). */


fp = fopen("C:\Ring\ReadMe.txt","r")
r = ""
while isstring(r)
      r = fgetc(fp)
      if r = char(10) see nl
      else see r ok
end
fclose(fp)


IO.foreach "foobar.txt" do |line|
  # Do something with line.
  puts line
end


open DefaultDir$ + "\public\filetest.txt" for input as #f
while not(eof(#f))
  line input #f, a$
  print a$
wend
close #f


use std::io::{BufReader,BufRead};
use std::fs::File;

fn main() {
    let file = File::open("file.txt").unwrap();
    for line in BufReader::new(file).lines() {
        println!("{}", line.unwrap());
    }
}


; Commented line below should be uncommented to use read-line with Guile
;(use-modules (ice-9 rdelim))

(define file (open-input-file "input.txt"))
(do ((line (read-line file) (read-line file))) ((eof-object? line))
        (display line)
        (newline))


$ include "seed7_05.s7i";

const proc: main is func
  local
    var file: aFile is STD_NULL;
    var string: line is "";
  begin
    aFile := open("input.txt", "r");
    while hasNext(aFile) do
      readln(aFile, line);
      writeln("LINE: " <& line);
    end while;
  end func;


repeat with each line of file "input.txt"
	put it
end repeat


File(__FILE__).open_r.each { |line|
    print line
}


(StandardFileStream oldFileNamed: 'test.txt') contents lines do: [  :each | Transcript show: each. ]


        input(.infile,20,"readfrom.txt")      :f(end)
rdloop  output = infile                       :s(rdloop)
end


let f = fopen("foo.txt", "r");
if f != nil {
    var line;
    while (line = fgetline(f)) != nil {
        print(line);
    }

    fclose(f);
}


f = "file.txt"
> !#.eof(f)
  #.output(#.readline(f))
<


set f [open "foobar.txt"]
while {[gets $f line] >= 0} {
    # This loops over every line
    puts ">>$line<<"
}
close $f


//Create a file object

%f = new fileObject();

//Open and read a file

%f.openForRead("PATH/PATH.txt");

while(!%f.isEOF())
{
	//Read each line from our file

	%line = %f.readLine();
}

//Close the file object

%f.close();

//Delete the file object

%f.delete();


var f : int
open : f, "rosetta.txt", get
loop
    exit when eof (f)
    var line: string
    get : f, line:*
    put line
end loop
close : f


$$ MODE TUSCRIPT

datei="rosetta.txt"
ERROR/STOP OPEN (datei,READ,-std-)

ACCESS q: READ/RECORDS/UTF8 $datei s,line
 LOOP
 READ/NEXT/EXIT q
 PRINT line
 ENDLOOP
ENDACCESS q


#include <Core/Core.h>

using namespace Upp;

CONSOLE_APP_MAIN
{
	FileIn in(CommandLine()[0]);
	while(in && !in.IsEof())
		Cout().PutLine(in.GetLine());
}


# This while loop repeats for each line of the file.
# This loop is inside a pipeline; many shells will
# run this loop inside a subshell.
cat input.txt |
while IFS= read -r line ; do
  printf '%s\n' "$line"
done


decl file f
f.open "filename.txt"
while (f.hasline)
        out (in string f) endl console
end while


public static void main(){
	var file = FileStream.open("foo.txt", "r");

	string line = file.read_line();
	while (line != null){
		stdout.printf("%s\n", line);
		line = file.read_line();
	}
}


' Read a file line by line
Sub Main()
    Dim fInput As String, fOutput As String 'File names
    Dim sInput As String, sOutput As String 'Lines
    fInput = "input.txt"
    fOutput = "output.txt"
    Open fInput For Input As #1
    Open fOutput For Output As #2
    While Not EOF(1)
        Line Input #1, sInput
        sOutput = Process(sInput) 'do something
        Print #2, sOutput
    Wend
    Close #1
    Close #2
End Sub 'Main


FilePath = "<SPECIFY FILE PATH HERE>"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(FilePath,1)
Do Until objFile.AtEndOfStream
	WScript.Echo objFile.ReadLine
Loop
objFile.Close
Set objFSO = Nothing


File_Open("line_by_line.vdm")
#10 = Buf_Num                   // edit buffer for input file
#11 = Buf_Free                  // edit buffer for output
#1 = 1                          // line number
while (!At_EOF) {
    Reg_Copy(20,1)              // read one line into text register 20
    Buf_Switch(#11)             // switch to output file
    Num_Ins(#1++, NOCR)         // write line number
    Ins_Text("  ")
    Reg_Ins(20)                 // write the line
    Buf_Switch(#10)             // switch to input file
    Line(1)                     // next line
}
Buf_Close(NOMSG)                // close the input file
Buf_Switch(#11)                 // show the output


' Read a file line by line
Sub Main()
    Dim fInput As String, fOutput As String 'File names
    Dim sInput As String, sOutput As String 'Lines
    Dim nRecord As Long
    fInput = "input.txt"
    fOutput = "output.txt"
    On Error GoTo InputError
    Open fInput For Input As #1
    On Error GoTo 0 'reset error handling
    Open fOutput For Output As #2
    nRecord = 0
    While Not EOF(1)
        Line Input #1, sInput
        sOutput = Process(sInput) 'do something
        nRecord = nRecord + 1
        Print #2, sOutput
    Wend
    Close #1
    Close #2
    Exit Sub
InputError:
    MsgBox "File: " & fInput & " not found"
End Sub 'Main


Imports System.IO

  ' Loop through the lines of a file.
  ' Function assumes that the file exists.
  Private Sub ReadLines(ByVal FileName As String)

    Dim oReader As New StreamReader(FileName)
    Dim sLine As String = Nothing

    While Not oReader.EndOfStream
      sLine = oReader.ReadLine()
      ' Do something with the line.
    End While

    oReader.Close()

  End Sub


import "io" for File

var lines = [] // store lines read
File.open("input.txt") { |file|
    var offset = 0
    var line = ""
    while(true) {
        var b = file.readBytes(1, offset)
        offset = offset + 1
        if (b == "\n") {
            lines.add(line)
            line = "" // reset line variable
        } else if (b == "\r") { // Windows
            // wait for following "\n"
        } else if (b == "") { // end of stream
            return
        } else {
            line = line + b
        }
    }
}

System.print(lines.join("\n")) // print out lines


int C;
[repeat repeat  C:= ChIn(1);    \repeat until end-of-line
                ChOut(0, C);
        until   C < $20;        \CR, LF, or EOF
until   C = \EOF\ $1A;          \repeat until end-of-file
]


foreach line in (File("foo.zkl")){print(line)}


INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit

DEFINE PTR="CARD"

CARD FUNC GetFrame()
  BYTE RTCLOK1=$13,RTCLOK2=$14
  CARD res
  BYTE lsb=res,msb=res+1

  lsb=RTCLOK2
  msb=RTCLOK1
RETURN (res)

CARD FUNC FramesToMs(CARD frames)
  BYTE PALNTSC=$D014
  CARD res

  IF PALNTSC=15 THEN
    res=frames*60
  ELSE
    res=frames*50
  FI
RETURN (res)

CARD FUNC ItersPerSecond(CARD timeMs,iters)
  REAL rTime,rIters,r1000,tmp
  CARD res

  IntToReal(timeMs,tmp)
  IntToReal(iters,rIters)
  IntToReal(1000,r1000)
  RealDiv(tmp,r1000,rTime)
  RealDiv(rIters,rTime,tmp)
  res=RealToInt(tmp)
RETURN (res)

;jump addr is stored in X and A registers
PROC Action=*(PTR jumpAddr)
  DEFINE STX="$8E"
  DEFINE STA="$8D"
  DEFINE JSR="$20"
  DEFINE RTS="$60"
  [STX Action+8
   STA Action+7
   JSR $00 $00
   RTS]

PROC Benchmark(PTR ARRAY actions,times BYTE count CARD iters)
  BYTE i
  CARD j,beg,end,diff,diffMs
  PTR act

  FOR i=0 TO count-1
  DO
    act=actions(i)
    beg=GetFrame()
    FOR j=0 TO iters-1
    DO
      Action(act)
    OD
    end=GetFrame()
    diff=end-beg
    times(i)=FramesToMs(diff)
  OD
RETURN

PROC Action1()
RETURN

PROC Action2()
  INT a=[12345],b=[23456],c

  c=a+b
RETURN

PROC Action3()
  INT i=[12345]
  CHAR ARRAY s(6)

  StrI(i,s)
RETURN

PROC Main()
  DEFINE COUNT="3"
  DEFINE ITERS="10000"
  PTR ARRAY actions(COUNT)
  CARD ARRAY times(COUNT),prec,rate
  BYTE i

  Put(125) PutE() ;clear the screen
  prec=FramesToMs(1)
  PrintF("Iteration count: %U%E",ITERS)
  PrintF("Clock precision: %U ms%E%E",prec)
  actions(0)=Action1
  actions(1)=Action2
  actions(2)=Action3
  Benchmark(actions,times,COUNT,ITERS)

  FOR i=0 TO COUNT-1
  DO
    rate=ItersPerSecond(times(i),iters)
    PrintF("Action%B: %U ms, %U times per sec%E",i+1,times(i),rate)
  OD
RETURN


with System;                     use System;
with Ada.Text_IO;                use Ada.Text_IO;
with Ada.Calendar;               use Ada.Calendar;
with Ada.Unchecked_Deallocation; use Ada;
with Interfaces;

procedure Rate_Counter is
   pragma Priority (Max_Priority);

   package Duration_IO is new Fixed_IO (Duration);

   Job_Nbr : constant := 6; -- adjust to your need
   subtype Job_Index is Natural range 1 .. Job_Nbr;

   task type Job (ID : Job_Index) is
      pragma Priority (Default_Priority);
      entry Start;
   end Job;

   type Job_Ptr is access Job;
   procedure Free is new Unchecked_Deallocation (Job, Job_Ptr);

   Jobs : array (Job_Index) of Job_Ptr;

   Done      : Natural                      := 0;
   Completed : array (Job_Index) of Boolean := (others => False);

   type Timings is array (Job_Index) of Calendar.Time;
   Start_T, Stop_T : Timings;

   task body Job is
      Anchor : Interfaces.Integer_32;
      pragma Volatile (Anchor); -- necessary to avoid compiler optimization.
   begin
      accept Start;

      for I in Interfaces.Integer_32'Range loop      -- the job to do
         Anchor := I;
      end loop;
   end Job;

begin
   for J in Job_Index'Range loop
      Jobs (J) := new Job (ID => J); -- create the jobs first, sync later
   end loop;
   for J in Job_Index'Range loop -- launch the jobs in parallel
      Start_T (J) := Calendar.Clock; -- get the start time
      Jobs (J).Start; -- priority settings necessary to regain control.
   end loop;
   -- Polling for the results / also possible to use a protected type.
   while not (Done = Job_Nbr) loop
      for J in Job_Index'Range loop
         if not Completed (J) and then Jobs (J)'Terminated then
            Stop_T (J) := Calendar.Clock; -- get the end time
            Put ("Job #" & Job_Index'Image (J) & " is finished. It took ");
            Duration_IO.Put (Stop_T (J) - Start_T (J), Fore => 3, Aft => 2);
            Put_Line (" seconds.");
            Completed (J) := True;
            Done          := Done + 1;
         end if;
      end loop;
      delay System.Tick; -- according to the precision of the system clock
   end loop;
   Duration_IO.Put (System.Tick, Fore => 1, Aft => 6);
   Put_Line (" seconds is the precision of System clock.");

   for J in Job_Index'Range loop
      Free (Jobs (J)); -- no GC in Ada, clean-up is explicit
   end loop;

end Rate_Counter;


SetBatchLines, -1
Tick := A_TickCount    ; store tickcount
Loop, 1000000 {
    Random, x, 1, 1000000
    Random, y, 1, 1000000
    gcd(x, y)
}
t := A_TickCount - Tick    ; store ticks elapsed
MsgBox, % t / 1000 " Seconds elapsed.`n" Round(1 / (t / 1000000000), 0) " Loop iterations per second."

gcd(a, b) {    ; Euclidean GCD
    while b
        t := b, b := Mod(a, b), a := t
    return, a
}


' Rate counter
FOR i = 1 TO 3
    GOSUB timeit
NEXT

i = 2000
GOSUB timeit
END

LABEL timeit
    iter = 0
    starter = TIMER
    WHILE TRUE DO
        INCR iter
        IF TIMER >= starter + i THEN BREAK
    WEND
    PRINT iter, " iterations in ", i, " millisecond", IIF$(i > 1, "s", "")
    RETURN


global i
subroutine timeit()
	iter = 0
	starter = msec
	while True
		iter += 1
		if msec >= starter + i then exit while
	end while
	print iter; " iteraciones en "; i; " milisegundo";
	if i > 1 then print "s" else print
end subroutine

for i = 1 to 3
	call timeit()
next i

i = 200
call timeit()
end


      PRINT "Method 1: Calculate reciprocal of elapsed time:"
      FOR trial% = 1 TO 3
        start% = TIME
        PROCtasktomeasure
        finish% = TIME
        PRINT "Rate = "; 100 / (finish%-start%) " per second"
      NEXT trial%

      PRINT '"Method 2: Count completed tasks in one second:"
      FOR trial% = 1 TO 3
        runs% = 0
        finish% = TIME + 100
        REPEAT
          PROCtasktomeasure
          IF TIME < finish% runs% += 1
        UNTIL TIME >= finish%
        PRINT "Rate = "; runs% " per second"
      NEXT trial%
      END

      REM This is an example, replace with the task you want to measure
      DEF PROCtasktomeasure
      LOCAL i%
      FOR i% = 1 TO 1000000
      NEXT
      ENDPROC


#include <stdio.h>
#include <time.h>

// We only get one-second precision on most systems, as
// time_t only holds seconds.
struct rate_state_s
{
    time_t lastFlush;
    time_t period;
    size_t tickCount;
};

void tic_rate(struct rate_state_s* pRate)
{
    pRate->tickCount += 1;

    time_t now = time(NULL);

    if((now - pRate->lastFlush) >= pRate->period)
    {
        //TPS Report
        size_t tps = 0.0;
        if(pRate->tickCount > 0)
            tps = pRate->tickCount / (now - pRate->lastFlush);

        printf("%u tics per second.\n", tps);

        //Reset
        pRate->tickCount = 0;
        pRate->lastFlush = now;
    }
}

// A stub function that simply represents whatever it is
// that we want to multiple times.
void something_we_do()
{
    // We use volatile here, as many compilers will optimize away
    // the for() loop otherwise, even without optimizations
    // explicitly enabled.
    //
    // volatile tells the compiler not to make any assumptions
    // about the variable, implying that the programmer knows more
    // about that variable than the compiler, in this case.
    volatile size_t anchor = 0;
    size_t x = 0;
    for(x = 0; x < 0xffff; ++x)
    {
        anchor = x;
    }
}

int main()
{
    time_t start = time(NULL);

    struct rate_state_s rateWatch;
    rateWatch.lastFlush = start;
    rateWatch.tickCount = 0;
    rateWatch.period = 5; // Report every five seconds.

    time_t latest = start;
    // Loop for twenty seconds
    for(latest = start; (latest - start) < 20; latest = time(NULL))
    {
        // Do something.
        something_we_do();

        // Note that we did something.
        tic_rate(&rateWatch);
    }

    return 0;
}


#include <iostream>
#include <ctime>

// We only get one-second precision on most systems, as
// time_t only holds seconds.
class CRateState
{
protected:
    time_t m_lastFlush;
    time_t m_period;
    size_t m_tickCount;
public:
    CRateState(time_t period);
    void Tick();
};

CRateState::CRateState(time_t period) : m_lastFlush(std::time(NULL)),
                                        m_period(period),
                                        m_tickCount(0)
{ }

void CRateState::Tick()
{
    m_tickCount++;

    time_t now = std::time(NULL);

    if((now - m_lastFlush) >= m_period)
    {
        //TPS Report
        size_t tps = 0.0;
        if(m_tickCount > 0)
            tps = m_tickCount / (now - m_lastFlush);

        std::cout << tps << " tics per second" << std::endl;

        //Reset
        m_tickCount = 0;
        m_lastFlush = now;
    }
}

// A stub function that simply represents whatever it is
// that we want to multiple times.
void something_we_do()
{
    // We use volatile here, as many compilers will optimize away
    // the for() loop otherwise, even without optimizations
    // explicitly enabled.
    //
    // volatile tells the compiler not to make any assumptions
    // about the variable, implying that the programmer knows more
    // about that variable than the compiler, in this case.
    volatile size_t anchor = 0;
    for(size_t x = 0; x < 0xffff; ++x)
    {
        anchor = x;
    }
}

int main()
{
    time_t start = std::time(NULL);

    CRateState rateWatch(5);

    // Loop for twenty seconds
    for(time_t latest = start; (latest - start) < 20; latest = std::time(NULL))
    {
        // Do something.
        something_we_do();

        // Note that we did something.
        rateWatch.Tick();
    }

    return 0;
}


require "benchmark"

struct Document
  property :id
  def initialize(@id : Int32) end
end

documents_a = [] of Int32 | Document
documents_h = {} of Int32 => Int32 | Document

1.upto(10_000) do |n|
  d = Document.new(n)
  documents_a << d
  documents_h[d.id] = d
end

searchlist = Array.new(1000){ rand(10_000)+1 }

Benchmark.bm do |x|
  x.report("array"){searchlist.each{ |el| documents_a.any?{ |d| d == el }} }
  x.report("hash") {searchlist.each{ |el| documents_h.has_key?(el) } }
end
puts
Benchmark.ips do |x|
  x.report("array"){searchlist.each{ |el| documents_a.any?{ |d| d == el }} }
  x.report("hash") {searchlist.each{ |el| documents_h.has_key?(el) } }
end


import std.stdio;
import std.conv;
import std.datetime.stopwatch;

int a;
void f0() {}
void f1() { auto b = a; }
void f2() { auto b = to!string(a); }

void main()
{
  auto r = benchmark!(f0, f1, f2)(10_000);

  writeln("Time fx took to run 10,000 times:\n");
  writeln("f0: ", r[0]);
  writeln("f1: ", r[1]);
  writeln("f2: ", r[2]);

}


program Rate_counter;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Diagnostics;

var
  a: Integer;

function TickToString(Tick: Int64): string;
var
  ns, us, ms, s, t: Cardinal;
begin
  Result := '';
  ns := (Tick mod 10) * 100;
  if ns > 0 then
    Result := format(' %dns', [ns]);

  t := Tick div 10;
  us := t mod 1000;
  if us > 0 then
    Result := format(' %dus', [us]) + Result;

  t := t div 1000;
  ms := t mod 1000;
  if ms > 0 then
    Result := format(' %dms', [ms]) + Result;

  t := t div 1000;
  s := t mod 1000;
  if s > 0 then
    Result := format(' %ds', [s]) + Result;
end;

function Benchmark(Fns: TArray<TProc>; times: Cardinal): TArray<string>;
var
  Stopwatch: TStopwatch;
  fn: TProc;
  i, j: Cardinal;
begin
  SetLength(result, length(Fns));
  Stopwatch := TStopwatch.Create;

  for i := 0 to High(Fns) do
  begin
    fn := Fns[i];
    if not Assigned(fn) then
      Continue;
    Stopwatch.Reset;
    Stopwatch.Start;
    for j := 1 to times do
      fn();
    Stopwatch.Stop;
    Result[i] := TickToString(Stopwatch.ElapsedTicks);
  end;
end;

procedure F0();
begin
end;

procedure F1();
begin
  var b := a;
end;

procedure F2();
begin
  var b := a.ToString;
end;

begin
  writeln('Time fx took to run 10,000 times:'#10);
  var r := Benchmark([F0, F1, F2], 10000);
  for var i := 0 to High(r) do
    writeln('f', i, ': ', r[i]);
  Readln;
end.


def makeLamportSlot := <import:org.erights.e.elib.slot.makeLamportSlot>

The rate counter:

/** Returns a function to call to report the event being counted, and an
    EverReporter slot containing the current rate, as a float64 in units of
    events per millisecond. */
def makeRateCounter(timer, reportPeriod) {
    var count := 0
    var start := timer.now()
    def &rate := makeLamportSlot(nullOk[float64], null)

    def signal() {
        def time := timer.now()
        count += 1
        if (time >= start + reportPeriod) {
            rate := count / (time - start)
            start := time
            count := 0
        }
    }

    return [signal, &rate]
}


-module( rate_counter ).

-export( [fun_during_seconds/2, task/0] ).

fun_during_seconds( Fun, Seconds ) ->
	My_pid = erlang:self(),
	Ref = erlang:make_ref(),
        Pid = erlang:spawn( fun() -> fun_during_seconds_loop( My_pid, Fun ) end ),
        timer:send_after( Seconds * 1000, My_pid, {stop, Ref} ),
	N = fun_during_seconds_receive_loop( Ref, Pid, 0 ),
	erlang:exit( Pid, kill ),
	N.

task() ->
    Results = [timer:tc( fun() -> io:fwrite("Hello, world!~n") end ) || _X <- lists:seq(1, 3)],
    Times = [X || {X, _Returned} <- Results],
    io:fwrite( "Times ~p, average ~p microseconds.~n", [Times, lists:sum(Times) / erlang:length(Times)]),
    N =	fun_during_seconds( fun() -> math:sqrt(123) end, 2 ),
    io:fwrite( "Square root of 123, during 2	seconds, was done ~p times.~n", [N] ).

fun_during_seconds_loop( Pid, Fun ) ->
	Fun(),
	Pid ! {one_time, erlang:self()},
	fun_during_seconds_loop( Pid, Fun ).

fun_during_seconds_receive_loop( Ref, Pid, N ) ->
	receive
	{stop, Ref} -> N;
        {one_time, Pid} -> fun_during_seconds_receive_loop( Ref, Pid, N + 1 )
	end.


PROGRAM RATE_COUNTER

!
! for rosettacode.org
!

!
! This is an example, replace with the task you want to  measure
!
PROCEDURE TASK_TO_MEASURE
  LOCAL I
    FOR I=1 TO 1000000 DO
    END FOR
END PROCEDURE

BEGIN
    PRINT("Method 1: Calculate reciprocal of elapsed time:")
    FOR TRIAL%=1 TO 3 DO
      START=TIMER
      TASK_TO_MEASURE
      FINISH=TIMER
      PRINT("Rate =";100/(FINISH-START);"per second")
    END FOR

    PRINT("Method 2: Count completed tasks in one minute:")
    FOR TRIAL%=1 TO 3 DO
      RUNS%=0
      FINISH=TIMER+60
      REPEAT
        TASK_TO_MEASURE
        IF TIMER<FINISH THEN RUNS%+=1 END IF
      UNTIL TIMER>=FINISH
      PRINT("Rate =";RUNS%;"per minute")
    END FOR
END PROGRAM


      DO I = FIRST,LAST
        IF (PROGRESSNOTE((I - FIRST)/(LAST - FIRST + 1.0))) WRITE (6,*) "Reached ",I,", towards ",LAST
        ...much computation...
      END DO


Dim Shared As Integer i

Sub timeit
    Dim As Integer iter = 0
    Dim As Double starter = Timer
    While True
        iter += 1
        If Timer >= starter + i Then Exit While
    Wend
    Print iter; " iteraciones en"; i; " milisegundo"; Iif(i > 1, "s", "")
End Sub

For i = 1 To 3
    timeit
Next i

i = 200 : timeit
Sleep


package main

import (
    "fmt"
    "math/rand"
    "time"
)

// representation of time.Time is nanosecond, actual resolution system specific
type rateStateS struct {
    lastFlush time.Time
    period    time.Duration
    tickCount int
}

func ticRate(pRate *rateStateS) {
    pRate.tickCount++
    now := time.Now()
    if now.Sub(pRate.lastFlush) >= pRate.period {
        // TPS Report
        tps := 0.
        if pRate.tickCount > 0 {
            tps = float64(pRate.tickCount) / now.Sub(pRate.lastFlush).Seconds()
        }
        fmt.Println(tps, "tics per second.")

        // Reset
        pRate.tickCount = 0
        pRate.lastFlush = now
    }
}

func somethingWeDo() {
    time.Sleep(time.Duration(9e7 + rand.Int63n(2e7))) // sleep about .1 second.
}

func main() {
    start := time.Now()

    rateWatch := rateStateS{
        lastFlush: start,
        period:    5 * time.Second,
    }

    // Loop for twenty seconds
    latest := start
    for latest.Sub(start) < 20*time.Second {
        somethingWeDo()
        ticRate(&rateWatch)
        latest = time.Now()
    }
}


import Control.Monad
import Control.Concurrent
import Data.Time

getTime :: IO DiffTime
getTime = fmap utctDayTime getCurrentTime

addSample :: MVar [a] -> a -> IO ()
addSample q v = modifyMVar_ q (return . (v:))

timeit :: Int -> IO a -> IO [DiffTime]
timeit n task = do
    samples <- newMVar []
    forM_ [0..n] $ \n -> do
        t1 <- getTime
        task
        t2 <- getTime
        addSample samples (t2 - t1)

    readMVar samples

main = timeit 10 (threadDelay 1000000)


CHARACTER prompt='Count "Hits++" for 5 sec, get current rate'

DLG(Button="1:&Hits++", CALL="cb", B="2:&Count 5sec", B="3:&Rate", RC=retcod, TItle=prompt, WIN=hdl)

SUBROUTINE cb              ! callback after dialog buttons
  IF(retcod == 1) THEN     ! "Hits++" button
    Hits = Hits + 1
  ELSEIF(retcod == 2) THEN ! "Count 5 sec" button
    Hits = 0
    ALARM(5, 5)            ! call F5 in 5 seconds
    t_start = TIME()
  ELSE                     ! "Rate" button
    sec = TIME() - t_start
    WRITE(StatusBar) 'Average rate since last "5 sec" button = ', hits/sec, " Hz"
  ENDIF
END

SUBROUTINE F5 ! called 5 sec after button "5 sec"
  WRITE(StatusBar) Hits, "hits last 5 sec"
END


import java.util.function.Consumer;

public class RateCounter {

    public static void main(String[] args) {
        for (double d : benchmark(10, x -> System.out.print(""), 10))
            System.out.println(d);
    }

    static double[] benchmark(int n, Consumer<Integer> f, int arg) {
        double[] timings = new double[n];
        for (int i = 0; i < n; i++) {
            long time = System.nanoTime();
            f.accept(arg);
            timings[i] = System.nanoTime() - time;
        }
        return timings;
    }
}


function millis() { // Gets current time in milliseconds.
  return (new Date()).getTime();
}

/* Executes function 'func' n times, returns array of execution times. */
function benchmark(n, func, args) {
  var times = [];
  for (var i=0; i<n; i++) {
    var m = millis();
    func.apply(func, args);
    times.push(millis() - m);
  }
  return times;
}


#!/usr/bin/env jsish
"use strict";
/* Rate counter, timer access, in Jsish */

/* System time in milliseconds */
var runs = 0, newMs;
function countJobsIsTheJob() { runs += 1; }
var milliSeconds = strptime();
while ((newMs = strptime()) < (milliSeconds + 1000)) { countJobsIsTheJob(); }
puts(runs, 'runs in', newMs - milliSeconds, 'ms');

/* Builtin times test(callback, runs), result in microseconds */
function sleeper() { sleep(10); }

var timer;
for (var i = 1; i < 4; i++) {
    timer = times(sleeper, 100);
    puts(timer, 'μs to sleep 10 ms, 100 times');
}


dosomething() = sleep(abs(randn()))

function runNsecondsworthofjobs(N)
    times = Vector{Float64}()
    totaltime = 0
    runcount = 0
    while totaltime < N
        t = @elapsed(dosomething())
        push!(times, t)
        totaltime += t
        runcount += 1
    end
    println("Ran job $runcount times, for total time of $totaltime seconds.")
    println("Average time per run was $(sum(times)/length(times)) seconds.")
    println("Individual times of the jobs in seconds were:")
    for t in times
        println("    $t")
    end
end

runNsecondsworthofjobs(5)


// version 1.1.3

typealias Func<T> = (T) -> T

fun cube(n: Int) = n * n * n

fun <T> benchmark(n: Int, func: Func<T>, arg: T): LongArray {
    val times = LongArray(n)
    for (i in 0 until n) {
         val m = System.nanoTime()
         func(arg)
         times[i] = System.nanoTime() - m
    }
    return times
}

fun main(args: Array<String>) {
    println("\nTimings (nanoseconds) : ")
    for (time in benchmark(10, ::cube, 5)) println(time)
}


Print "Rate counter"
print "Precision: system clock, ms ";
t0=time$("ms")
while time$("ms")=t0    'busy loop till click ticks
wend
print time$("ms")-t0
print

Print "Run jobs N times, report every time"
Print "After that, report average time"
N=10
t00=time$("ms")
for i = 1 to 10
    scan
    t0=time$("ms")
    'any code we want to measure goes here
    res = testFunc()
    'end of measured code
    t1=time$("ms")
    ElapsedTime = t1-t0
    print "Job #";i;" Elapsed time, ms ";ElapsedTime, 1000/ElapsedTime; " ticks per second"
next
print "---------------------------------"
print "Average time, ms, is ";(t1-t00)/N,  1000/((t1-t00)/N); " ticks per second"

print
print "Run jobs for not less then N seconds (if time up, it'll finish last job)"
print "After that, report average time"

NSec=5
i = 0
t00=time$("ms")
while time$("ms")<t00+NSec*1000
    scan
    i = i+1
    t0=time$("ms")
    'any code we want to measure goes here
    res = testFunc()
    'end of measured code
    t1=time$("ms")
    ElapsedTime = t1-t0
    print "Job #";i;" Elapsed time, ms ";ElapsedTime,  1000/ElapsedTime; " ticks per second"
wend
print "---------------------------------"
print "Average time, ms, is ";(t1-t00)/i,  1000/((t1-t00)/i); " ticks per second"

end

function testFunc()
    s=0
    for i = 1 to 30000
        s=s+sin(i)/30000
    next
    testFunc = s
end function


import sugar, std/monotimes, times

type Func[T] = (T) -> T

func cube(n: int): int = n * n * n

proc benchmark[T](n: int; f: Func[T]; arg: T): seq[Duration] =
  result.setLen(n)
  for i in 0..<n:
    let m = getMonoTime()
    discard f(arg)
    result[i] = getMonoTime() - m

echo "Timings (nanoseconds):"
for time in benchmark(10, cube, 5):
  echo time.inNanoseconds


'========
'TIME API
'========

'http://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx

extern lib "kernel32.dll"

type SYSTEMTIME
  WORD wYear
  WORD wMonth
  WORD wDayOfWeek
  WORD wDay
  WORD wHour
  WORD wMinute
  WORD wSecond
  WORD wMilliseconds
end type

void GetSystemTime(SYSTEMTIME*t)
void GetLocalTime(SYSTEMTIME*t)
void QueryPerformanceCounter(quad*c)
void QueryPerformanceFrequency(quad*freq)
void Sleep(sys millisecods)

end extern

String WeekDay[7]={"Sunday","Monday","Tuesday","Wednesday",
"Thursday","Friday","Saturday"}

String MonthName[12]={"January","February","March","April","May","June",
"July","August","September","October","November","December"}

'==============
Class Jobrecord
'==============

  has SYSTEMTIME stt
  has SYSTEMTIME fin
  quad countA
  quad CountB
  quad freq
  sys  serial

  method pad(string s) as string
    method=s
    if len(method)<2 then method="0"+method
  end method

  method ShowDateTime(sys a,f) as string

  SYSTEMTIME *t

  if a then
    @[email protected]
  else
    @[email protected]
  end if
  '
  String month=pad(str t.wMonth)
  String day=pad(str t.wDay)
  if f=0 then
    return "" t.wYear "-" month "-" day "    "+
    pad(t.wHour) ":" pad(t.wMinute) ":" pad(t.wSecond) ":" t.wMilliSeconds
  elseif f=1
    return WeekDay[t.wDayOfWeek+1 and 7 ] " " +
    MonthName[t.wMonth and 31] " " day " " t.wYear
  end if
  end method

  method Start()
  QueryPerformanceCounter countA
  QueryPerformanceFrequency freq
  serial++
  GetLocalTime stt
  end method

  method Finish()
  GetLocalTime fin
  QueryPerformanceCounter countB
  end method

  method ShowDuration() as string
  return str((countB-countA)/freq,6) 'seconds with microsecond resolution
  end method

  method report() as string
  string tab=chr(9), cr=chr(13)+chr(10)
  method="Job:" tab serial cr +
  "Duration:"   tab ShowDuration() cr +
  "Start: "     tab ShowDateTime(0,0) cr +
  "Finish:"     tab ShowDateTime(1,0) cr +
  ShowDateTime(1,1) cr
  end method

end class

'#recordof JobRecord

'====
'TEST
'====

JobRecord JR
JR.start
sleep 100 'JOB!
JR.finish
print JR.Report
'putfile "s.txt",JR.Report
'
'Job:	1
'Duration:	0.099026
'Start: 	2012-07-01    00:52:36:874
'Finish:	2012-07-01    00:52:36:974
'Sunday July 01 2012


use Benchmark;

timethese COUNT,{ 'Job1' => &job1, 'Job2' => &job2 };

sub job1
{
	...job1 code...
}
sub job2
{
	...job2 code...
}


procedure task_to_measure()
    sleep(0.1)
end procedure

printf(1,"method 1: calculate reciprocal of elapsed time:\n")
for trial=1 to 3 do
    atom t=time()
    task_to_measure()
    t = time()-t
    string r = iff(t?sprintf("%g",1/t):"inf")
    printf(1,"rate = %s per second\n",{r})
end for

printf(1,"method 2: count completed tasks in one second:\n")
for trial=1 to 3 do
    integer runs=0
    atom finish=time()+1
    while true do
        task_to_measure()
        if time()>=finish then exit end if
        runs += 1
    end while
    printf(1,"rate = %d per second\n",runs)
end for


100000 var iterations
2 4 2 tolist
for
    msec var a
    iterations
    for
        over 2 power + drop
    endfor
    msec a - var dif
    "take " print dif print " secs" print
    " or " print iterations dif / print " sums per second" print nl
endfor


(prin "Hit a key ... ")
(key)
(prinl)
(let Usec (usec)
   (prin "Hit another key ... ")
   (key)
   (prinl)
   (prinl "This took " (format (- (usec) Usec) 6) " seconds") )


[datetime]$start = Get-Date

[int]$count = 3

[timespan[]]$times = for ($i = 0; $i -lt $count; $i++)
{
    Measure-Command {0..999999 | Out-Null}
}

[datetime]$end = Get-Date

$rate = [PSCustomObject]@{
    StartTime      = $start
    EndTime        = $end
    Duration       = ($end - $start).TotalSeconds
    TimesRun       = $count
    AverageRunTime = ($times.TotalSeconds | Measure-Object -Average).Average
}

$rate | Format-List


Procedure.d TimesPSec(Reset=#False)
  Static starttime, cnt
  Protected Result.d, dt
  If Reset
    starttime=ElapsedMilliseconds(): cnt=0
  Else
    cnt+1
    dt=(ElapsedMilliseconds()-starttime)
    If dt
      Result=cnt/(ElapsedMilliseconds()-starttime)
    EndIf
  EndIf
  ProcedureReturn Result*1000
EndProcedure

If OpenWindow(0,#PB_Ignore,#PB_Ignore,220,110,"",#PB_Window_SystemMenu)
  Define Event, r.d, GadgetNumber
  ButtonGadget(0,10, 5,200,35,"Click me!")
  ButtonGadget(1,10,70,100,35,"Reset")
  TextGadget  (2,10,45,200,25,"")
  TimesPSec(1)
  Repeat
    Event=WaitWindowEvent()
    If Event=#PB_Event_Gadget
      GadgetNumber =EventGadget()
      If GadgetNumber=0
        r=TimesPSec()
        SetGadgetText(2,"You are clicking at "+StrD(r,5)+" Hz.")
      ElseIf GadgetNumber=1
        TimesPSec(1)
        SetGadgetText(2,"Counter zeroed.")
      EndIf
    EndIf
  Until Event=#PB_Event_CloseWindow
EndIf


import subprocess
import time

class Tlogger(object):
    def __init__(self):
        self.counts = 0
        self.tottime = 0.0
        self.laststart = 0.0
        self.lastreport = time.time()

    def logstart(self):
        self.laststart = time.time()

    def logend(self):
        self.counts +=1
        self.tottime += (time.time()-self.laststart)
        if (time.time()-self.lastreport)>5.0:   # report once every 5 seconds
           self.report()

    def report(self):
        if ( self.counts > 4*self.tottime):
            print "Subtask execution rate: %f times/second"% (self.counts/self.tottime);
        else:
            print "Average execution time: %f seconds"%(self.tottime/self.counts);
        self.lastreport = time.time()

def taskTimer( n, subproc_args ):
    logger = Tlogger()

    for x in range(n):
        logger.logstart()
        p = subprocess.Popen(subproc_args)
        p.wait()
        logger.logend()
    logger.report()

import timeit
import sys

def main( ):

    # for accurate timing of code segments
    s = """j = [4*n for n in range(50)]"""
    timer = timeit.Timer(s)
    rzlts = timer.repeat(5, 5000)
    for t in rzlts:
        print "Time for 5000 executions of statement = ",t

    # subprocess execution timing
    print "#times:",sys.argv[1]
    print "Command:",sys.argv[2:]
    print ""
    for k in range(3):
       taskTimer( int(sys.argv[1]), sys.argv[2:])

main()


#lang racket

;; Racket has a useful `time*' macro that does just what's requested:
;; run some expression N times, and produce timing results
(require unstable/time)

;; Sample use:
(define (fib n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2)))))
(time* 10 (fib 38))

;; But of course, can be used to measure external processes too:
(time* 10 (system "sleep 1"))


sub runrate($N where $N > 0, &todo) {
    my $n = $N;

    my $start = now;
    todo() while --$n;
    my $end = now;

    say "Start time: ", DateTime.new($start).Str;
    say "End time: ", DateTime.new($end).Str;
    my $elapsed = $end - $start;

    say "Elapsed time: $elapsed seconds";
    say "Rate: { ($N / $elapsed).fmt('%.2f') } per second\n";
}

sub factorial($n) { (state @)[$n] //= $n < 2 ?? 1 !! $n * factorial($n-1) }

runrate 10000, { state $n = 1; factorial($n++) }

runrate 10000, { state $n = 1; factorial($n++) }


/*REXX program reports on the amount of elapsed time 4 different tasks use (wall clock).*/
time.=                                           /*nullify times for all the tasks below*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
call time 'Reset'                                /*reset the REXX (elapsed) clock timer.*/
                                                 /*show pi in hex to  2,000 dec. digits.*/
                  task.1= 'base(pi,16)  ;;;  lowercase   digits 2k   echoOptions'
                  call '$CALC' task.1            /*perform task number one  (via $CALC).*/
time.1=time('E')                                 /*get and save the time used by task 1.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
call time 'Reset'                                /*reset the REXX (elapsed) clock timer.*/
                                                 /*get primes  40000 ──► 40800 and      */
                                                 /*show their differences.              */
                  task.2= 'diffs[ prime(40k, 40.8k) ]  ;;;  GRoup 20'
                  call '$CALC' task.2            /*perform task number two  (via $CALC).*/
time.2=time('E')                                 /*get and save the time used by task 2.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
call time 'Reset'                                /*reset the REXX (elapsed) clock timer.*/
                                                 /*show the  Collatz sequence  for a    */
                                                 /*stupidly gihugeic number.            */
                  task.3= 'Collatz(38**8)  ;;;  Horizontal'
                  call '$CALC' task.3            /*perform task number three (via $CALC)*/
time.3=time('E')                                 /*get and save the time used by task 3.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
call time 'Reset'                                /*reset the REXX (elapsed) clock timer.*/
                                                 /*plot  SINE  in  ½  degree increments.*/
                                                 /*using five decimal digits  (¬ 60).   */
                  task.4= 'sinD(-180, +180, 0.5)  ;;;  Plot  DIGits 5   echoOptions'
                  call '$CALC' task.4            /*perform task number four (via $CALC).*/
time.4=time('E')                                 /*get and save the time used by task 4.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
say
    do j=1  while  time.j\==''
    say 'time used for task'     j     "was"     right(format(time.j,,0),4)     'seconds.'
    end   /*j*/
                                                 /*stick a fork in it,  we're all done. */


# Project : Rate counter

see "method 1: calculate reciprocal of elapsed time:" + nl
for trial = 1 to 3
    start = clock()
    tasktomeasure()
    finish = clock()
    see "rate = " + 100 / (finish-start) + " per second" + nl
next

see "method 2: count completed tasks in one second:" + nl
for trial = 1 to 3
    runs = 0
    finish = clock() + 100
    while clock()  < finish
          tasktomeasure()
          if clock() < finish
             runs = runs + 1
          ok
    end
    see "rate = " + runs + " per second" + nl
next

func tasktomeasure
     for i = 1 to 100000
     next


require 'benchmark'
Document = Struct.new(:id,:a,:b,:c)
documents_a = []
documents_h = {}
1.upto(10_000) do |n|
  d = Document.new(n)
  documents_a << d
  documents_h[d.id] = d
end
searchlist = Array.new(1000){ rand(10_000)+1 }

Benchmark.bm(10) do |x|
  x.report('array'){searchlist.each{|el| documents_a.any?{|d| d.id == el}} }
  x.report('hash'){searchlist.each{|el| documents_h.has_key?(el)} }
end


html "

Rate Counter

Run Job Times	"
    textbox #runTimes,"10",3

html "

"
     button #r,"Run", [runIt]
html "        "
     button #a, "Average", [ave]
html "

"
wait

[runIt]
runTimes = min(10,val(#runTimes contents$()))
count = count + 1
print "-------- Run Number ";count;" ----------------"
print "Run jobs";runTimes;" times, reporting each"

for i = 1 to runTimes
    ' -----------------------------------------------------------------
    ' Normally we use a RUN() command to run another program
    ' but for test pruporse we have a routine that simply loops a bunch
    ' -----------------------------------------------------------------
    begTime  = time$("ms")
    theRun   = bogusProg()

    endTime  = time$("ms")
    lapsTime = endTime - begTime
    print "Job #";i;" Elapsed time, ms ";lapsTime;" ";1000/lapsTime; " ticks per second"
next
aveTime    = (endTime-startTime)/runTimes
totAveTime = totAveTime + aveTime
print "Average time, ms, is ";aveTime;" "; 1000/((endTime-startTime)/runTimes); " ticks per second"
wait

[ave]
print "---------------------------------"
print "Total average time:";aveTime/count

function bogusProg()
    for i = 1 to 10000
        sini = sini + sin(i)
        tani = tani + tan(i)
        cpsi = cosi + cos(i)
    next
end function


def task(n: Int) = Thread.sleep(n * 1000)
def rate(fs: List[() => Unit]) = {
  val jobs = fs map (f => scala.actors.Futures.future(f()))
  val cnt1 = scala.actors.Futures.awaitAll(5000, jobs: _*).count(_ != None)
  val cnt2 = scala.actors.Futures.awaitAll(5000, jobs: _*).count(_ != None)
  val cnt3 = scala.actors.Futures.awaitAll(5000, jobs: _*).count(_ != None)
  println("%d jobs in 5 seconds" format cnt1)
  println("%d jobs in 10 seconds" format cnt2)
  println("%d jobs in 15 seconds" format cnt3)
}
rate(List.fill(30)(() => task(scala.util.Random.nextInt(10)+1)))


var benchmark = frequire('Benchmark');

func job1 {
    #...job1 code...
}
func job2 {
    #...job2 code...
}

const COUNT = -1;   # run for one CPU second
benchmark.timethese(COUNT, Hash.new('Job1' => job1, 'Job2' => job2));


|times|
times := Bag new.
1 to: 10 do: [:n| times add:
   (Time millisecondsToRun: [3000 factorial])].
Transcript show: times average asInteger.


set iters 10

# A silly example task
proc theTask {} {
    for {set a 0} {$a < 100000} {incr a} {
        expr {$a**3+$a**2+$a+1}
    }
}

# Measure the time taken $iters times
for {set i 1} {$i <= $iters} {incr i} {
    set t [lindex [time {
        theTask
    }] 0]
    puts "task took $t microseconds on iteration $i"
}


#!/bin/bash

while : ; do
task && echo >> .fc
done


import rand
import time

// representation of time.Time is nanosecond, actual resolution system specific
struct RateStateS {
mut:
    last_flush time.Time
    period    time.Duration
    tick_count int
}

fn (mut p_rate RateStateS) tic_rate() {
    p_rate.tick_count++
    now := time.now()
    if now-p_rate.last_flush >= p_rate.period {
        // TPS Report
        mut tps := 0.0
        if p_rate.tick_count > 0 {
            tps = f64(p_rate.tick_count) / (now-p_rate.last_flush).seconds()
        }
        println("$tps tics per second.")

        // Reset
        p_rate.tick_count = 0
        p_rate.last_flush = now
    }
}

fn something_we_do() {
    time.sleep(time.Duration(i64(9e7) + rand.i64n(i64(2e7)) or {i64(0)})) // sleep about .1 second.
}

fn main() {
    start := time.now()

    mut rate_watch := RateStateS{
        last_flush: start,
        period:    5 * time.second,
    }

    // Loop for twenty seconds
    mut latest := start
    for latest-start < 20*time.second {
        something_we_do()
        rate_watch.tic_rate()
        latest = time.now()
    }
}


var cube = Fn.new { |n| n * n * n }

var benchmark = Fn.new { |n, func, arg, calls|
    var times = List.filled(n, 0)
    for (i in 0...n) {
        var m = System.clock
        for (j in 0...calls) func.call(arg)
        times[i] = ((System.clock - m) * 1000).round  // milliseconds
    }
    return times
}

System.print("Timings (milliseconds) : ")
for (time in benchmark.call(10, cube, 5, 1e6)) System.print(time)


include c:\cxpl\codes;               \intrinsic 'code' declarations
int N, I, T0, Time;
[for N:= 1, 3 do
    [T0:= GetTime;
    for I:= 1 to 100 do
        [while port($3DA) & $08 do [];  \wait for vertical retrace to go away
        repeat until port($3DA) & $08;  \wait for vertical retrace signal
        ];
    Time:= GetTime - T0;
    IntOut(0, Time);  Text(0, " microseconds for 100 samples = ");
    RlOut(0, 100.0e6/float(Time));  Text(0, "Hz");  CrLf(0);
    ];
]


iterations = 100000

for j = 2 to 4
    a = peek("millisrunning")
    for i = 1 to iterations
        void = i + j^2
    next
    dif = peek("millisrunning") - a
    print "take ", dif, " ms";
    print " or ", iterations / dif * 1000 using "########", " sums per second"
next


fcn rateCounter(f,timeNRuns,secsToRun=Void){
   now:=Time.Clock.time;
   if(secsToRun){
      then:=now + secsToRun;
      N:=0; do{ f(); N+=1; }while(Time.Clock.time<then);
      t:=Time.Clock.time - now;
      println("%d runs in %s seconds = %.3f sec/run"
              .fmt(N,Time.Date.toHMSString(0,0,t),t.toFloat()/N));
   }
   else{
      do(timeNRuns){ f() }
      t:=Time.Clock.time - now;
      println("%s seconds to run %d times = %.3f sec/run"
              .fmt(Time.Date.toHMSString(0,0,t),timeNRuns,
	           t.toFloat()/timeNRuns));
      t
   }
}


# generate random sentences using text from a book as a basis        #

# use the associative array in the Associate array/iteration task    #
PR read "aArray.a68" PR

# returns s with chars removed                                       #
PRIO REMOVE = 1;
OP   REMOVE = ( STRING s, chars )STRING:
     BEGIN
        [ LWB s : UPB s ]CHAR result;
        INT r pos := LWB result - 1;
        FOR s pos FROM LWB s TO UPB s DO
            IF NOT char in string( s[ s pos ], NIL, chars ) THEN
                # have a character that needn't be removed           #
                r pos +:= 1;
                result[ r pos ] := s[ s pos ]
            FI
        OD;
        result[ LWB s : r pos ]
     END # REMOVE # ;
# returns text converted to an INT or -1 if text is not a number     #
OP   TOINT    = ( STRING text )INT:
     BEGIN
        INT  result     := 0;
        BOOL is numeric := TRUE;
        FOR ch pos FROM LWB text TO UPB text WHILE is numeric DO
            CHAR c = text[ ch pos ];
            is numeric := ( c >= "0" AND c <= "9" );
            IF is numeric THEN ( result *:= 10 ) +:= ABS c - ABS "0" FI
        OD;
        IF is numeric THEN result ELSE -1 FI
     END # TOINT # ;

# get the file name and number of words for the prefix and           #
# max number of words and sentences from the command line            #
STRING file name           := "twotw.txt";
STRING start word          := "";
INT    prefix length       := 2;
INT    number of sentences := 10;
INT    max words           := 1 000 000;
FOR arg pos TO argc - 1 DO
    STRING arg upper := argv( arg pos );
    FOR ch pos FROM LWB arg upper TO UPB arg upper DO
        IF is lower( arg upper[ ch pos ] ) THEN arg upper[ ch pos ] := to upper( arg upper[ ch pos ] ) FI
    OD;
    IF   arg upper  = "FILE"   THEN
        file name           :=       argv( arg pos + 1 )
    ELIF arg upper  = "PREFIX" THEN
        prefix length       := TOINT argv( arg pos + 1 )
    ELIF arg upper  = "SENTENCES" THEN
        number of sentences := TOINT argv( arg pos + 1 )
    ELIF arg upper  = "MAXWORDS" THEN
        max words           := TOINT argv( arg pos + 1 )
    ELIF arg upper  = "STARTWORD" THEN
        start word          :=       argv( arg pos + 1 )
    FI
OD;

# delimiter for separating suffixes - must not appear in the text    #
CHAR   suffix delimiter = REPR 1; # ^A #
STRING punctuation      = """'@,/;:(){}[]*&^%$£";

IF  FILE input file;
    open( input file, file name, stand in channel ) /= 0
THEN
    # failed to open the file #
    print( ( "Unable to open """ + file name + """", newline ) )
ELSE
    # file opened OK #
    BOOL at eof := FALSE;
    BOOL at eol := FALSE;
    # set the EOF handler for the file #
    on logical file end( input file
                       , ( REF FILE f )BOOL:
                         BEGIN
                             # note that we reached EOF on the #
                             # latest read #
                             at eof := TRUE;
                             # return TRUE so processing can continue #
                             TRUE
                         END
                       );
    # set the end-of-line handler for the file so get word can see line boundaries #
    on line end( input file
               , ( REF FILE f )BOOL:
                 BEGIN
                     # note we reached end-of-line #
                     at eol := TRUE;
                     # return FALSE to use the default eol handling  #
                     # i.e. just get the next charactefr             #
                     FALSE
                 END
               );
    CHAR   c    := " ";
    # returns the next word from input file                          #
    # a word is any sequence of characters separated by spaces and   #
    # suffix delimiters, or one of the characters ".", "!" or "?"    #
    PROC get word = STRING:
         IF at eof THEN ""
         ELSE # not at end of file                                   #
            STRING word := "";
            at eol := FALSE;
            IF c = "." OR c = "!" OR c = "?" THEN
                # sentence ending "word"                             #
                word := c;
                get( input file, ( c ) )
            ELSE
                # "normal" word                                      #
                WHILE ( c = " " OR c = suffix delimiter ) AND NOT at eof DO get( input file, ( c ) ) OD;
                WHILE c /= " "
                  AND c /= "."
                  AND c /= "!"
                  AND c /= "?"
                  AND c /= suffix delimiter
                  AND NOT at eol
                  AND NOT at eof
                DO
                    word +:= c;
                    get( input file, ( c ) )
                OD
            FI;
            at eol := FALSE;
            word
         FI # get word # ;

    # returns a random number between 1 and n inclusive              #
    PROC random choice = ( INT n )INT: IF n < 2 THEN n ELSE ENTIER ( ( next random * n ) + 1 ) FI;

    # chooses a suffix at random to continue a sentence              #
    PROC choose suffix = ( STRING sfxs )STRING:
         BEGIN
            # count the number of suffixes                           #
            INT suffix max := 0;
            FOR s pos FROM LWB sfxs TO UPB sfxs DO
               IF sfxs[ s pos ] = suffix delimiter THEN suffix max +:= 1 FI
            OD;
            # select a random suffix to continue the text with       #
            STRING sfx          := "";
            INT    prev pos     := LWB sfxs - 1;
            INT    suffix count := random choice( suffix max );
            FOR s pos FROM LWB sfxs TO UPB sfxs WHILE suffix count > 0  DO
                IF sfxs[ s pos ] = suffix delimiter THEN
                    # found the end of a suffix                      #
                    sfx           := sfxs[ prev pos + 1 : s pos - 1 @ 1 ];
                    prev pos      := s pos;
                    suffix count -:= 1
                FI
            OD;
            sfx
         END # choose suffix # ;

    # skip to the start word, if there is one                        #
    IF start word /= "" THEN WHILE NOT at eof AND get word /= start word DO SKIP OD FI;
    # get the first prefix from the file                             #
    [ prefix length ]STRING prefix;
    FOR p pos TO prefix length WHILE NOT at eof DO prefix[ p pos ] := get word OD;
    IF at eof THEN
        # not enough words in the file                               #
        print( ( file name, " contains less than ", whole( prefix length, 0 ), " words", newline ) )
    ELSE
        # have some words                                            #
        INT word count := prefix length;
        # store the prefixes and suffixes in the associatibe array   #
        # we store the suffix as a single concatenated               #
        # string delimited by suffix delimiters, the string will     #
        # have a leading delimiter                                   #
        # suffixes that appear multiple times in the input text will #
        # appear multiple time in the array, this will allow them to #
        # have a higher probability than suffixes that appear fewer  #
        # times                                                      #
        # this will use more memory than storing the sufixes and a   #
        # count, but simplifies the generation                       #
        # with a prefix length of 2 (as required by the task),       #
        # the War Of The Worlds can be processed - for longer prefix #
        # lengths a less memory hungry algorithm would be needed     #
        REF AARRAY suffixes := INIT LOC AARRAY;
        INT prefix count    := 0;
        WHILE NOT at eof AND word count <= max words
        DO
            # concatenate the prefix words to a single string        #
            STRING prefix text := prefix[ 1 ];
            FOR p pos FROM 2 TO prefix length DO prefix text +:= ( " " + prefix[ p pos ] ) OD;
            STRING suffix := get word;
            # if the prefix has no lower case, ignore it as it is    #
            # probably a chapter heading or similar                  #
            IF BOOL has lowercase := FALSE;
               FOR s pos FROM LWB prefix text TO UPB prefix text
               WHILE NOT ( has lowercase := is lower( prefix text[ s pos ] ) )
               DO SKIP OD;
               has lowercase
            THEN
                # the prefix contains some lower case                #
                # store the suffixes associated with the prefix      #
                IF NOT ( suffixes CONTAINSKEY prefix text ) THEN
                    # first time this prefix has appeared            #
                    prefix count +:= 1
                FI;
                IF prefix[ 1 ] = "." OR prefix[ 1 ] = "!" OR prefix[ 1 ] = "?" THEN
                    # have the start of a sentence                   #
                    suffixes // "*." +:= ( suffix delimiter + prefix text )
                FI;
                STRING prefix without punctuation = prefix text REMOVE punctuation;
                IF prefix without punctuation /= "" THEN prefix text := prefix without punctuation FI;
                suffixes // prefix text +:= ( suffix delimiter + suffix )
            FI;
            # shuffle the prefixes down one and add the new suffix   #
            # as the final prefix                                    #
            FOR p pos FROM 2 TO prefix length DO prefix[ p pos - 1 ] := prefix[ p pos ] OD;
            prefix[ prefix length ] := suffix;
            IF NOT at eof THEN word count +:= 1 FI
        OD;

        # generate text                                                  #
        TO number of sentences DO
            print( ( newline ) );
            # start with a random prefix                                 #
            STRING pfx      := choose suffix( suffixes // "*." );
            STRING line     := pfx[ @ 1 ][ 3 : ]; # remove the leading   #
                                                  #   ". " from the line #
            pfx             := pfx REMOVE punctuation;
            BOOL   finished := FALSE;
            WHILE NOT finished DO
                IF STRING sfxs := ( suffixes // pfx );
                   IF LWB sfxs <= UPB sfxs THEN
                       IF sfxs[ LWB sfxs ] = suffix delimiter THEN sfxs := sfxs[ LWB sfxs + 1 : ] FI
                   FI;
                   sfxs +:= suffix delimiter;
                   sfxs = suffix delimiter
                THEN
                    # no suffix - reached the end of the generated text  #
                    line +:= " (" + pfx + " has no suffix)";
                    finished := TRUE
                ELSE
                    # can continue to generate text                      #
                    STRING sfx = choose suffix( sfxs );
                    IF sfx = "." OR sfx = "!" OR sfx = "?"
                    THEN
                        # reached the end of a sentence                  #
                        finished := TRUE;
                        # if the line ends with ",;:", remove it         #
                        INT    line end := UPB line;
                        IF CHAR c = line[ line end ]; c = "," OR c = ";" OR c = ":" THEN
                            line end -:= 1
                        FI;
                        # remove trailing spaces                         #
                        WHILE line[ line end ] = " " AND line end > LWB line DO line end -:= 1 OD;
                        line := line[ LWB line : line end ] + sfx
                    ELSE
                        # not at the end of the sentence                 #
                        line +:= " " + sfx;
                        # remove the first word from the prefix and add  #
                        # the suffix                                     #
                        IF  INT space pos := 0;
                            NOT char in string( " ", space pos, pfx )
                        THEN
                            # the prefix is only one word                #
                            pfx := sfx
                        ELSE
                            # have multiple words                        #
                            pfx := ( pfx[ space pos + 1 : ] + " " + sfx )[ @ 1 ]
                        FI;
                        STRING pfx without punctuation = pfx REMOVE punctuation;
                        IF pfx without punctuation /= "" THEN pfx := pfx without punctuation FI
                    FI
                FI
            OD;
            print( ( line, newline ) )
        OD
    FI;
    close( input file )
FI


""" weighted random pick of items in a Dict{String, Int} where keys are words, values counts """
function weightedrandompick(dict, total)
    n = rand(1:total)
    for (key, value) in dict
        n -= value
        if n <= 0
            return key
        end
    end
    return last(keys(dict))
end

let
    """ Read in the book "The War of the Worlds", by H. G. Wells. """
    wotw_uri =  "http://www.gutenberg.org/files/36/36-0.txt"
    wfile = "war_of_the_worlds.txt"
    stat(wfile).size == 0 && download(wotw_uri, wfile)  # download if file not here already
    text = read(wfile, String)

    """skip to start of book and prune end """
    startphrase, endphrase = "No one would have believed", "she has counted me, among the dead"
    text = text[findfirst(startphrase, text).start:findlast(endphrase, text).stop]

    """ Remove extraneous punctuation, but keep at least sentence-ending punctuation characters . ! and ? """
    text = replace(replace(text, r"[^01-9a-zA-Z\.\?\!’,]" => " "), r"([.?!])" => s" \1")
    words = split(text, r"\s+")
    for (i, w) in enumerate(words)
        w != "I" && i > 1 && words[i - 1] in [".", "?", "!"] && (words[i] = lowercase(words[i]))
    end

    """ Keep account of what words follow words and how many times it is seen. Treat sentence terminators
       (?.!) as words too. Keep account of what words follow two words and how many times it is seen.
    """
    follows, follows2 = Dict{String, Dict{String, Int}}(), Dict{String, Dict{String, Int}}()
    afterstop, wlen = Dict{String, Int}(), length(words)
    for (i, w) in enumerate(@view words[1:end-1])
        d = get!(follows, w, Dict(words[i + 1] => 0))
        get!(d, words[i + 1], 0)
        d[words[i + 1]] += 1
        if w in [".", "?", "!"]
            d = get!(afterstop, words[i + 1], 0)
            afterstop[words[i + 1]] += 1
        end
        (i > wlen - 2) && continue
        w2 = w * " " * words[i + 1]
        d = get!(follows2, w2, Dict(words[i + 2] => 0))
        get!(d, words[i + 2], 0)
        d[words[i + 2]] += 1
    end
    followsums = Dict(key => sum(values(follows[key])) for key in keys(follows))
    follow2sums = Dict(key => sum(values(follows2[key])) for key in keys(follows2))
    afterstopsum = sum(values(afterstop))

   """ Assume that a sentence starts with a not to be shown full-stop character then use a weighted
       random choice of the possible words that may follow a full-stop to add to the sentence.
   """
    function makesentence()
        firstword = weightedrandompick(afterstop, afterstopsum)
        sentencewords = [firstword, weightedrandompick(follows[firstword], followsums[firstword])]
        while !(sentencewords[end] in [".", "?", "!"])
            w2 = sentencewords[end-1] * " " * sentencewords[end]
            if haskey(follows2, w2)
                push!(sentencewords, weightedrandompick(follows2[w2], follow2sums[w2]))
            else
                push!(sentencewords, weightedrandompick(afterstop, afterstopsum))
            end
        end
        sentencewords[1] = uppercase(firstword[1]) * (length(firstword) > 1 ? firstword[2:end] : "")
        println(join(sentencewords[1:end-1], " ") * sentencewords[end] * "\n")
    end
    # Print 3 weighted random pick sentences
    makesentence(); makesentence(); makesentence()
end


import random, sequtils, strutils, tables
from unicode import utf8

const StopChars = [".", "?", "!"]

proc weightedChoice(choices: CountTable[string]; totalCount: int): string =
  ## Return a string from "choices" key using counts as weights.
  var n = rand(1..totalCount)
  for word, count in choices.pairs:
    dec n, count
    if n <= 0: return word
  assert false, "internal error"

proc finalFilter(words: seq[string]): seq[string] =
  ## Eliminate words of length one (except those of a given list)
  ## and words containing only uppercase letters (words from titles).
  for word in words:
    if word in [".", "?", "!", "I", "A", "a"]:
      result.add word
    elif word.len > 1 and any(word, isLowerAscii):
      result.add word

randomize()

var text = readFile("The War of the Worlds.txt")

# Extract the actual text from the book.
const
  StartText = "BOOK ONE\r\nTHE COMING OF THE MARTIANS"
  EndText = "End of the Project Gutenberg EBook"
let startIndex = text.find(StartText)
let endIndex = text.find(EndText)
text = text[startIndex..<endIndex]

# Clean the text by removing some characters and replacing others.
# As there are some non ASCII characters, we have to apply special rules.
var processedText: string
for uchar in text.utf8():
  if uchar.len == 1:
    # ASCII character.
    let ch = uchar[0]
    case ch
    of '0'..'9', 'a'..'z', 'A'..'Z', ' ': processedText.add ch  # Keep as is.
    of '\n': processedText.add ' '                              # Replace with a space.
    of '.', '?', '!': processedText.add ' ' & ch                # Make sure these characters are isolated.
    else: discard                                               # Remove others.
  else:
    # Some UTF-8 representation of a non ASCII character.
    case uchar
    of "—": processedText.add ' '                               # Replace EM DASH with space.
    of "ç", "æ", "’": processedText.add uchar                   # Keep these characters as they are parts of words.
    of "“", "”", "‘": discard                                   # Removed these ones.
    else: echo "encountered: ", uchar                           # Should not go here.

# Extract words and filter them.
let words = processedText.splitWhitespace().finalFilter()

# Build count tables.
var followCount, followCount2: Table[string, CountTable[string]]
for i in 1..words.high:
  followCount.mgetOrPut(words[i - 1], initCountTable[string]()).inc(words[i])
for i in 2..words.high:
  followCount2.mgetOrPut(words[i - 2] & ' ' & words[i - 1], initCountTable[string]()).inc words[i]

# Build sum tables.
var followSum, followSum2: CountTable[string]
for key in followCount.keys:
  for count in followCount[key].values:
    followSum.inc key, count
for key in followCount2.keys:
  for count in followCount2[key].values:
    followSum2.inc key, count

# Build table of starting words and compute the sum.
var
  startingWords: CountTable[string]
  startingSum: int
for stopChar in StopChars:
  for word, count in followCount[stopChar].pairs:
    startingWords.inc word, count
    inc startingSum, count

# Build a sentence.
let firstWord = weightedChoice(startingWords, startingSum)
var sentence = @[firstWord]
var lastWord = weightedChoice(followCount[firstWord], followSum[firstWord])
while lastWord notin StopChars:
  sentence.add lastWord
  let key = sentence[^2] & ' ' & lastWord
  lastWord = if key in followCount2:
               weightedChoice(followCount2[key], followSum2[key])
             else:
               weightedChoice(followCount[lastWord], followSum[lastWord])
echo sentence.join(" ") & lastWord


#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Random_sentence_from_book
use warnings;

my $book = do { local (@ARGV, $/) = 'waroftheworlds.txt'; <> };
my (%one, %two);

s/^.*?START OF THIS\N*\n//s, s/END OF THIS.*//s,
  tr/a-zA-Z.!?/ /c, tr/ / /s for $book;

my $qr = qr/(\b\w+\b|[.!?])/;
$one{$1}{$2}++, $two{$1}{$2}{$3}++ while $book =~ /$qr(?= *$qr *$qr)/g;

sub weightedpick
  {
  my $href = shift;
  my @weightedpick = map { ($_) x $href->{$_} } keys %$href;
  $weightedpick[rand @weightedpick];
  }

sub sentence
  {
  my @sentence = qw( . ! ? )[rand 3];
  push @sentence, weightedpick( $one{ $sentence[0] } );
  push @sentence, weightedpick( $two{ $sentence[-2] }{ $sentence[-1] } )
    while $sentence[-1] =~ /\w/;
  shift @sentence;
  "@sentence\n\n" =~ s/\w\K (?=[st]\b)/'/gr =~ s/ (?=[.!?]\n)//r
    =~ s/.{60,}?\K /\n/gr;
  }

print sentence() for 1 .. 10;


-- demo/rosetta/RandomSentence.exw
include builtins\libcurl.e
constant url =  "http://www.gutenberg.org/files/36/36-0.txt",
         filename = "war_of_the_worlds.txt",
         fsent = "No one would have believed",
         lasts = "End of the Project Gutenberg EBook",
         unicodes = {utf32_to_utf8({#2019}),    -- rsquo
                     utf32_to_utf8({#2014})},   -- hyphen
         asciis = {"'","-"},
         aleph = tagset('Z','A')&tagset('z','a')&tagset('9','0')&",'.?! ",
         follow = new_dict(),   -- {word}      -> {words,counts}
         follow2 = new_dict()   -- {word,word} -> {words,counts}

if not file_exists(filename) then
    printf(1,"Downloading %s...\n",{filename})
    CURLcode res = curl_easy_get_file(url,"",filename)
    if res!=CURLE_OK then crash("cannot download") end if
end if
string text = get_text(filename)
text = text[match(fsent,text)..match(lasts,text)-1]
text = substitute_all(text,unicodes,asciis)
text = substitute_all(text,".?!-\n",{" ."," ? "," ! "," "," "})
text = filter(text,"in",aleph)
sequence words = split(text)

procedure account(sequence words)
    string next = words[$]
    words = words[1..$-1]
    for i=length(words) to 1 by -1 do
        integer d = {follow,follow2}[i]
        sequence t = getdd(words,{{},{}},d)
        integer tk = find(next,t[1])
        if tk=0 then
            t[1] = append(t[1],next)
            t[2] = append(t[2],1)
        else
            t[2][tk] += 1
        end if
        setd(words,t,d)
        words = words[2..$]
        if words!={"."} then exit end if -- (may as well quit)
    end for
end procedure

for i=2 to length(words) do
    if find(words[i],{".","?","!"})
    and i<length(words) then
        words[i+1] = lower(words[i+1])
    end if
    account(words[max(1,i-2)..i])
end for

function weighted_random_pick(sequence words, integer dict)
    sequence t = getd(words,dict)
    integer total = sum(t[2]),
            r = rand(total)
    for i=1 to length(t[2]) do
        r -= t[2][i]
        if r<=0 then
            return t[1][i]
        end if
    end for
end function

for i=1 to 5 do
    sequence sentence = {".",weighted_random_pick({"."},follow)}
    while true do
        string next = weighted_random_pick(sentence[-2..-1],follow2)
        sentence = append(sentence,next)
        if find(next,{".","?","!"}) then exit end if
    end while
    sentence[2][1] = upper(sentence[2][1])
    printf(1,"%s\n",{join(sentence[2..$-1])&sentence[$]})
end for
{} = wait_key()


from urllib.request import urlopen
import re
from string import punctuation
from collections import Counter, defaultdict
import random

# The War of the Worlds, by H. G. Wells
text_url = 'http://www.gutenberg.org/files/36/36-0.txt'
text_start = 'No one would have believed'

sentence_ending = '.!?'
sentence_pausing = ',;:'

def read_book(text_url, text_start) -> str:
    with urlopen(text_url) as book:
        text = book.read().decode('utf-8')
    return text[text.index(text_start):]

def remove_punctuation(text: str, keep=sentence_ending+sentence_pausing)-> str:
    "Remove punctuation, keeping some"
    to_remove = ''.join(set(punctuation) - set(keep))
    text = text.translate(str.maketrans(to_remove, ' ' * len(to_remove))).strip()
    text = re.sub(fr"[^a-zA-Z0-9{keep}\n ]+", ' ', text)
    # Remove duplicates and put space around remaining punctuation
    if keep:
        text = re.sub(f"([{keep}])+", r" \1 ", text).strip()
    if text[-1] not in sentence_ending:
        text += ' .'
    return text.lower()

def word_follows_words(txt_with_pauses_and_endings):
    "return dict of freq of words following one/two words"
    words = ['.'] + txt_with_pauses_and_endings.strip().split()

    # count of what word follows this
    word2next = defaultdict(lambda :defaultdict(int))
    word2next2 = defaultdict(lambda :defaultdict(int))
    for lh, rh in zip(words, words[1:]):
        word2next[lh][rh] += 1
    for lh, mid, rh in zip(words, words[1:], words[2:]):
        word2next2[(lh, mid)][rh] += 1

    return dict(word2next), dict(word2next2)

def gen_sentence(word2next, word2next2) -> str:

    s = ['.']
    s += random.choices(*zip(*word2next[s[-1]].items()))
    while True:
        s += random.choices(*zip(*word2next2[(s[-2], s[-1])].items()))
        if s[-1] in sentence_ending:
            break

    s  = ' '.join(s[1:]).capitalize()
    s = re.sub(fr" ([{sentence_ending+sentence_pausing}])", r'\1', s)
    s = re.sub(r" re\b", "'re", s)
    s = re.sub(r" s\b", "'s", s)
    s = re.sub(r"\bi\b", "I", s)

    return s

if __name__ == "__main__":
    txt_with_pauses_and_endings = remove_punctuation(read_book(text_url, text_start))
    word2next, word2next2 = word_follows_words(txt_with_pauses_and_endings)
    #%%
    sentence = gen_sentence(word2next, word2next2)
    print(sentence)


my $text = '36-0.txt'.IO.slurp.subst(/.+ '*** START OF THIS' .+? \n (.*?) 'End of the Project Gutenberg EBook' .*/, {$0} );

$text.=subst(/ <+punct-[.!?\’,]> /, ' ', :g);
$text.=subst(/ (\s) '’' (\s)  /, '', :g);
$text.=subst(/ (\w) '’' (\s)  /, {$0~$1}, :g);
$text.=subst(/ (\s) '’' (\w)  /, {$0~$1}, :g);

my (%one, %two);

for $text.comb(/[\w+(\’\w+)?]','?|<punct>/).rotor(3 => -2) {
    %two{.[0]}{.[1]}{.[2]}++;
    %one{.[0]}{.[1]}++;
}

sub weightedpick (%hash) { %hash.keys.map( { $_ xx %hash{$_} } ).pick }

sub sentence {
    my @sentence = <. ! ?>.roll;
    @sentence.push: weightedpick( %one{ @sentence[0] } );
    @sentence.push: weightedpick( %two{ @sentence[*-2] }{ @sentence[*-1] } // %('.' => 1) )[0]
      until @sentence[*-1] ∈ <. ! ?>;
    @sentence.=squish;
    shift @sentence;
    redo if @sentence < 7;
    @sentence.join(' ').tc.subst(/\s(<:punct>)/, {$0}, :g);
}

say sentence() ~ "\n" for ^10;


import "io" for File
import "random" for Random
import "/seq" for Lst

// puctuation to keep (also keep hyphen and apostrophe but don't count as words)
var ending  = ".!?"
var pausing = ",:;"

// puctuation to remove
var removing = "\"#$\%&()*+/<=>@[\\]^_`{|}~“”"

// read in book
var fileName = "36-0.txt"  // local copy of http://www.gutenberg.org/files/36/36-0.txt
var text = File.read(fileName)

// skip to start
var ix = text.indexOf("No one would have believed")
text = text[ix..-1]

// remove extraneous punctuation
for (r in removing) text = text.replace(r, "")

// replace EM DASH (unicode 8212) with a space
text = text.replace("—", " ")

// split into words
var words = text.split(" ").where { |w| w != "" }.toList
// treat 'ending' and 'pausing' punctuation as words
for (i in 0...words.count) {
    var w = words[i]
    for (p in ending + pausing) if (w.endsWith(p)) words[i] = [w[0...-1], w[-1]]
}
words = Lst.flatten(words)

// Keep account of what words follow words and how many times it is seen
var dict1 = {}
for (i in 0...words.count-1) {
    var w1 = words[i]
    var w2 = words[i+1]
    if (dict1[w1]) {
        dict1[w1].add(w2)
    } else {
        dict1[w1] = [w2]
    }
}
for (key in dict1.keys) dict1[key] = [dict1[key].count, Lst.individuals(dict1[key])]

// Keep account of what words follow two words and how many times it is seen
var dict2 = {}
for (i in 0...words.count-2) {
    var w12 = words[i] + " " + words[i+1]
    var w3  = words[i+2]
    if (dict2[w12]) {
        dict2[w12].add(w3)
    } else {
        dict2[w12] = [w3]
    }
}
for (key in dict2.keys) dict2[key] = [dict2[key].count, Lst.individuals(dict2[key])]

var rand = Random.new()

var weightedRandomChoice = Fn.new { |value|
    var n = value[0]
    var indivs = value[1]
    var r = rand.int(n)
    var sum = 0
    for (indiv in indivs) {
        sum = sum + indiv[1]
        if (r < sum) return indiv[0]
    }
}

// build 5 random sentences say
for (i in 1..5) {
    var sentence = weightedRandomChoice.call(dict1["."])
    var lastOne = sentence
    var lastTwo = ". " + sentence
    while (true) {
        var nextOne = weightedRandomChoice.call(dict2[lastTwo])
        sentence = sentence + " " + nextOne
        if (ending.contains(nextOne)) break // stop on reaching ending punctuation
        lastTwo = lastOne + " " + nextOne
        lastOne = nextOne
    }

    // tidy up sentence
    for (p in ending + pausing) sentence = sentence.replace(" %(p)", "%(p)")
    sentence = sentence.replace("\n", " ")
    System.print(sentence)
    System.print()
}


INCLUDE "H6:REALMATH.ACT"

DEFINE PTR="CARD"
DEFINE RANGESIZE="12"
DEFINE LOW_="+0"
DEFINE HIGH_="+6"
TYPE Range=[CARD l1,l2,l3,h1,h2,h3]

PROC Inverse(Range POINTER r)
  REAL tmp

  RealAssign(r LOW_,tmp)
  RealAssign(r HIGH_,r LOW_)
  RealAssign(tmp,r HIGH_)
RETURN

PROC Normalize(Range POINTER r)
  IF RealLess(r HIGH_,r LOW_) THEN
    Inverse(r)
  FI
RETURN

INT FUNC Compare(Range Pointer r1,r2)
  IF RealLess(r1 LOW_,r2 LOW_) THEN
    RETURN (-1)
  ELSEIF RealLess(r2 LOW_,r1 LOW_) THEN
    RETURN (1)
  ELSEIF RealLess(r1 HIGH_,r2 HIGH_) THEN
    RETURN (-1)
  ELSEIF RealLess(r2 HIGH_,r1 HIGH_) THEN
    RETURN (1)
  FI
RETURN (0)

PTR FUNC GetItemAddr(PTR data INT index)
RETURN (data+index*RANGESIZE)

PROC Swap(Range POINTER r1,r2)
  REAL tmp

  RealAssign(r1 LOW_,tmp)
  RealAssign(r2 LOW_,r1 LOW_)
  RealAssign(tmp, r2 LOW_)
  RealAssign(r1 HIGH_,tmp)
  RealAssign(r2 HIGH_,r1 HIGH_)
  RealAssign(tmp, r2 HIGH_)
RETURN

PROC Sort(PTR data INT count)
  INT i,j,minpos
  Range POINTER r1,r2

  FOR i=0 TO count-2
  DO
    minpos=i
    FOR j=i+1 TO count-1
    DO
      r1=GetItemAddr(data,minpos)
      r2=GetItemAddr(data,j)
      IF Compare(r1,r2)>0 THEN
        minpos=j
      FI
    OD

    IF minpos#i THEN
      r1=GetItemAddr(data,minpos)
      r2=GetItemAddr(data,i)
      Swap(r1,r2)
    FI
  OD
RETURN

PROC Consolidate(PTR data INT POINTER count)
  INT i,j,newCount
  Range POINTER r1,r2

  FOR i=0 TO count^-1
  DO
    r1=GetItemAddr(data,i)
    Normalize(r1)
  OD
  Sort(data,count^)

  newCount=0 i=0
  WHILE i<count^
  DO
    j=i+1
    WHILE j<count^
    DO
      r1=GetItemAddr(data,i)
      r2=GetItemAddr(data,j)
      IF RealLess(r1 HIGH_,r2 LOW_) THEN
        EXIT
      ELSEIF RealLess(r1 HIGH_,r2 HIGH_) THEN
        RealAssign(r2 HIGH_,r1 HIGH_)
      FI
      j==+1
    OD
    r1=GetItemAddr(data,i)
    r2=GetItemAddr(data,newCount)
    RealAssign(r1 LOW_,r2 LOW_)
    RealAssign(r1 HIGH_,r2 HIGH_)
    newCount==+1
    i=j
  OD
  count^=newCount
RETURN

PROC PrintRanges(PTR data INT count)
  INT i
  Range POINTER r

  FOR i=0 TO count-1
  DO
    IF i>0 THEN Put(' ) FI
    r=GetItemAddr(data,i)
    Put('[) PrintR(r LOW_)
    Put(',) PrintR(r HIGH_) Put('])
  OD
RETURN

PROC Append(PTR data INT POINTER count
  CHAR ARRAY sLow,sHigh)
  Range POINTER r

  r=GetItemAddr(data,count^)
  ValR(sLow,r LOW_)
  ValR(sHigh,r High_)
  count^=count^+1
RETURN

INT FUNC InitData(BYTE case PTR data)
  INT count

  count=0
  IF case=0 THEN
    Append(data,@count,"1.1","2.2")
  ELSEIF case=1 THEN
    Append(data,@count,"6.1","7.2")
    Append(data,@count,"7.2","8.3")
  ELSEIF case=2 THEN
    Append(data,@count,"4","3")
    Append(data,@count,"2","1")
  ELSEIF case=3 THEN
    Append(data,@count,"4","3")
    Append(data,@count,"2","1")
    Append(data,@count,"-1","-2")
    Append(data,@count,"3.9","10")
  ELSEIF case=4 THEN
    Append(data,@count,"1","3")
    Append(data,@count,"-6","-1")
    Append(data,@count,"-4","-5")
    Append(data,@count,"8","2")
    Append(data,@count,"-6","-6")
  FI
RETURN (count)

PROC Main()
  BYTE ARRAY data(100)
  INT count
  BYTE i

  Put(125) PutE() ;clear the screen
  FOR i=0 TO 4
  DO
    count=InitData(i,data)
    PrintRanges(data,count)
    Print(" -> ")
    Consolidate(data,@count)
    PrintRanges(data,count)
    PutE() PutE()
  OD
RETURN