{ File: bosco.pas }

{ Scopo: esercizio sull'uso di liste collegate }

program Bosco;
{ Esercizio di esame di Fondamenti di Informatica del 19/2/1997.
  Soluzione completa. }

const
  MaxCoordX = 19;
  MaxCoordY = 29;

type
  TipoCoordinataX  = 0..MaxCoordX;
  TipoCoordinataY  = 0..MaxCoordY;
  TipoCoordinate   = record
                       x : TipoCoordinataX;
                       y : TipoCoordinataY
                     end;
  TipoRegione      = record
                       coordinate        : TipoCoordinate;   { della regione }
                       volpi, scoiattoli : 0..MAXINT  { numero di tane di volpi
                                                        e di scoiattoli }
                     end;

  TipoListaRegioni = ^TipoRecordLista;
  TipoRecordLista  = record
                       regione : TipoRegione;
                       next    : TipoListaRegioni
                     end;


{ procedura che risolve il punto 1 }

  procedure SommaNumTaneArea (lista_regioni                 : TipoListaRegioni;
                              inferiore, superiore          : TipoCoordinate;
                              var tot_volpi, tot_scoiattoli : integer);
  { Calcola il numero totale di tane di volpi e di scoiattoli nelle regioni
    censite contenute nell'area di bosco delimitata da p1 e p2. }

    function InArea (inf, sup, reg : TipoCoordinate): boolean;
    { Verifica se una regione` e` contenuta nell'area di bosco delimitata da
      inf e sup. }
    begin
      InArea := (inf.x <= reg.x) and (reg.x <= sup.x) and
                (inf.y <= reg.y) and (reg.y <= sup.y)
    end; { InArea }

  begin { SommaNumTaneArea }
    tot_volpi := 0;
    tot_scoiattoli := 0;
    while lista_regioni <> NIL do
    begin
      if InArea(inferiore, superiore, lista_regioni^.regione.coordinate) then
      begin
        tot_volpi := tot_volpi + lista_regioni^.regione.volpi;
        tot_scoiattoli := tot_scoiattoli + lista_regioni^.regione.scoiattoli
      end;
      lista_regioni := lista_regioni^.next
    end
  end; { SommaNumTaneArea }


{ procedura che risolve il punto 2 }

  procedure RegioniConTaneAnimale (lista_regioni : TipoListaRegioni;
                                   animale       : char;
                                   var lista_sol : TipoListaRegioni);
  { Restituisce in lista_sol la lista delle regioni in lista_regioni che
    contengono un numero di tane dell'animale specificato magiore di 0. }
  var
    paux     : TipoListaRegioni;
    num_tane : 0..MAXINT;

  begin { RegioniConTaneAnimale }
    lista_sol := NIL;
    while lista_regioni <> NIL do
    begin
      if animale = 'V' then
        num_tane := lista_regioni^.regione.volpi
      else
        num_tane := lista_regioni^.regione.scoiattoli;
      if num_tane > 0 then
      begin
        new(paux);
        paux^.regione := lista_regioni^.regione;
        paux^.next := lista_sol;
        lista_sol := paux
      end;
      lista_regioni := lista_regioni^.next
    end
  end; { RegioniConTaneAnimale }


{ procedure ausialiarie usate dal programma driver }

  procedure LeggiListaRegioni (nomefile : string; var lista: TipoListaRegioni);
  { Legge dal file di testo nomefile le informazioni riguardo al numero di tane
    nelle regioni del bosco.
    Assume che il file termini con l'ultima cifra del numero di tane di
    scoiattolo nell'ultima regione del bosco che e` stata censita. }
  var
    f    : text;
    paux : TipoListaRegioni;

  begin { LeggiListaTane }
    assign(f, nomefile);
    reset(f);
    lista := NIL;
    while not eof(f) do
    begin                { esegue l'inserimento in testa di un nuovo elemento }
      new(paux);
      with paux^.regione do      { lettura delle informazioni per una regione }
        readln(f, coordinate.x, coordinate.y, volpi, scoiattoli);
      paux^.next := lista;
      lista := paux
    end;
    close(f)
  end; { LeggiListaRegioni }


  procedure StampaListaRegioni (lista: TipoListaRegioni);
  { Stampa su video le informazioni riguardo al numero di tane in lista. }
  begin { StampaListaTane }
    writeln('X':4, 'Y':4, 'volpi':7, 'scoiattoli':12);
    while lista <> NIL do
    begin
      with lista^.regione do
        writeln(coordinate.x:4, coordinate.y:4, volpi:7, scoiattoli:12);
      lista := lista^.next
    end
  end; { StampaListaregioni }


{ variabili usate nel programma principale }
var
  regioni, volpi_o_scoiattoli : TipoListaRegioni;
  nomefile : string;         { nome del file contenente le informazioni sulle
                               regioni censite del bosco }
  punto1, punto2 : TipoCoordinate;        { coordinate dei due punti che
                                            identificano un'area di bosco }
  num_volpi, num_scoiattoli : integer;    { numero totale di tane di volpi e di
                                            scoiattoli nell'area di bosco }
  scelta : char;       { carattere usato per scegliere tra volpi e scoiattoli }


begin { Bosco }

  { Lettura delle informazioni sul numero di tane da file. }
  writeln('Immetti il nome del file dal quale leggere le informazioni sulle regioni!');
  writeln('(N.B. Il file deve gia'' esitere)');
  readln(nomefile);
  LeggiListaRegioni(nomefile, regioni);          { lettura da file }
  StampaListaregioni(regioni);                   { stampa di conferma }


  { Lettura delle coordinate dei punti che identificano una regione. }
  writeln('Immettere le coordinate del punto in alto a sinistra della regione!');
  writeln('(prima coordinata tra 0 e ', MaxCoordX,
          ' e seconda coordinata tra 0 e ', MaxCoordY, ')');
  readln(punto1.x, punto1.y);

  writeln('Immettere le coordinate del punto in basso a destra della regione!');
  writeln('(prima coordinata tra 0 e ', MaxCoordX,
          ' e seconda coordinata tra 0 e ', MaxCoordY, ')');
  readln(punto2.x, punto2.y);

  { Attivazione della procedura che risolve il punto 1,
    - prendendo in ingresso la lista regioni e le due coppie di coordinate in
      punto1 e punto2 che identificano un'area di bosco e
    - restituendo il risultato nelle variabili num_volpi e num_scoiattoli }

  SommaNumTaneArea(regioni, punto1, punto2, num_volpi, num_scoiattoli);

  { stampa del risultato dell'attivazione della procedura o funzione 1 }
  writeln;
  writeln('Nella regione (', punto1.x, ',', punto1.y, ') - (', punto2.x, ',',
          punto2.y, ') ci sono ', num_volpi, ' volpi e ', num_scoiattoli,
          ' scoiattoli');

  writeln;
  writeln('Costruzione della lista di regioni con tane di volpi o di scoiattoli?');
  write('Digitare ''V'' per volpi e ''S'' per scoiattoli! ');
  readln(scelta);

  { Attivazione della procedura che risolve il punto 2,
    - prendendo in ingresso la lista tane e il carattere scelta e
    - restituendo il risultato nella variabile volpi_o_scoiattoli }

  RegioniConTaneAnimale(regioni, scelta, volpi_o_scoiattoli);

  { stampa del risultato dell'attivazione della procedura o funzione 2 }
  writeln;
  if scelta = 'V' then
    writeln('Regioni con volpi:')
  else
    writeln('Regioni con scoiattoli:');
  StampaListaRegioni(volpi_o_scoiattoli)

end. { Bosco }