Text processing/Max licenses in use: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|R}}: Fixed filename)
m (→‎{{header|Ursala}}: corrected a bug)
Line 481: Line 481:


=={{header|Ursala}}==
=={{header|Ursala}}==
{{incorrect|Ursala|It shows incorrect times.}}
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.
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.


Line 490: Line 489:
log = ^(~&hh==`O,~&tth)*FtPS sep` *F mlijobs_dot_txt
log = ^(~&hh==`O,~&tth)*FtPS sep` *F mlijobs_dot_txt
scan = @NiX ~&ar^& ^C/~&alrhr2X ~&arlh?/~&faNlCrtPXPR ~&fabt2R
scan = @NiX ~&ar^& ^C/~&alrhr2X ~&arlh?/~&faNlCrtPXPR ~&fabt2R
search = leql$^&hl@lK2; ^/length@hl ~&rS
search = @lSzyCrSPp leql$^&hl@lK2; ^/length@hl ~&rS
format = ^|C\~& --' licenses in use at'@h+ %nP
format = ^|C\~& --' licenses in use at'@h+ %nP


Line 498: Line 497:
output:
output:
<pre>99 licenses in use at
<pre>99 licenses in use at
2008/10/03_08:39:45
2008/10/03_08:39:34
2008/10/03_08:40:47
2008/10/03_08:40:40
</pre>
</pre>



Revision as of 13:51, 13 August 2009

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 softwares file faithfully records a checkout event when a copy of the software starts and a checkin event when the software finishes. 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.

APL

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

Translation of: Python

<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

C

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <string.h>
  3. include <sys/types.h>
  1. define INOUT_LEN 4
  2. define TIME_LEN 20
  3. 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>


E

Translation of: Python

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

Fortran

Works with: Fortran version 90 and later

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

J

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

</lang>

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

Java

Works with: Java version 1.5+

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

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>

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

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>

  1. Read in data, discard useless bits

dfr <- read.table("mlijobs.txt") dfr <- dfr[,c(2,4)]

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

  1. As a bonus, plot license use

plot(times, n.checked.out, type="s") </lang>

Ruby

<lang ruby>out = 0 max_out = -1 max_times = []

open('mlijobs.txt') do |file|

 for job in file
   if job.include?("OUT")
       out += 1
   else
       out -= 1
   end
   if out > max_out
       max_out = out
       max_times = []
   end
   if out == max_out
       max_times << job.split[3]
   end
 end

end

puts "Maximum simultaneous license use is #{max_out} at the following times:" for time in max_times

 puts "  #{time}"

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

Translation of: Python

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

  1. import std
  2. 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

  1. 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. 1 = 0 // Number of licenses active
  2. 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