Text processing/3

From Rosetta Code

(Redirected from Max Licenses In Use)
Jump to: navigation, search
Text processing/3 is a programming task. Visitors like you are encouraged to solve it according to the task description, using any language they may happen to know.
Add to BlogMarksAdd to del.icio.usAdd to diggAdd to NewsvineAdd to redditAdd to Slashdot

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


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.

Contents

[edit] APL

Works with: APL2Translation 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

[edit] AutoHotkey

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

[edit] AWK

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

$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 " !"}
 
Output:
The biggest number of licenses is 99 at 2008/10/03_08:39:34 !

[edit] 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);
}

[edit] C++

Library: Boost

#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 ;
}
}
 
Output:
The maximum number of licenses out is 99 at 2008/10/03_08:39:34 !

[edit] Common Lisp

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

[edit] 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);
}
}
 

[edit] E

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

[edit] Factor

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

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

[edit] Fortran

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

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

[edit] J

 
NB. Parse data, select columns
'I D' =: (8 ; 14+i.19) { ::]"1 L:0 ];._2 ] 1!:1 ::(''"_) <'licenses.txt'
 
NB. Calculate number of licenses used at any given time
lu =: +/\ _1 ^ 'OI' i. I
 
NB. Find the maxima
mx =: (I.@:= >./) lu
 
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

[edit] Java

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]

[edit] JavaScript

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

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

Output:

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

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

Output

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

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

[edit] Oz

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

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

Example output:

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

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

Example output:

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

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

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

Example output:

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

[edit] Tcl

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

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

 
#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

output:

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

[edit] Vedit macro language

 
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
Personal tools
Google AdSense