Lezione del 16 Febbraio 2001 (Esercizi: quelli delle lezioni precedenti)

La "insert" e altri due esercizi


procedure insert(var l:list; e:elemtype; i:integer);

{AF: inserisce l'elemento 'e' in 'l' alla posizione i-esima}

 var p,t:list;
     j:integer;

 begin
  if (0>=i) OR (i>length(l)+1) then writeln('errore...')
  else
   begin
    if i=1 then   {inserzione in testa!!!}
     begin
      new(p);     {(1)}
      p^.elem:=e;
      p^.next:=l;
      l:=p;   {da (1) a qui e` in pratica una 'cons(e,l)'}
     end
    else
     begin
      j:=1; t:=l;
      while i-1>j do
       begin
        t:=t^.next;
        j:=j+1;
       end;
      new(p);
      p^.elem:=e;
      p^.next:=t^.next;
      t^.next:=p
     end
   end
 end;




procedure delete_el_ric(var l:list; p:list; e:elemtype);

{AF: elimina la prima occorrenza di 'e' in 'l', vers. ricorsiva}

{VISTA IL 9/2/2001}

 begin
  if l<>nil
  then begin
   if l^.elem=e then
    if p=l then l:=l^.next
    else p^.next:=l^.next
   else delete_el_ric(l^.next, l, e)
  end
 end;


procedure delete_el_ric2(var l:list; p:list; e:elemtype);

{AF: cancella TUTTE le occorrenze di 'e' in 'l', versione ricorsiva}

{VISTA DURANTE LA LEZIONE DI OGGI}

 begin
  if l<>nil
  then begin 
   if l^.elem=e then
    if p=l then begin l:=l^.next; delete_el_ric2(l, l, e) end
    else begin p^.next:=l^.next; delete_el_ric2(p^.next, p, e) end
   else delete_el_ric2(l^.next, l, e)
  end
 end;


Una proposta di soluzione (senza controlli sugli errori, per cui da completare, se volete) per l'esercizio:



(19/1/2001) - Date le dichiarazioni di record e array
type famiglia = record
          nomepadre,nome: char
          end;

max=100;
type arrfam = array [1..max] of famiglia;
scrivere una procedura (o funzione, scegliete voi la piu' adatta) ricorsiva che, dato un parametro 'nm' di tipo carattere rappresentante un nome, e un intero 'a', ritrovi l'a-esimo antenato di 'nm' (con la convenzione che a=1 richiede di trovare il padre di 'nm', a=2 il nonno, etc). Ad esempio, se nell'array abbiamo |c.p|b.c|k.b|f.g|, e nm=p e a=2, l'output deve essere 'b' (ovvero il padre del padre di p). Ovviamente questa procedura/funzione dovra` essere opportunamente inserita in una unit che permetta anche l'inserimento e la stampa dell'array. Inoltre, cercate di prevedere tutti i possibili casi in cui la procedura/funzione potrebbe dare errore, e trattate questi casi di conseguenza.

function trovanome(cnome:char):integer

 var i:integer;

 {ASSUMIAMO che l'array 'par' di tipo 'arrfam' e la sua
  dimensione 'n' siano GLOBALI.  Quello che interessa QUI e` 
  capire come sviluppare il punto centrale del problema.  
  Le eventuali migliorie rispetto a buone regole di programmazione, 
  efficienza, etc, possono essere realizzate dopo...}

 begin
  for i:= 1 to n do
   if (par[i].nome=cnome) then trovanome:=i;
 end;


function antenato(c:char; a:integer; cont:integer):char
  
 var pos:integer;

 {ASSUMIAMO che l'array 'par' di tipo 'arrfam' e la sua
  dimensione 'n' siano GLOBALI.  Quello che interessa QUI e` 
  capire come sviluppare il punto centrale del problema.  
  Le eventuali migliorie rispetto a buone regole di programmazione, 
  efficienza, etc, possono essere realizzate dopo...}

  begin
   pos:=trovanome(c);
   if (cont=a) then antenato:=par[pos].nomepadre
   else antenato:=antenato(par[pos].nomepadre, a, cont+1)
  end;

...

begin {main}
...
{l'array 'par' di tipo 'arrfam' viene opportunamente riempito}
...
{siano 'cnome' e 'ant' inizializzate con un carattere e un numero:}

anten:=antenato(cnome, ant, 1);

{'anten', che va` dichiarato come carattere, conterra` l'antenato numero 'ant'
 di 'cnome'.  Naturalmente, modulo eventuali errori che possono accadere, ad
 esempio se l'array 'par' non contenesse la catena ereditaria completa 
 richiesta, o, come caso particolare del problema precedente, se 'cnome' 
 non appartenesse a 'par', etc, etc.  Ripeto, pensate voi a completare 
 opportunamente l'esercizio.}
...
end.