CloudFlare suffered a massive security issue affecting all of its customers, including Rosetta Code. All passwords not changed since February 19th 2017 have been expired, and session cookie longevity will be reduced until late March.--Michael Mol (talk) 05:15, 25 February 2017 (UTC)

Text processing/Max licenses in use

From Rosetta Code
Task
Text processing/Max licenses in use
You are encouraged to solve this task according to the task description, using any language you may know.

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.

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


Task

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[edit]

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

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[edit]

Translation of: C
note: This specimen retains the original C coding style.
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
PROC report = (REF FILE file in)INT: (
 
MODE TIME = [19]CHAR;
STRUCT ([3]CHAR inout, TIME time, INT jobnum) record;
FORMAT record fmt = $"License "g" @ "g" for job "g(0)l$;
 
FLEX[1]TIME 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, (record fmt, record));
# WHILE # NOT file in ended DO
IF inout OF record = "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
[UPB max time*2]TIME new max time;
new max time[:UPB max time] := max time;
max time := new max time
# ;putf(stand error, ($"increasing UPB max time (now it is "g(0)")"l$, UPB max time)); #
FI;
max time[max count +:= 1] := time OF record
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
)

Output:

Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

APL[edit]

Works with: APL2
Translation of: J
⍝  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;]
Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

AutoHotkey[edit]

Translation of: Python
 
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%
 
Maximum use is 99 at:

2008/10/03_08:39:34
2008/10/03_08:40:40

AWK[edit]

to be called with awk -f licenses.awk ./mlijobs.txt

$2=="OUT" { 
count = count + 1
time = $4
if ( count > maxcount ) {
maxcount = count
maxtimes = time
} else {
if ( count == maxcount ) {
maxtimes = maxtimes " and " time
}
}
}
$2=="IN" { count = count - 1 }
END {print "The biggest number of licenses is " maxcount " at " maxtimes " !"}

Sample output

The biggest number of licenses is 99 at 2008/10/03_08:39:34 and 2008/10/03_08:40:40 !

On a 2.53MHz machine, these timings were obtained using GNU Awk 4.0.2:

user	0m0.015s
sys	0m0.008s

BBC BASIC[edit]

      max% = 0
nlicence% = 0
file% = OPENIN("mlijobs.txt")
 
WHILE NOT EOF#file%
a$ = GET$#file%
stamp$ = MID$(a$, 15, 19)
IF INSTR(a$, "OUT") THEN
nlicence% += 1
IF nlicence% > max% THEN
max% = nlicence%
start$ = stamp$
ENDIF
ENDIF
IF INSTR(a$, "IN") THEN
IF nlicence% = max% THEN
finish$ = previous$
ENDIF
nlicence% -= 1
ENDIF
previous$ = stamp$
ENDWHILE
CLOSE #file%
 
PRINT "Maximum licences checked out = " ; max%
PRINT "From " start$ " to " finish$
END

Output:

Maximum licences checked out = 99
From 2008/10/03_08:39:34 to 2008/10/03_08:40:40

Bracmat[edit]

(   0:?N:?n
& :?Ts
& @( get$("mlijobs.txt",STR)
 :  ?
( "e " ?OI " @ " ?T " " ?
& (  !OI:OUT
&  !n+1
 : ( >!N:?N&!T:?Ts
| !N&!Ts !T:?Ts
| ?
)
| !n+-1
)
 : ?n
& ~
)
)
| out$(!N !Ts)
);
 

Output:

99 2008/10/03_08:39:34 2008/10/03_08:40:40

C[edit]

#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);
}
Using mmap, no extra storage (think this as a search and replace):
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <err.h>
#include <string.h>
 
int main()
{
struct stat s;
int fd = open("mlijobs.txt", O_RDONLY);
int cnt, max_cnt, occur;
char *buf, *ptr;
 
if (fd == -1) err(1, "open");
fstat(fd, &s);
ptr = buf = mmap(0, s.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 
cnt = max_cnt = 0;
while(ptr - buf < s.st_size - 33) {
if (!strncmp(ptr, "License OUT", 11) && ++cnt >= max_cnt) {
if (cnt > max_cnt) {
max_cnt = cnt;
occur = 0;
}
/* can't sprintf time stamp: might overlap */
memmove(buf + 26 * occur, ptr + 14, 19);
sprintf(buf + 26 * occur + 19, "%6d\n", cnt);
occur++;
} else if (!strncmp(ptr, "License IN ", 11)) cnt --;
 
while (ptr < buf + s.st_size && *ptr++ != '\n');
}
 
printf(buf);
munmap(buf, s.st_size);
return close(fd);
}
output
2008/10/03_08:39:34    99
2008/10/03_08:40:40 99

C++[edit]

#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
 
int main()
{
const char logfilename[] = "mlijobs.txt";
std::ifstream logfile(logfilename);
 
if (!logfile.is_open())
{
std::cerr << "Error opening: " << logfilename << "\n";
return -1;
}
 
int license = 0, max_license = 0;
std::vector<std::string> max_timestamp;
 
for (std::string logline; std::getline(logfile, logline); )
{
std::string action(logline.substr(8,3));
 
if (action == "OUT")
{
if (++license >= max_license)
{
if (license > max_license)
{
max_license = license;
max_timestamp.clear();
}
max_timestamp.push_back(logline.substr(14, 19));
}
}
else if (action == "IN ")
{
--license;
}
}
 
std::cout << "License count at log end: " << license
<< "\nMaximum simultaneous license: " << max_license
<< "\nMaximum license time(s):\n";
 
std::copy(max_timestamp.begin(), max_timestamp.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
Output:
License count at log end: 0
Maximum simultaneous licenses: 99
Maximum license time(s):
2008/10/03_08:39:34
2008/10/03_08:40:40

C#[edit]

 
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);
}
}
}
}
 
