Text processing/Max licenses in use
A company currently pays a fixed sum for the use of a particular licensed software package. In determining if it has a good deal it decides to calculate its maximum use of the software from its license management log file.
You are encouraged to solve this task according to the task description, using any language you may know.
Assume the software's licensing daemon faithfully records a checkout event when a copy of the software starts and a checkin event when the software finishes to its log file. An example of checkout and checkin events are:
License OUT @ 2008/10/03_23:51:05 for job 4974 ... License IN @ 2008/10/04_00:18:22 for job 4974
Save the 10,000 line log file from here into a local file then write a program to scan the file extracting both the maximum licenses that were out at any time, and the time(s) at which this occurs.
Ada
<lang Ada>-- licenselist.adb -- -- run under GPS 4.3-5 (Sidux/Debian) -- process rosetta.org text_processing/3 example -- uses linked-list to hold times with Ada.Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded,
Ada.Strings.Unbounded.Text_IO, Ada.Containers.Doubly_Linked_Lists;
use Ada.Text_IO, Ada.Integer_Text_IO,
Ada.Strings.Unbounded, Ada.Strings.Unbounded.Text_IO, Ada.Containers;
procedure licenselist is
type logrec is record -- define a record 'logrec' to place in a list logtext : String(1..19); end record;
package dblist is new Doubly_Linked_Lists(logrec); use dblist; -- declare dblist as a list of logrec's licenselog : list; logtime : logrec; -- to record the time of max OUT licenses
infile : File_Type; -- file handle str : Unbounded_String; -- input string buffer of unknown length outcnt, maxoutcnt : integer := 0; infilename : string := "license.log";
procedure trace_times is -- loop thru times list and print pntr : cursor := licenselog.first; -- pntr is of system type cursor reference to local list 'licenselog' begin new_line; while has_element(pntr) loop put(element(pntr).logtext); new_line; next(pntr); end loop; end trace_times;
begin -- main program --
open ( infile, mode=> in_file, name=> infilename );
loop exit when End_of_file ( infile ); str := get_line( infile ); if index( str, "OUT" ) > 0 then -- test if OUT record outcnt := outcnt +1; else -- else assume IN record outcnt := outcnt -1; end if; if outcnt > maxoutcnt then maxoutcnt := outcnt;
logtime.logtext := slice(str,15,33); -- date_time field
licenselog.clear; -- reset list for new time(s) licenselog.append (logtime); -- put current time into list elsif outcnt = maxoutcnt then logtime.logtext := slice(str,15,33); -- date_time field licenselog.append (logtime); -- add current time into list end if; -- have to account for possibility of equal number of OUT's end loop; put("The max. number of licenses OUT is ");put(maxoutcnt,5); new_line; put(" at these times ");
trace_times; close ( infile );
end licenselist;</lang> Output:
The max. number of licenses out is 99 at these times 2008/10/03_08:39:34 2008/10/03_08:40:40 [2010-06-06 01:06:07] process terminated successfully (elapsed time: 00.25s)
ALGOL 68
note: This specimen retains the original C coding style.
<lang algol68>PROC report = (REF FILE file in)INT: (
[3]CHAR inout; [19]CHAR time; INT jobnum;
[1000][UPB time]CHAR max time;
INT lic out := 0, max out := LWB max time-1, max count := LWB max time-1; BOOL file in ended := FALSE; on logical file end(file in, (REF FILE file in)BOOL: file in ended := TRUE); WHILE getf(file in, ($"License "g" @ "g" for job "g(0)l$, inout, time, jobnum));
- WHILE # NOT file in ended DO
IF inout = "OUT" THEN lic out +:= 1 ELIF lic out > 0 THEN # incase license already "OUT" # lic out -:= 1 FI;
IF lic out > max out THEN max out := lic out; max count := LWB max time-1 FI; IF lic out = max out THEN IF max count < UPB max time THEN max time[max count +:= 1] := time ELSE putf(stand error, ($"increase UPB max time (now it is "g(0)")"l$, UPB max time)); exit report error FI FI OD;
printf(($"Maximum simultaneous license use is "g(0)" at the following times:"l$, max out)); FOR lic out FROM LWB max time TO max count DO printf(($gl$, max time[lic out])) OD;
0 EXIT exit report error: errno
);
INT errno;
COMMENT
Usage: a68g Text_processing_3.a68 --exit Text_processing_3.dat a68g Text_processing_3.a68 < Text_processing_3.dat
END COMMENT
main: (
INT argv1 := 4; IF argc >= argv1 THEN FOR i FROM argv1 TO argc DO FILE file in; errno := open(file in, argv(i), stand in channel); IF errno /= 0 THEN putf(stand error, ($"cannot read "gl$, argv(1))); exit main error ELSE report(file in) FI; close(file in) OD ELSE report(stand in) FI; exit main error: SKIP
)</lang> Output:
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40
APL
<lang apl>⍝ Copy/paste file's contents into TXT (easiest), or TXT ← ⎕NREAD
I ← TXT[;8+⎕IO] D ← TXT[;⎕IO+14+⍳19] lu ← +\ ¯1 * 'OI' ⍳ I mx ← (⎕IO+⍳⍴lu)/⍨lu= max ← ⌈/ lu ⎕ ← 'Maximum simultaneous license use is ' , ' at the following times:' ,⍨ ⍕max ⋄ ⎕←D[mx;]</lang>
<lang apl>Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34 2008/10/03_08:40:40</lang>
AutoHotkey
<lang autohotkey> IfNotExist, mlijobs.txt
UrlDownloadToFile, http://rosettacode.org/mlijobs.txt, mlijobs.txt
out := 0, max_out := -1, max_times := ""
Loop, Read, mlijobs.txt {
If InStr(A_LoopReadLine, "OUT") out++ Else out-- If (out > max_out) max_out := out, max_times := "" If (out = max_out) { StringSplit, lineArr, A_LoopReadLine, %A_Space% max_times .= lineArr4 . "`n" }
}
MsgBox Maximum use is %max_out% at:`n`n%max_times% </lang>
Maximum use is 99 at: 2008/10/03_08:39:34 2008/10/03_08:40:40
AWK
to be called with awk -f licenses.awk ./mlijobs.txt <lang awk>$2=="OUT" { count = count + 1
time = $4
if ( count > maxcount ) { maxcount = count maxtime = time }
}
$2=="IN" { count = count - 1 } END {print "The biggest number of licenses is " maxcount " at " maxtime " !"} </lang>
Output: The biggest number of licenses is 99 at 2008/10/03_08:39:34 !
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <string.h>
- include <sys/types.h>
- define INOUT_LEN 4
- define TIME_LEN 20
- define MAX_MAXOUT 1000
char inout[INOUT_LEN]; char time[TIME_LEN]; uint jobnum;
char maxtime[MAX_MAXOUT][TIME_LEN];
int main(int argc, char **argv) {
FILE *in = NULL; int l_out = 0, maxout=-1, maxcount=0;
if ( argc > 1 ) { in = fopen(argv[1], "r"); if ( in == NULL ) { fprintf(stderr, "cannot read %s\n", argv[1]); exit(1); } } else { in = stdin; }
while( fscanf(in, "License %s @ %s for job %u\n", inout, time, &jobnum) != EOF ) {
if ( strcmp(inout, "OUT") == 0 ) l_out++; else l_out--;
if ( l_out > maxout ) { maxout = l_out; maxcount=0; maxtime[0][0] = '\0'; } if ( l_out == maxout ) { if ( maxcount < MAX_MAXOUT ) {
strncpy(maxtime[maxcount], time, TIME_LEN); maxcount++;
} else {
fprintf(stderr, "increase MAX_MAXOUT (now it is %u)\n", MAX_MAXOUT); exit(1);
} } }
printf("Maximum simultaneous license use is %d at the following times:\n", maxout); for(l_out=0; l_out < maxcount; l_out++) { printf("%s\n", maxtime[l_out]); }
if ( in != stdin ) fclose(in); exit(0);
}</lang>
C++
<lang cpp>#include <iostream>
- include <boost/algorithm/string.hpp>
- include <string>
- include <fstream>
- include <vector>
int main( int argc, char * argv[ ] ) {
if ( argc != 2 ) { std::cout << "Error: syntax: ./licenseout <filename of data file>!\n " ; return 1 ; } std::ifstream infile ( argv[ 1 ] , std::ios::in ) ; //nextLine holds the next line of the text file , maxTime the time with //most licenses out , timeOut the respective time entry in a file line std::string nextLine , maxTime , timeOut ; //count holds the number of licenses out at any time , maxcount the maximum //number int count = 0 , maxcount = 0 ; std::vector<std::string> lineElements ; //for the words of a text line if ( infile.is_open( ) ) { while ( infile ) {
getline( infile , nextLine ) ; boost::split( lineElements, nextLine , boost::is_any_of( " " ) ) ; if ( lineElements[ 1 ] == "OUT" ) { count++ ;
timeOut = lineElements[ 3 ] ;
} if ( lineElements[ 1 ] == "IN" ) count-- ; if ( count > maxcount ) { maxcount = count ; maxTime = timeOut ; } lineElements.clear( ) ;
} infile.close( ) ; std::cout << "The maximum number of licenses out is " << maxcount <<
" at " << maxTime << " !\n" ;
return 0 ; } else { std::cout << "Could not open " << argv[ 1 ] << " !\n" ; return 1 ; }
} </lang>
Output: The maximum number of licenses out is 99 at 2008/10/03_08:39:34 !
C#
<lang csharp> using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO;
namespace TextProc3 {
class Program { static void Main(string[] args) { string line; int count = 0, maxcount = 0; List<string> times = new List<string>(); System.IO.StreamReader file = new StreamReader("mlijobs.txt"); while ((line = file.ReadLine()) != null) { string[] lineelements = line.Split(' '); switch (lineelements[1]) { case "IN": count--; break; case "OUT": count++; if (count > maxcount) { maxcount = count; times.Clear(); times.Add(lineelements[3]); }else if(count == maxcount){ times.Add(lineelements[3]); } break; } } file.Close(); Console.WriteLine(maxcount); foreach (string time in times) { Console.WriteLine(time); } } }
} </lang>
99 2008/10/03_08:39:34 2008/10/03_08:40:40
Common Lisp
<lang lisp>(defun max-licenses (&optional (logfile "mlijobs.txt"))
(with-open-file (log logfile :direction :input) (do ((current-logs 0) (max-logs 0) (max-log-times '()) (line #1=(read-line log nil nil) #1#)) ((null line) (format t "~&Maximum simultaneous license use is ~w at the ~ following time~p: ~{~% ~a~}." max-logs (length max-log-times) (nreverse max-log-times))) (cl-ppcre:register-groups-bind (op time) ("License (\\b.*\\b)[ ]{1,2}@ (\\b.*\\b)" line) (cond ((string= "OUT" op) (incf current-logs)) ((string= "IN" op) (decf current-logs)) (t (cerror "Ignore it." "Malformed entry ~s." line))) (cond ((> current-logs max-logs) (setf max-logs current-logs max-log-times (list time))) ((= current-logs max-logs) (push time max-log-times)))))))</lang>
> (max-licenses) Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40. NIL
D
<lang d> import std.stdio; import std.file; import std.string; void main() {
int maxlic = 0,currlic = 0; char[][]maxlic_times; foreach(line;split(cast(char[])read("mlijobs.txt"),"\n")) if (line.length) { if (line[8] == 'O') { // license out currlic++; if (currlic < maxlic) continue; if (currlic > maxlic) { maxlic = currlic; maxlic_times = null; } maxlic_times ~= line[14..33]; } else { // license in currlic--; } }
writefln("Found max %d licenses out at times:",maxlic); foreach(time;maxlic_times) { writefln("%s",time); }
} </lang>
E
<lang e>var out := 0 var maxOut := 0 var maxTimes := []
def events := ["OUT " => 1, "IN " => -1]
for line in <file:mlijobs.txt> {
def `License @{via (events.fetch) delta}@@ @time for job @num$\n` := line
out += delta if (out > maxOut) { maxOut := out maxTimes := [] } if (out == maxOut) { maxTimes with= time }
}
println(`Maximum simultaneous license use is $maxOut at the following times:`) for time in maxTimes {
println(` $time`)
}</lang>
Factor
Placing the file in resource:work/mlijobs.txt:
<lang factor>USING: kernel sequences splitting math accessors io.encodings.ascii io.files math.parser io ; IN: maxlicenses
TUPLE: maxlicense max-count current-count times ;
<PRIVATE
- <maxlicense> ( -- max ) -1 0 V{ } clone \ maxlicense boa ; inline
- out? ( line -- ? ) [ "OUT" ] dip subseq? ; inline
- line-time ( line -- time ) " " split harvest fourth ; inline
- update-max-count ( max -- max' )
dup [ current-count>> ] [ max-count>> ] bi > [ dup current-count>> >>max-count V{ } clone >>times ] when ;
- (inc-current-count) ( max ? -- max' )
[ [ 1 + ] change-current-count ] [ [ 1 - ] change-current-count ] if update-max-count ; inline
- inc-current-count ( max ? time -- max' time )
[ (inc-current-count) ] dip ;
- current-max-equal? ( max -- max ? )
dup [ current-count>> ] [ max-count>> ] bi = ;
- update-time ( max time -- max' )
[ current-max-equal? ] dip swap [ [ suffix ] curry change-times ] [ drop ] if ;
- split-line ( line -- ? time ) [ out? ] [ line-time ] bi ;
- process ( max line -- max ) split-line inc-current-count update-time ;
PRIVATE>
- find-max-licenses ( -- max )
"resource:work/mlijobs.txt" ascii file-lines <maxlicense> [ process ] reduce ;
- print-max-licenses ( max -- )
[ times>> ] [ max-count>> ] bi "Maximum simultaneous license use is " write number>string write " at the following times: " print [ print ] each ;</lang>
<lang factor>( scratchpad ) [ find-max-licenses print-max-licenses ] time Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40 Running time: 0.16164423 seconds</lang>
Forth
<lang forth> 20 constant date-size create max-dates date-size 100 * allot variable max-out variable counter
stdin value input
- process ( addr len -- )
8 /string over 3 s" OUT" compare 0= if 1 counter +! counter @ max-out @ > if counter @ max-out ! drop 5 + date-size max-dates place else counter @ max-out @ = if drop 5 + date-size max-dates +place else 2drop then then else drop 2 s" IN" compare 0= if -1 counter +! then then ;
- main
0 max-out ! 0 counter ! s" mlijobs.txt" r/o open-file throw to input begin pad 80 input read-line throw while pad swap process repeat drop input close-file throw max-out @ . ." max licenses in use @" max-dates count type cr ;
main bye </lang>
Fortran
<lang fortran>
PROGRAM MAX_LICENSES IMPLICIT NONE INTEGER :: out=0, maxout=0, maxcount=0, err CHARACTER(50) :: line CHARACTER(19) :: maxtime(100) OPEN (UNIT=5, FILE="Licenses.txt", STATUS="OLD", IOSTAT=err) IF (err > 0) THEN WRITE(*,*) "Error opening file Licenses.txt" STOP END IF DO READ(5, "(A)", IOSTAT=err) line IF (err == -1) EXIT ! EOF detected IF (line(9:9) == "O") THEN out = out + 1 ELSE IF (line(9:9) == "I") THEN out = out - 1 END IF IF (out > maxout ) THEN maxout = maxout + 1 maxcount = 1 maxtime(maxcount) = line(15:33) ELSE IF (out == maxout) THEN maxcount = maxcount + 1 maxtime(maxcount) = line(15:33) END IF END DO CLOSE(5) WRITE(*,"(A,I4,A)") "Maximum simultaneous license use is", maxout, " at the following times:" WRITE(*,"(A)") maxtime(1:maxcount) END PROGRAM MAX_LICENSES
</lang> Output
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40
Haskell
<lang haskell> import Data.List
main = do
f <- readFile "./../Puzzels/Rosetta/inout.txt" let (ioo,dt) = unzip. map ((\(_:io:_:t:_)-> (io,t)). words) . lines $ f cio = drop 1 . scanl (\c io -> if io == "IN" then pred c else succ c) 0 $ ioo mo = maximum cio putStrLn $ "Maximum simultaneous license use is " ++ show mo ++ " at:" mapM_ (putStrLn . (dt!!)) . elemIndices mo $ cio
</lang>
HicEst
We open Licenses.txt in MatrixExplorer mode with 3 columns: IN/OUT, date_time, ID_nr. This allows to adress single file elements by Licenses(row, column). <lang HicEst>CHARACTER Licenses="Licenses.txt" REAL :: counts(1), Top10(10)
OPEN(FIle=Licenses, fmt='8x,A3,3x,A19,Nb ,', LENgth=lines)
ALLOCATE(counts, lines) counts(1) = 1 DO line = 2, lines
counts(line) = counts(line-1) + 1 - 2*(Licenses(line,1)=='IN')
ENDDO
SORT(Vector=counts, Descending=1, Index=Top10)
DO i = 1, LEN(Top10)
WRITE() counts(Top10(i)), Licenses(Top10(i), 2)
ENDDO
END</lang>
99 2008/10/03_08:40:40 99 2008/10/03_08:39:34 98 2008/10/03_08:40:47 98 2008/10/03_08:40:11 98 2008/10/03_08:39:46 98 2008/10/03_08:39:45 98 2008/10/03_08:39:30 97 2008/10/03_20:44:58 97 2008/10/03_08:41:36 97 2008/10/03_08:40:53
J
<lang j> require 'files'
'I D' =: (8 ; 14+i.19) {"1 &.> <'m' fread 'licenses.txt' NB. read file as matrix, select columns lu =: +/\ _1 ^ 'OI' i. I NB. Number of licenses in use at any given time mx =: (I.@:= >./) lu NB. Indicies of maxima
NB. Output results (mx { D) ,~ 'Maximum simultaneous license use is ' , ' at the following times:' ,~ ": {. ,mx { lu</lang>
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40
Java
<lang java5>import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.LinkedList;
public class License {
public static void main(String[] args) throws FileNotFoundException, IOException{ BufferedReader in = new BufferedReader(new FileReader(args[0])); int max = Integer.MIN_VALUE; LinkedList<String> dates = new LinkedList<String>(); String line; int count = 0; while((line = in.readLine()) != null){ if(line.startsWith("License OUT ")) count++; if(line.startsWith("License IN ")) count--; if(count > max){ max = count; String date = line.split(" ")[3]; dates.clear(); dates.add(date); }else if(count == max){ String date = line.split(" ")[3]; dates.add(date); } } System.out.println("Max licenses out: "+max); System.out.println("At time(s): "+dates); }
}</lang>
Max licenses out: 99 At time(s): [2008/10/03_08:39:34, 2008/10/03_08:40:40]
JavaScript
for the file i/o
<lang javascript>var file_system = new ActiveXObject("Scripting.FileSystemObject"); var fh = file_system.openTextFile('mlijobs.txt', 1); // 1 == open for reading var in_use = 0, max_in_use = -1, max_in_use_at = [];
while ( ! fh.atEndOfStream) {
var line = fh.readline(); if (line.substr(8,3) == "OUT") { in_use++; if (in_use > max_in_use) { max_in_use = in_use; max_in_use_at = [ line.split(' ')[3] ]; } else if (in_use == max_in_use) max_in_use_at.push( line.split(' ')[3] ); } else if (line.substr(8,2) == "IN") in_use--;
}
fh.close();
WScript.echo("Max licenses out: " + max_in_use + "\n " + max_in_use_at.join('\n '));</lang>
output:
Max licenses out: 99 2008/10/03_08:39:34 2008/10/03_08:40:40
M4
<lang M4> divert(-1) define(`current',0) define(`max',0) define(`OUT',`define(`current',incr(current))`'ifelse(eval(current>max),1,
`define(`max',current)`'divert(-1)`'undivert(1)`'divert(1)', `ifelse(current,max,`divert(1)undivert(1)')')')
define(`IN',`define(`current',decr(current))') define(`for',`divert(-1)') include(mlijobs.txt)) divert max undivert(1) </lang>
Output:
99 @ 2008/10/03_08:39:34 @ 2008/10/03_08:40:40
MAXScript
<lang maxscript>fn licencesInUse = (
local logFile = openFile "mlijobs.txt" local out = 0 local maxOut = -1 local maxTimes = #()
while not EOF logFile do ( line = readLine logFile
if findString line "OUT" != undefined then ( out += 1 ) else ( out -= 1 )
if out > maxOut then ( maxOut = out maxTimes = #() )
if out == maxOut then ( append maxTimes (filterString line " ")[4] ) ) format "Maximum simultaneous license use is % at the following times:\n" maxOut
for time in maxTimes do ( format "%\n" time )
close logFile
)
licencesInUse()</lang> Output
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40
OCaml
<lang ocaml>let () =
let out = ref 0 in let max_out = ref(-1) in let max_times = ref [] in
let ic = open_in "mlijobs.txt" in try while true do let line = input_line ic in let io, date, n = Scanf.sscanf line "License %3[IN OUT] %_c %19[0-9/:_] for job %d" (fun io date n -> (io, date, n)) in if io = "OUT" then incr out else decr out; if !out > !max_out then ( max_out := !out; max_times := [date]; ) else if !out = !max_out then max_times := date :: !max_times; done with End_of_file -> close_in ic; Printf.printf "Maximum simultaneous license use is %d \ at the following times:\n" !max_out; List.iter print_endline !max_times;
- </lang>
Oz
<lang oz>declare
fun {MaxLicenses Filename ?Times} InUse = {NewCell 0} MaxInUse = {NewCell 0} MaxTimes = {NewCell nil} in for Job in {ReadLines Filename} do case {List.take Job 11} of "License OUT" then InUse := @InUse + 1 if @InUse > @MaxInUse then MaxInUse := @InUse MaxTimes := nil end if @InUse == @MaxInUse then
JobTime = {Nth {String.tokens Job & } 4} in
MaxTimes := JobTime|@MaxTimes end [] "License IN " then InUse := @InUse - 1 end end Times = {Reverse @MaxTimes} @MaxInUse end
%% Helper. %% Returns a lazy list. So we don't keep the whole logfile in memory... fun {ReadLines Filename} F = {New class $ from Open.file Open.text end init(name:Filename)} fun lazy {ReadNext} case {F getS($)} of false then nil [] Line then Line|{ReadNext} end end in %% close file when handle becomes unreachable {Finalize.register F proc {$ F} {F close} end} {ReadNext} end
Times MaxInUse = {MaxLicenses "mlijobs.txt" ?Times}
in
{System.showInfo "Maximum simultaneous license use is "#MaxInUse#" at the following times:"} {ForAll Times System.showInfo}</lang>
Output:
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40
Perl
<lang perl>#!/usr/bin/perl -w use strict;
my $out = 0; my $max_out = -1; my @max_times;
open FH, '<mlijobs.txt' or die "Can't open file: $!"; while (<FH>) {
chomp; if (/OUT/) { $out++; } else { $out--; } if ($out > $max_out) { $max_out = $out; @max_times = (); } if ($out == $max_out) { push @max_times, (split)[3]; }
} close FH;
print "Maximum simultaneous license use is $max_out at the following times:\n"; print " $_\n" foreach @max_times;</lang> Example output:
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40
PHP
<lang php>$handle = fopen ("mlijobs.txt", "rb"); $maxcount = 0; $count = 0; $times = array(); while (!feof($handle)) {
$buffer = fgets($handle); $op = trim(substr($buffer,8,3));
switch ($op){ case 'IN': $count--; break; case 'OUT': $count++; preg_match('/([\d|\/|_|:]+)/',$buffer,$time); if($count>$maxcount){ $maxcount = $count; $times = Array($time[0]); }elseif($count == $maxcount){ $times[] = $time[0]; } break; } } fclose ($handle);
echo $maxcount . '
';
for($i=0;$i<count($times);$i++){
echo $times[$i] . '
';
}</lang>
99 2008/10/03_08:39:34 2008/10/03_08:40:40
PL/I
<lang PL/I> text3: procedure options (main); /* 13 May 2010 */
declare line character (80) varying; declare (nout, max_nout) fixed; declare in file input;
open file (in) title ('/TEXT3.DAT,TYPE(TEXT),RECSIZE(80)' );
on endfile (in) go to finish_up;
max_nout, nout = 0; do forever; get file (in) edit (line) (L); if substr(line, 9, 4) = 'OUT' then nout = nout+1; else if substr(line, 9, 3) = 'IN' then nout = nout-1; if nout > max_nout then max_nout = nout; end;
finish_up:
put skip list ('The maximum number of licences taken out = ' || max_nout);
end text3; </lang> (more to come)
PicoLisp
Put the following into an executable file "licenses": <lang PicoLisp>#!bin/picolisp lib.l
(zero Count MaxCount)
(in (opt)
(while (split (line) " ") (case (pack (cadr (setq Line @))) (IN (dec 'Count) ) (OUT (when (> (inc 'Count) MaxCount) (setq MaxCount Count MaxTime (get Line 4) ) ) ) ) ) )
(prinl "The biggest number of licenses is " MaxCount " at " MaxTime " !") (bye)</lang> Then it can be called as
$ ./licenses mlijobs.txt The biggest number of licenses is 99 at 2008/10/03_08:39:34 !
PureBasic
<lang PureBasic>OpenConsole()
If ReadFile(0, OpenFileRequester("Text processing/3","mlijobs.txt","All files",1))
While Not Eof(0) currline$=ReadString(0) If StringField(currline$,2," ")="OUT" counter+1 Else counter-1 EndIf If counter>max max=counter maxtime$=StringField(currline$,4," ") ElseIf counter=max maxtime$+#CRLF$+StringField(currline$,4," ") EndIf Wend PrintN(Str(max)+" license(s) used at ;"+#CRLF$+maxtime$) CloseFile(0)
Else
PrintN("Failed to open the file.")
EndIf
PrintN(#CRLF$+"Press ENTER to exit"): Input() CloseConsole()</lang>
99 license(s) used at ; 2008/10/03_08:39:34 2008/10/03_08:40:40 Press ENTER to exit
Python
<lang python>out = 0 max_out = -1 max_times = []
for job in open('mlijobs.txt'):
if "OUT" in job: out += 1 else: out -= 1 if out > max_out: max_out = out max_times = [] if out == max_out: max_times.append(job.split()[3])
print "Maximum simultaneous license use is", max_out, "at the following times:" for time in max_times:
print " ", time</lang>
Example output:
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40
R
<lang R>
- Read in data, discard useless bits
dfr <- read.table("mlijobs.txt") dfr <- dfr[,c(2,4)]
- Find most concurrent licences, and when
n.checked.out <- cumsum(ifelse(dfr$V2=="OUT", 1, -1)) times <- strptime(dfr$V4, "%Y/%m/%d_%H:%M:%S") most.checked.out <- max(n.checked.out) when.most.checked.out <- times[which(n.checked.out==most.checked.out)]
- As a bonus, plot license use
plot(times, n.checked.out, type="s") </lang>
Ruby
<lang ruby>out = 0 max_out = -1 max_times = []
File.foreach('mlijobs.txt') do |line|
out += line.include?("OUT") ? 1 : -1 if out > max_out max_out = out max_times = [] end max_times << line.split[3] if out == max_out
end
puts "Maximum simultaneous license use is #{max_out} at the following times:" max_times.each {|time| puts " #{time}"}</lang>
Example output:
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 2008/10/03_08:40:40
Tcl
<lang tcl> set out 0
set max_out -1 set max_times {} foreach job [split [read [open "mlijobs.txt" "r"]] "\n"] { if {[lindex $job 1] == "OUT"} { incr out } { incr out -1 } if {$out > $max_out} { set max_out $out set max_times {} } if {$out == $max_out} { lappend max_times [lindex $job 3] } } puts "Maximum simultaneous license use is $max_out at the following times:" foreach t $max_times { puts " $t" }</lang>
Output matches Python
Ursala
Four functions are defined. Log lexes the log file, which can be accessed as a pre-declared constant without explicit I/O by being given as a compile-time command line parameter. Scan accumulates running totals of licenses in use. Search identifies the maxima, and format transforms the results to human readable form.
<lang Ursala>
- import std
- import nat
log = ^(~&hh==`O,~&tth)*FtPS sep` *F mlijobs_dot_txt scan = @NiX ~&ar^& ^C/~&alrhr2X ~&arlh?/~&faNlCrtPXPR ~&fabt2R search = @lSzyCrSPp leql$^&hl@lK2; ^/length@hl ~&rS format = ^|C\~& --' licenses in use at'@h+ %nP
- show+
main = format search scan log</lang> output:
99 licenses in use at 2008/10/03_08:39:34 2008/10/03_08:40:40
Vedit macro language
<lang vedit> File_Open("|(PATH_ONLY)\data\mlijobs.txt", BROWSE)
- 1 = 0 // Number of licenses active
- 2 = 0 // Max number of active licenses found
Repeat(ALL) {
Search("|{OUT,IN}|W@", ADVANCE+ERRBREAK) if (Match_Item == 1) { // "OUT" #1++ if (#1 > #2) { // new high value #2 = #1 Reg_Empty(10) // empty the time list } if (#1 == #2) { // same as high value Reg_Copy(10, 1, APPEND) // store time } } else { // "IN" #1-- }
}
Message("Maximum simultaneous license use is ") Num_Type(#2, LEFT+NOCR) Message(" at the following times:\n") Reg_Type(10)
Buf_Quit(OK) </lang>
Output:
Maximum simultaneous license use is 99 at the following times: 2008/10/03_08:39:34 for job 1833 2008/10/03_08:40:40 for job 1837