#!/usr/bin/perl -w

# Histogram z dowolnej kolumny danych wejsciowych
# [c]piotao, 20011115, @emalia, perl 5+
# zmieniony i przetlumaczony na polski 20070123 dla studentow
# wykladu monograficznego Perl-programowanie

# Sposob uzycia:
# histogram.pl input.txt > results.txt
# Opcje: -r10 -c1 -f10%f10%f\\n
# -r   - okresla wielosc zakresow na osi x
# -c   - okresla ktora kolumna z pliku ma byc wczytana (0-pierwsza, domyslnie)
# -f   - format danych wynikowych wypisywanych na standardowe wyjscie (zawsze 2 kolumny)
#
# Wartosci standardowe: ZAKRES=1000 COLUMN=0 FORMAT=%10.4f%10.4f\n

### KONFIGURACJA ############################################

my $ZAKRES   = 1000;    # zrob histogram z czynnikiem skalujacym = 1000
my $COLUMN   =    0;    # wczytaj dane z pierwszej kolumny (ma ona numer 0)

# teraz okreslamy format danych wyjsciowych, sa to dwie kolumny wysylane na standardowe
# wyjscie; pierwsza z nich to wartosc zakresu danych, druga to wartosc
# histogramu dla tego zakresu
my $FORMAT = "%10.4f%10.4f\n";   # format jednego wiersza w stylu C - printf

#############################################################################

use strict;       # tryb scislego sprawdzania nazw
use warnings;     # tryb ostrzezen
use Getopt::Std;  # uzywamy obslugi wiersza polecen: proste argumenty typu -x

my $var2,%hist;   # zmienne pomocnicze, w tym %hist do pamietania histogramu

# analiza argumentow wiersza polecen i przedefiniowanie $ZAKRES, $COLUMN lub $FORMAT
&AnalizujOpcje;

# obliczanie wartosci histogramu dla kazdego zakresu danych
# polega to na tym, ze dzielimy wybrana kolumne przez zakres
# w jakim histogram ma byc policzony i wynik zapamietujemy w haszu
# jako wartosc calkowita, ktora bedzie na osi X, zliczajac wszystkie
# takie same wystapienia tych wartosci (dlatego hasz)
# zapamietaj: wynik histogramu jest kluczem, ilosc tych wynikow - wartoscia
while(<>){
  $hist{ int( (split)[$COLUMN] / $ZAKRES ) }++;
}

# wypisywanie wynikow to proste wypisanie hasza z sortowaniem kluczy
foreach my $value (sort { $a <=> $b } keys %hist){
  printf $FORMAT,$value*$ZAKRES,$hist{$value};
}

exit;

# analiza argumentow z wiersza polecen programu
sub AnalizujOpcje {

  # na poczatek ustawiamy format, o ile go podano, w tym celu:
  for(my $i = 0; $i <= $#ARGV; $i++){         # zasuwamy po wszystkich argumentach
    if($ARGV[$i] =~ /^-f(.+)/){               # jezeli opcja to -f...
      $FORMAT = $1; splice @ARGV,$i,1; last;  # to wyciagamy to '...' jako format
    }
  }
  getopt('rcf');                          # wyciagamy opcje -r, -c i -f (one znikaja)
  if(defined $opt_r){ $ZAKRES = $opt_r }  # ale trafiaja do zmiennych $opt_X skad je
  if(defined $opt_c){ $COLUMN = $opt_c }  # przepisujemy do wlasciwych zmiennych
  $FORMAT =~ s/\\n/\n/g;                  # ostatnia poprawka w FORMAT
}