99
2008/10/03_08:39:34
2008/10/03_08:40:40

Clojure[edit]

(defn delta [entry]
(case (second (re-find #"\ (.*)\ @" entry))
"IN " -1
"OUT" 1
(throw (Exception. (str "Invalid entry:" entry)))))
 
(defn t [entry]
(second (re-find #"@\ (.*)\ f" entry)))
 
(let [entries (clojure.string/split (slurp "mlijobs.txt") #"\n")
in-use (reductions + (map delta entries))
m (apply max in-use)
times (map #(nth (map t entries) %)
(keep-indexed #(when (= m %2) %1) in-use))]
(println "Maximum simultaneous license use is" m "at the following times:")
(map println times))
Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

COBOL[edit]

Works with: OpenCOBOL
       IDENTIFICATION DIVISION.
PROGRAM-ID. max-licenses-in-use.
 
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT license-file ASSIGN "mlijobs.txt"
ORGANIZATION LINE SEQUENTIAL
FILE STATUS file-status.
 
DATA DIVISION.
FILE SECTION.
FD license-file.
01 license-record.
03 FILLER PIC X(8).
03 action PIC X(3).
88 license-out VALUE "OUT".
03 FILLER PIC X(3).
03 license-timestamp PIC X(19).
03 FILLER PIC X(13).
 
WORKING-STORAGE SECTION.
01 file-status PIC XX.
88 file-ok VALUE "00".
 
01 max-licenses-out PIC 9(6).
01 num-max-times PIC 99.
01 max-license-times-area.
03 max-timestamps PIC X(19) OCCURS 1 TO 50 TIMES
DEPENDING ON num-max-times.
01 current-licenses-out PIC 9(6).
 
01 i PIC 99.
 
PROCEDURE DIVISION.
DECLARATIVES.
license-file-error SECTION.
USE AFTER ERROR ON license-file.
 
DISPLAY "An unexpected error has occurred. Error "
file-status ". The program will close."
GOBACK
.
END DECLARATIVES.
 
main-line.
OPEN INPUT license-file
IF NOT file-ok
DISPLAY "File could not be opened. Error " file-status
"."
GOBACK
END-IF
 
PERFORM FOREVER
READ license-file
AT END
EXIT PERFORM
END-READ
 
IF license-out
ADD 1 TO current-licenses-out
 
EVALUATE TRUE
WHEN current-licenses-out > max-licenses-out
MOVE 1 TO num-max-times
MOVE current-licenses-out TO max-licenses-out
MOVE license-timestamp
TO max-timestamps (num-max-times)
 
WHEN current-licenses-out = max-licenses-out
ADD 1 TO num-max-times
MOVE license-timestamp
TO max-timestamps (num-max-times)
END-EVALUATE
ELSE
SUBTRACT 1 FROM current-licenses-out
END-IF
END-PERFORM
 
CLOSE license-file
 
DISPLAY "License count at log end: " current-licenses-out
DISPLAY "Maximum simulataneous licenses: " max-licenses-out
DISPLAY "Time(s):"
PERFORM VARYING i FROM 1 BY 1 UNTIL num-max-times < i
DISPLAY max-timestamps (i)
END-PERFORM
 
GOBACK
.

Common Lisp[edit]

Library: CL-PPCRE
(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)))))))
> (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[edit]

void main() {
import std.stdio;
int nOut, maxOut = -1;
string[] maxTimes;
 
foreach (string job; lines(File("mlijobs.txt"))) {
nOut += (job[8] == 'O') ? 1 : -1;
if (nOut > maxOut) {
maxOut = nOut;
maxTimes = null;
}
if (nOut == maxOut)
maxTimes ~= job[14 .. 33];
}
 
writefln("Maximum simultaneous license use is %d at" ~
" the following times:\n%( %s\n%)", maxOut, maxTimes);
}
Output:
Maximum simultaneous license use is 99 at the following times:
 "2008/10/03_08:39:34"
 "2008/10/03_08:40:40"

E[edit]

Translation of: Python
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`)
}

Eiffel[edit]

 
class
APPLICATION
 
create
make
 
feature
 
make
-- Max Licences used.
local
count: INTEGER
max_count: INTEGER
date: STRING
do
read_list
create date.make_empty
across
data as d
loop
if d.item.has_substring ("OUT") then
count := count + 1
if count > max_count then
max_count := count
date := d.item
end
elseif d.item.has_substring ("IN") then
count := count - 1
end
end
io.put_string ("Max Licences OUT: " + max_count.out)
io.new_line
io.put_string ("Date: " + date.substring (15, 33))
end
 
original_list: STRING = "mlijobs.txt"
 
feature {NONE}
 
read_list
-- Data read into 'data.
local
l_file: PLAIN_TEXT_FILE
do
create l_file.make_open_read_write (original_list)
l_file.read_stream (l_file.count)
data := l_file.last_string.split ('%N')
l_file.close
end
 
data: LIST [STRING]
 
end
 
Output:
Max Licences OUT: 99
Date: 2008/10/03_08:39:34

Erlang[edit]

 
-module( text_processing_max_licenses ).
 
-export( [out_dates_from_file/1, task/0] ).
 
out_dates_from_file( Name ) ->
{ok, Binary} = file:read_file( Name ),
Lines = binary:split( Binary, <<"\n">>, [global] ),
{_N, _Date, Dict} = lists:foldl( fun out_dates/2, {0, "", dict:new()}, Lines ),
[{X, dict:fetch(X, Dict)} || X <- dict:fetch_keys( Dict )].
 
task() ->
[{Max, Dates} | _T] = lists:reverse(lists:sort(out_dates_from_file("mlijobs.txt")) ),
io:fwrite( "Max licenses was ~p at ~p~n", [Max, Dates] ).
 
 
 
out_dates( <<>>, Acc ) -> Acc;
out_dates( Line, {N, Date, Dict} ) ->
[_License, Direction, <<"@">>, New_date | _T] = [X || X <- binary:split(Line, <<" ">>, [global]), X =/= <<>>],
New_n = out_dates_n( N, Direction ),
New_dict = out_dates_dict( N, New_n, Date, Dict ),
{New_n, New_date, New_dict}.
 
out_dates_dict( N, New_n, Date, Dict ) when N > New_n -> dict:append( N, Date, Dict );
out_dates_dict( _N, _New_n, _Date, Dict ) -> Dict.
 
out_dates_n( N, <<"OUT">> ) -> N + 1;
out_dates_n( N, <<"IN">> ) -> N - 1.
 
Output:
12> text_processing_max_licenses:task().
Max licenses was 99 at [<<"2008/10/03_08:39:34">>,<<"2008/10/03_08:40:40">>]

Euphoria[edit]

function split(sequence s, integer c)
sequence out
integer first, delim
out = {}
first = 1
while first <= length(s) do
delim = find_from(c, s, first)
if delim = 0 then
delim = length(s) + 1
end if
out = append(out, s[first..delim-1])
first = delim + 1
end while
return out
end function
 
include get.e
function val(sequence s)
sequence v
v = value(s)
return v[2] - v[1] * v[1]
end function
 
constant fn = open("mlijobs.txt", "r")
integer maxout
sequence jobs, line, maxtime
object x
jobs = {}
maxout = 0
while 1 do
x = gets(fn)
if atom(x) then
exit
end if
line = split(x, ' ')
line[$] = val(line[$])
if equal(line[2], "OUT") then
jobs &= line[$]
if length(jobs) > maxout then
maxout = length(jobs)
maxtime = {line[4]}
elsif length(jobs) = maxout then
maxtime = append(maxtime, line[4])
end if
else
jobs[find(line[$],jobs)] = jobs[$]
jobs = jobs[1..$-1]
end if
end while
close(fn)
 
printf(1, "Maximum simultaneous license use is %d at the following times:\n", maxout)
for i = 1 to length(maxtime) do
printf(1, "%s\n", {maxtime[i]})
end for

Output:

Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

Factor[edit]

Placing the file in resource:work/mlijobs.txt:

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

Forth[edit]

 
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
 

Fortran[edit]

Works with: Fortran version 90 and later
 
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
 

Output

 Maximum simultaneous license use is  99 at the following times:
 2008/10/03_08:39:34                                           
 2008/10/03_08:40:40

Gema[edit]

Start with gema -f licenses.gema mlijobs.txt

 
@set{count;0};@set{max;0}
 
License OUT \@ * *\[email protected][email protected]{${count},*}
License IN \@ * *\[email protected]{count}
\[email protected]{${max},${times${max}}}
 
testmax:*,[email protected]{${max};$1;@set{max;$1};;[email protected]{times${count};$2\n}
 
report:*,*=Maximum simultaneous license use is * at\n*
 

Output:

Maximum simultaneous license use is 99 at
2008/10/03_08:39:34
2008/10/03_08:40:40

Go[edit]

package main
 
import (
"bufio"
"bytes"
"fmt"
"log"
"os"
)
 
const (
filename = "mlijobs.txt"
inoutField = 1
timeField = 3
numFields = 7
)
 
func main() {
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
var ml, out int
var mlTimes []string
in := []byte("IN")
s := bufio.NewScanner(file)
for s.Scan() {
f := bytes.Fields(s.Bytes())
if len(f) != numFields {
log.Fatal("unexpected format,", len(f), "fields.")
}
if bytes.Equal(f[inoutField], in) {
out--
if out < 0 {
log.Fatalf("negative license use at %s", f[timeField])
}
continue
}
out++
if out < ml {
continue
}
 
if out > ml {
ml = out
mlTimes = mlTimes[:0]
}
mlTimes = append(mlTimes, string(f[timeField]))
}
if err = s.Err(); err != nil {
log.Fatal(err)
}
 
fmt.Println("max licenses:", ml)
fmt.Println("at:")
for _, t := range mlTimes {
fmt.Println(" ", t)
}
}
Output:
max licenses: 99
at:
  2008/10/03_08:39:34
  2008/10/03_08:40:40

Groovy[edit]

def max = 0
def dates = []
def licenses = [:]
new File('licenseFile.txt').eachLine { line ->
(line =~ /License (\w+)\s+@ ([\d\/_:]+) for job (\d+)/).each { matcher, action, date, job ->
switch (action) {
case 'IN':
assert licenses[job] != null : "License has not been checked out for $job"
licenses.remove job
break
case 'OUT':
assert licenses[job] == null : "License has already been checked out for $job"
licenses[job] = date
def count = licenses.keySet().size()
if (count > max) {
max = count
dates = [ date ]
} else if (count == max) {
dates << date
}
break
default:
throw new IllegalArgumentException("Unsupported license action $action")
}
}
}
 
println "Maximum Licenses $max"
dates.each { date -> println " $date" }
 

Output:

Maximum Licenses 99
  2008/10/03_08:39:34
  2008/10/03_08:40:40

Haskell[edit]

 
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
 

HicEst[edit]

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

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

Icon and Unicon[edit]

The following solution works in both languages:

procedure main(A)
maxCount := count := 0
 
every !&input ? case tab(upto('@')) of {
"License OUT ": {
maxTime := (maxCount <:= (count +:= 1), [])
put(maxTime, (maxCount = count, ="@ ", tab(find(" for "))))
}
"License IN ": count -:= (count > 0, 1) # Error check
}
 
write("There were ",maxCount," licenses out at:")
every write("\t",!maxTime)
end

And a run of the program:

->ml <mlijobs.txt
There were 99 licenses out at:
        2008/10/03_08:39:34
        2008/10/03_08:40:40
->


J[edit]

   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
 Maximum simultaneous license use is 99 at the following times:
 2008/10/03_08:39:34                                           
 2008/10/03_08:40:40

Java[edit]

Works with: Java version 1.5+
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);
}
}
Max licenses out: 99
At time(s): [2008/10/03_08:39:34, 2008/10/03_08:40:40]

JavaScript[edit]

Works with: JScript
for the file i/o
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 '));

output:

Max licenses out: 99
  2008/10/03_08:39:34
  2008/10/03_08:40:40

jq[edit]

Works with: jq version 1.4
# Input: an array of strings
def max_licenses_in_use:
# state: [in_use = 0, max_in_use = -1, max_in_use_at = [] ]
reduce .[] as $line
([0, -1, [] ];
($line|split(" ")) as $line
| if $line[1] == "OUT" then
.[0] += 1 # in_use++;
| if .[0] > .[1] # (in_use > max_in_use)
then .[1] = .[0] # max_in_use = in_use
| .[2] = [$line[3]] # max_in_use_at = [$line[3]]
elif .[0] == .[1] # (in_use == max_in_use)
then .[2] += [$line[3]] # max_in_use_at << $line[3]
else .
end
elif $line[1] == "IN" then .[0] -= 1 # in_use--
else .
end )
| "Max licenses out: \(.[1]) at:\n \(.[2]|join("\n "))" ;
 
# The file is read in as a single string and so must be split at newlines:
split("\n") | max_licenses_in_use
Output:
$ time /usr/local/bin/jq -M -R -r -s -f Max_licences_in_use.jq mlijobs.txt
Max licenses out: 99 at:
 2008/10/03_08:39:34
 2008/10/03_08:40:40

real	0m0.163s
user	0m0.154s
sys	0m0.005s

K[edit]

  r:m@&a=x:|/a:+\{:[x[8+!3]~"OUT";1;-1]}'m:0:"mlijobs.txt";
`0:,/"Maximum simultaneous license use is ",$x;
`0:" at the following times:\n";`0:r[;14+!19]

Output:

Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

Lua[edit]

 
filename = "mlijobs.txt"
io.input( filename )
 
max_out, n_out = 0, 0
occurr_dates = {}
 
while true do
line = io.read( "*line" )
if line == nil then break end
 
if string.find( line, "OUT" ) ~= nil then
n_out = n_out + 1
if n_out > max_out then
max_out = n_out
occurr_dates = {}
occurr_dates[#occurr_dates+1] = string.match( line, "@ ([%d+%p]+)" )
elseif n_out == max_out then
occurr_dates[#occurr_dates+1] = string.match( line, "@ ([%d+%p]+)" )
end
else
n_out = n_out - 1
end
end
 
print( "Maximum licenses in use:", max_out )
print( "Occurrences:" )
for i = 1, #occurr_dates do
print( "", occurr_dates[i] )
end

Output:

Maximum licenses in use: 99
Occurrences:
 	2008/10/03_08:39:34
 	2008/10/03_08:40:40

M4[edit]

 
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)
 

Output:

99
 @ 2008/10/03_08:39:34  @ 2008/10/03_08:40:40

Mathematica[edit]

LC = 0; LCMax = 0; Scan[
If[MemberQ[#, "OUT"], LC++;
If[LCMax < LC, LCMax = LC; LCMaxtimes = {};];
If[LCMax == LC, AppendTo[LCMaxtimes, #[[4]]]],
LC--;] &, Import["mlijobs.txt", "Table"]]
Print["The maximum number of licenses used was ", LCMax, ", at ", LCMaxtimes]

Output:

-> The maximum number of licenses used was 99, at {2008/10/03_08:39:34,2008/10/03_08:40:40}

MAXScript[edit]

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

Output

Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

Nim[edit]

Translation of: Python
import strutils
 
var
curOut = 0
maxOut = -1
maxTimes = newSeq[string]()
 
for job in lines "mlijobs.txt":
if "OUT" in job: inc curOut else: dec curOut
if curOut > maxOut:
maxOut = curOut
maxTimes = @[]
if curOut == maxOut:
maxTimes.add job.split[3]
 
echo "Maximum simultaneous license use is ",maxOut," at the following times:"
for i in maxTimes: echo " ",i

Output:

Maximum simultaneous license use is 99 at the following times:
  2008/10/03_08:39:34
  2008/10/03_08:40:40

OCaml[edit]

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

Oz[edit]

Translation of: Python
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}

Output:

Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

PARI/GP[edit]

license()={
my(v=externstr("type mlijobs.txt"),u,cur,rec,t);
for(i=1,#v,
u=Vec(v[i]);
if(#u>9 && u[9] == "O",
if(cur++>rec,
rec=cur;
t=[v[i]]
,
if(cur == rec,t=concat(t,[v[i]]))
)
,
cur--
)
);
print(apply(s->concat(vecextract(Vec(s),"15..33")), t));
rec
};
["2008/10/03_08:39:34", "2008/10/03_08:40:40"]
%1 = 99

Perl[edit]

#!/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;

Example output:

Maximum simultaneous license use is 99 at the following times:
  2008/10/03_08:39:34
  2008/10/03_08:40:40

Perl 6[edit]

Redirecting the mlijobs.txt file to STDIN:

my %licenses;
 
%licenses<count max> = 0,0;
 
for $*IN.lines -> $line {
my ( $license, $date_time );
( *, $license, *, $date_time ) = split /\s+/, $line;
if $license eq 'OUT' {
%licenses<count>++;
if %licenses<count> > %licenses<max> {
%licenses<max> = %licenses<count>;
%licenses<times> = [$date_time];
}
elsif %licenses<count> == %licenses<max> {
%licenses<times>.push($date_time);
}
}
else {
if %licenses<count> == %licenses<max> {
%licenses<times>[*-1] ~= " through " ~ $date_time;
}
%licenses<count>--;
}
};
 
my $plural = %licenses<times>.elems == 1 ?? '' !! 's';
 
say "Maximum concurrent licenses in use: {%licenses<max>}, in the time period{$plural}:";
say join ",\n", %licenses<times>.list;

Example output:

Maximum concurrent licenses in use: 99, in the time periods:
2008/10/03_08:39:34 through 2008/10/03_08:39:45,
2008/10/03_08:40:40 through 2008/10/03_08:40:47

Phix[edit]

Modified copy of Euphoria

constant fn = open("mlijobs.txt", "r")
integer maxout = 0, jobnumber
sequence jobs = {}, maxtime, scanres
string inout, jobtime
object line
while 1 do
line = gets(fn)
if atom(line) then exit end if
scanres = scanf(line,"License %s @ %s for job %d\n")
if length(scanres)!=1 then
printf(1,"error scanning line: %s\n",{line})
{} = wait_key()
abort(0)
end if
{{inout,jobtime,jobnumber}} = scanres
if inout="OUT" then
jobs &= jobnumber
if length(jobs)>maxout then
maxout = length(jobs)
maxtime = {jobtime}
elsif length(jobs)=maxout then
maxtime = append(maxtime, jobtime)
end if
else
jobs[find(jobnumber,jobs)] = jobs[$]
jobs = jobs[1..$-1]
end if
end while
close(fn)
 
printf(1, "Maximum simultaneous license use is %d at the following times:\n", maxout)
for i = 1 to length(maxtime) do
printf(1, "%s\n", {maxtime[i]})
end for
Output:
Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

PHP[edit]

$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 . '<br>';
for($i=0;$i<count($times);$i++){
echo $times[$i] . '<br>';
}
99
2008/10/03_08:39:34
2008/10/03_08:40:40

PL/I[edit]

 
text3: procedure options (main); /* 19 November 2011 */
declare line character (80) varying;
declare (nout, max_nout) fixed;
declare saveline character (80) varying controlled;
declare k fixed binary;
declare in file input;
 
open file (in) title ('/TEXT-MAX.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
do; allocate saveline; saveline = line; end;
if nout > max_nout then
do;
do while (allocation(saveline) > 0); free saveline; end;
max_nout = nout;
allocate saveline;
saveline = line;
end;
end;
 
finish_up:
put skip list ('The maximum number of licences taken out = ' || max_nout);
do while (allocation(saveline) > 0);
k = index(saveline, '@');
if k > 0 then put skip list ('It occurred at ' || substr(saveline, k+1) );
free saveline;
end;
end text3;
 

OUTPUT:

The maximum number of licences taken out =       99 
It occurred at  2008/10/03_08:40:40 for job 1837 
It occurred at  2008/10/03_08:39:34 for job 1833 

PicoLisp[edit]

Translation of: AWK

Put the following into an executable file "licenses":

#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
 
(zero Count MaxCount)
 
(in (opt)
(while (split (line) " ")
(case (pack (cadr (setq Line @)))
(IN
(dec 'Count) )
(OUT
(let Time (cadddr Line)
(cond
((> (inc 'Count) MaxCount)
(setq MaxCount Count MaxTimes Time) )
((= Count MaxCount)
(setq MaxTimes (pack MaxTimes " and " Time)) ) ) ) ) ) ) )
 
(prinl "The biggest number of licenses is " MaxCount " at " MaxTimes " !")
(bye)

Then it can be called as

$ ./licenses mlijobs.txt
The biggest number of licenses is 99 at 2008/10/03_08:39:34 and 2008/10/03_08:40:40 !

PowerShell[edit]

 
[int]$count = 0
[int]$maxCount = 0
[datetime[]]$times = @()
 
$jobs = Get-Content -Path ".\mlijobs.txt" | ForEach-Object {
[string[]]$fields = $_.Split(" ",[StringSplitOptions]::RemoveEmptyEntries)
[datetime]$datetime = Get-Date $fields[3].Replace("_"," ")
[PSCustomObject]@{
State = $fields[1]
Date = $datetime
Job = $fields[6]
}
}
 
foreach ($job in $jobs)
{
switch ($job.State)
{
"IN"
{
$count--
}
"OUT"
{
$count++
 
if ($count -gt $maxCount)
{
$maxCount = $count
$times = @()
$times+= $job.Date
}
elseif ($count -eq $maxCount)
{
$times+= $job.Date
}
}
}
}
 
[PSCustomObject]@{
LicensesOut = $maxCount
StartTime = $times[0]
EndTime = $times[1]
}
 
Output:
LicensesOut StartTime            EndTime             
----------- ---------            -------             
         99 10/3/2008 8:39:34 AM 10/3/2008 8:40:40 AM

PureBasic[edit]

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()
99 license(s) used at ;
2008/10/03_08:39:34
2008/10/03_08:40:40

Press ENTER to exit

Python[edit]

out, max_out, max_times = 0, -1, []
for job in open('mlijobs.txt'):
out += 1 if "OUT" in job else -1
if out > max_out:
max_out, max_times = out, []
if out == max_out:
max_times.append(job.split()[3])
 
print("Maximum simultaneous license use is %i at the following times:" % max_out)
print(' ' + '\n '.join(max_times))
Output:
Maximum simultaneous license use is 99 at the following times:
  2008/10/03_08:39:34
  2008/10/03_08:40:40

R[edit]

 
# 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")
 

Racket[edit]

#lang racket
;;; reads a licence file on standard input
;;; returns max licences used and list of times this occurred
(define (count-licences)
(let inner ((ln (read-line)) (in-use 0) (max-in-use 0) (times-list null))
(if (eof-object? ln)
(values max-in-use (reverse times-list))
(let ((mtch (regexp-match #px"License (IN |OUT) @ (.*) for job.*" ln)))
(cond
[(string=? "OUT" (second mtch))
(let ((in-use+1 (add1 in-use)))
(cond
[(> in-use+1 max-in-use)
(inner (read-line) in-use+1 in-use+1 (list (third mtch)))]
[(= in-use+1 max-in-use)
(inner (read-line) in-use+1 max-in-use (cons (third mtch) times-list))]
[else (inner (read-line) in-use+1 max-in-use times-list)]))]
[(string=? "IN " (second mtch))
(inner (read-line) (sub1 in-use) max-in-use times-list)]
[else (inner (read-line) in-use max-in-use times-list)])))))
 
(define-values (max-used max-used-when)
(with-input-from-file "mlijobs.txt" count-licences))
(printf "Maximum licences in simultaneously used is ~a at the following times:~%"
max-used)
(for-each displayln max-used-when)
 

Output:

Maximum licences in simultaneously used is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

The following takes advantage of a combination of for/fold and (in-lines) (and is possible more in the Racket idiom, rather than just using (read-line) and (regexp-match):

#lang racket
;;; reads a licence file on standard input
;;; returns max licences used and list of times this occurred
(define (count-licences)
(define (sub-count-licences)
(for/fold ((in-use 0) (max-in-use 0) (times-list null))
((ln (in-lines)))
(let ((mtch (regexp-match #px"License (IN |OUT) @ (.*) for job.*" ln)))
(cond
[(string=? "OUT" (second mtch))
(let ((in-use+1 (add1 in-use)))
(cond
[(> in-use+1 max-in-use) (values in-use+1 in-use+1 (list (third mtch)))]
[(= in-use+1 max-in-use) (values in-use+1 max-in-use (cons (third mtch) times-list))]
[else (values in-use+1 max-in-use times-list)]))]
[(string=? "IN " (second mtch)) (values (sub1 in-use) max-in-use times-list)]
[else (values in-use max-in-use times-list)]))))
(let-values (((in-use max-in-use times-list) (sub-count-licences)))
(values max-in-use (reverse times-list))))
 
(define-values (max-used max-used-when) (with-input-from-file "mlijobs.txt" count-licences))
(printf "Maximum licences in simultaneously used is ~a at the following times:~%" max-used)
(for-each displayln max-used-when)

(Same output)

REXX[edit]

version 1[edit]

/*REXX program processes instrument data as read from a time sorted data file.*/
iFID= 'LICENSE.LOG' /*the fileID of the input file. */
high=0 /*highest number of licenses (so far). */
#=0 /*the count of number of licenses out. */
n=0 /*the number of highest licenses out. */
do recs=0 while lines(iFID)\==0 /* [↓] read file until end─of─file. */
parse value linein(iFID) with . ? . $ /*get IN│OUT status, job info.*/
if ?=='IN' then #=#-1 /*decrement the license count.*/
else if ?=='OUT' then #=#+1 /*increment " " " */
if # >high then do; n=1; job.1=$; end /*the job info for highest cnt*/
if #==high then do; n=n+1; job.n=$; end /* " " " " equal " */
high=max(high,#) /*calculate max license count.*/
end /*while ···*/
 
say recs 'records read from the input file: ' iFID
say 'The maximum number of licenses out is ' high " at:"
say
do j=1 for n /*show what/when max licenses occurred.*/
say left('',20) job.j /*indent the information displayed. */
end /*j*/ /*stick a fork in it, we're all done. */

output   when using the default input file:

10000 records read from the input file:  LICENSE.LOG
The maximum number of licenses out is  99  at:

                     2008/10/03_08:39:34 for job 1833
                     2008/10/03_08:40:40 for job 1837

Version 2 dual-coded for PC and TSO[edit]

It should be noted that almost every REXX interpreter returns a different string for   parse source   under Microsoft Windows:

  •   MSDOS     for   BREXX
  •   PCDOS     for   PC/REXX   and   Personal Rexx for DOS
  •   WIN         for   Personal Rexx for Windows
  •   WIN32     for   Regina
  •   Win32     for   R4   and   ROO


It is unknown which classic REXX interpreter can be used (under Windows) below, it fails for the above mentioned seven REXX interpreters.
I am sure it has worked for Regina. Maybe this is now correct for all the WIN (and xxDOS) situations (pun intended)

/* REXX **************************************************************
* 19.11.2012 Walter Pachl transcribed from PL/I
* and dual-coded (for PC (Windows) and TSO)
**********************************************************************/

Parse Source source
call time 'R'
Say source
Parse Upper source system .
If left(system,3)='WIN' |, /* changed from 'Windows' (I see WIN64 in source) */
wordpos(system,'MSDOS PCDOS')>0 Then Do
fid='mlijobs.txt'
Do i=1 By 1 While lines(fid)>0
l.i=linein(fid)
End
l.0=i-1
End
Else Do
"ALLOC FI(IN) DA(MLIJOBS.TEXT) SHR REUSE"
'EXECIO * DISKR IN (STEM L. FINIS'
'FREE FI(IN)'
End
store.0=0
max_nout=0
nout =0
cnt=0
cnt.=0
do i=1 To l.0
line=l.i
Parse Var line 9 inout +3
Select
When inout='OUT' then nout = nout+1;
When inout='IN' then nout = nout-1;
Otherwise Iterate
End
cnt.nout=cnt.nout+1
cnt=cnt+1
if nout = max_nout then
Call store line
if nout > max_nout then Do
max_nout=nout
drop store.
store.0=0
Call store
end;
end;
 
Say 'The maximum number of licences taken out = ' max_nout
Do i=1 to store.0
k=pos('@',store.i)
Say 'It occurred at 'substr(store.i,k+1)
End
limit=5
Do nout=0 To max_nout
If nout=limit+1 Then Say '.........'
If nout<=limit | nout>=max_nout-limit Then
Say right(cnt.nout,5) right(nout,3)
End
Say right(cnt,5) 'Jobs'
Say time('E') 'seconds (elapsed)'
Exit
 
store:
z=store.0+1
store.z=line
store.0=z
Return
Output:
on Windows
D:\>rexx maxl
WindowsNT COMMAND D:\maxl.rex
The maximum number of licences taken out =  99
It occurred at  2008/10/03_08:39:34 for job 1833
It occurred at  2008/10/03_08:40:40 for job 1837
    1   0
    2   1
    2   2
    2   3
    2   4
    2   5
.........
   24  94
   22  95
   15  96
    7  97
    5  98
    2  99
10000 Jobs
0.234000 seconds (elapsed) ooRexx

D:\>regina maxl
WIN64 COMMAND D:\maxl.rex
...
10000 Jobs
.177000 seconds (elapsed) Regina
Output:
on TSO
TSO COMMAND LIC SYS00059 N555555.PRIV.CLIST ? TSO ISPF ?
The maximum number of licences taken out =  99
It occurred at  2008/10/03_08:39:34 for job 1833
It occurred at  2008/10/03_08:40:40 for job 1837
    1   0
    2   1
    2   2
    2   3
    2   4
    2   5
.........
   24  94
   22  95
   15  96
    7  97
    5  98
    2  99
10000 Jobs
0.384154 seconds (elapsed)

Ruby[edit]

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

Example output:

Maximum simultaneous license use is 99 at the following times:
  2008/10/03_08:39:34
  2008/10/03_08:40:40

Run BASIC[edit]

open "c:\data\temp\logFile.txt" for input as #f
while not(eof(#f))
line input #f, a$
if word$(a$,2," ") = "IN" then count = count - 1 else count = count + 1
maxCount = max(maxCount,count)
wend
open "c:\data\temp\logFile.txt" for input as #f
while not(eof(#f))
line input #f, a$
if word$(a$,2," ") = "IN" then count = count - 1 else count = count + 1
if count = maxCount then theDate$ = theDate$ + " | " + word$(a$,4," ") + " Job:";word$(a$,7," ")
wend
print maxCount;" ";theDate$

Seed7[edit]

$ include "seed7_05.s7i";
 
const proc: main is func
local
var file: inFile is STD_NULL;
var string: line is "";
var integer: currLicenses is 0;
var integer: maxLicenses is 0;
var array string: maxLicenseTimes is 0 times "";
var string: eventTime is "";
begin
inFile := open("mlijobs.txt", "r");
while hasNext(inFile) do
line := getln(inFile);
if line[9 len 3] = "OUT" then
incr(currLicenses);
if currLicenses >= maxLicenses then
if currLicenses > maxLicenses then
maxLicenses := currLicenses;
maxLicenseTimes := 0 times "";
end if;
maxLicenseTimes &:= line[15 len 19];
end if;
elsif currLicenses > 0 then
decr(currLicenses);
end if;
end while;
close(inFile);
writeln("Maximum simultaneous license use is " <& maxLicenses <& " at the following times:");
for eventTime range maxLicenseTimes do
writeln(eventTime);
end for;
end func;

Output:

Maximum simultaneous license use is 99 at the following times:
2008/10/03_08:39:34
2008/10/03_08:40:40

Sidef[edit]

Translation of: Perl
var out = 0;
var max_out = -1;
var max_times = [];
 
ARGF.each { |line|
out += (line ~~ /OUT/ ? 1 : -1);
out > max_out && (
max_out = out;
max_times = [];
);
out == max_out && (
max_times << line.split(' ')[3];
);
}
 
say "Maximum simultaneous license use is #{max_out} at the following times:";
max_times.each {|t| " #{t}".say };
Output:
$ sidef max_licenses.sf < mlijobs.txt
Maximum simultaneous license use is 99 at the following times:
  2008/10/03_08:39:34
  2008/10/03_08:40:40

Tcl[edit]

Translation of: Python
 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"
}

Output matches Python

TUSCRIPT[edit]

 
$$ MODE TUSCRIPT
joblog="mlijobs.txt",jobnrout=0
log=FILE (joblog)
DICT jobnrout CREATE
LOOP l=log
jobout=EXTRACT (l,":License :"|,": :")
IF (jobout=="out") THEN
time=EXTRACT (l,":@ :"|,": :"), jobnrout=jobnrout+1
DICT jobnrout APPEND/QUIET jobnrout,num,cnt,time;" "
ELSE
jobnrout=jobnrout-1
ENDIF
ENDLOOP
DICT jobnrout UNLOAD jobnrout,num,cnt,time
DICT jobnrout SIZE maxlicout
times=SELECT (time,#maxlicout)
PRINT "The max. number of licences out is ", maxlicout
PRINT "at these times: ", times
 

Output:

The max. number of licences out is 99
at these times: 2008/10/03_08:39:34 2008/10/03_08:40:40

Ursala[edit]

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.

 
#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$^&[email protected]; [email protected] ~&rS
format = ^|C\~& --' licenses in use [email protected]+ %nP
 
#show+
 
main = format search scan log

output:

99 licenses in use at
2008/10/03_08:39:34
2008/10/03_08:40:40

Vedit macro language[edit]

 
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)
 

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

zkl[edit]

Translation of: D

The referenced log file is no longer available, so, using the example log:

nOut,maxOut,maxTimes:=0,-1,List();
foreach job in (File("mlijobs.txt")){
_,status,_,date:=job.split();
nOut+=( if(status.toUpper()=="OUT") 1 else -1 );
if(nOut>maxOut){ maxOut=nOut; maxTimes.clear(); }
if(nOut==maxOut) maxTimes.append(date);
}
println(("Maximum simultaneous license use is %d at"
" the following times:\n %s").fmt(maxOut,maxTimes.concat("\n")));
Output:
Maximum simultaneous license use is 1 at the following times:
 2008/10/03_23:51:05