PAC 2 de l'assignatura de Programació del Grau Multimèdia de la UOC. Per a descarregar els arxius en PHP, visita la meva wiki: http://raco-vermell.wikispaces.com/PROGRAMACI%C3%93
1. Estudis d’Informàtica, Multimèdia i Telecomunicació
Programació
PAC2 — Segona Prova d'Avaluació Continuada
SOLUCIÓ
Indicacions generals:
Raoneu i justifiqueu totes les respostes.
Les respostes incorrectes no disminueixen la nota.
Per a dubtes i aclariments sobre l’enunciat, adreceu-vos al consultor responsable de l’aula.
Lliurament:
1. S'ha de respondre les preguntes al mateix document de l'enunciat que rebrà el nom
CognomsNomP_PAC2.doc (o CognomsNomP_PAC2.odt)
2. La codificació de la pregunta 7 es lliurarà mitjançant el fitxer PAC2_Exer07.php que es
construirà sobre las plantilla adjunta. És especialment important respectar el nom
d'aquesta arxiu php.
3. Els dos fitxers es comprimiran en un únic arxiu de format zip o rar de nom
CognomsNomP_PAC2.zip (o CognomsNomP_PAC2.rar) que es lliurarà a la bústia de
"Lliurament i registre d'AC"
4. Data límit per lliurar la solució: dilluns, 7 de novembre de 2011 (a les 23:59 hores).
És imprescindible respectar el format i data d’entrega. La no adequació a aquestes
especificacions pot suposar la no avaluació de la PAC.
1
2. Exercici 1: Declaració d’accions i funcions [10%]
Objectius: Distingir entre accions i funcions. Declarar accions i funcions per a resoldre un
problema. Definir els paràmetres, amb els tipus de dades corresponents i els modificadors
d’entrada i sortida correctes.
Materials: M1 i M2
Tasca: Per a cada apartat, decidiu si és millor una acció o una funció i definiu-ne la
capçalera (només es demana la capçalera, no cal que dissenyeu cap algorisme).
Es demana la capçalera d'un mòdul (acció o funció) que:
a) Donades la productivitat horària d’una persona (amb decimals) del mes actual i del
mes anterior retorni si la del mes actual s’ha incrementat o no respecte a la del mes
anterior.
funcio productivity (prodLastMonth: real, prodCurrentMonth: real): boolea
b) Donades les despeses realizades en programari fins el moment, el preu d’una nova
llicència i el número total de llicències que es compren ara, actualitzi l’import total
de la compra de programes acumulant l’import d’aquestes noves llicències.
accio updateCost(entsor totalCost: real, ent licensePrice:real,
ent numLicenses: enter)
c) Donada una població de gats, llegeixi del canal d’entrada estàndard les
característiques d’aquests gats i retorni el número de gats de la població que són
de color negre.
funcio numCats(): enter
d) Donat l’import d’un préstec, el percentatge de finançament i el número de mesos
finançat, retorni l’import mensual a pagar.
funcio mortgage (loan: real, interestRate: real, numMonths: enter): real
2
3. Exercici 2: Especificació d’accions i funcions [10%]
Objectius: Descriure de manera precisa què fa una funció o una acció sense necessitat de
saber com ho fa.
Materials: M1 i M2
Tasca: Especifiqueu les funcions i/o accions dels apartats a i b de l’exercici 1. Cal
que indiqueu la precondició, la postcondició i, si es tracta d’una funció, què retorna.
a)
{pre: prodLastMonth = PRODLASTMONT i PRODLASTMONT ≥ 0 i
prodCurrentMonth = PRODCURRENTMONTH i
PRODCURRENTMONTH ≥ 0}
funcio productivity (prodLastMonth: real, prodCurrentMont: real): boolea
{post: produtivity = (PRODLASTMONTH < PRODCURRENTMONTH) }
b)
{pre: totalCost = TOTALCOST i TOTALCOST ≥ 0 i
licensePrice = LICENSEPRICE i LICENSEPRICE ≥ 0 i
numLicenses = NUMLICENSES i NUMLICENSES ≥ 0 }
accio updateCost(entsor totalCost: real, ent licensePrice:real, ent numLicenses: enter)
{post: totalCost = TOTALCOST + LICENSEPRICE * NUMLICENSES}
3
4. Exercici 3: Modificadors d’entrada i sortida [10%]
Objectius: Saber detectar la correctesa en la crida a accions o funcions, entenent el
funcionament dels modificadors d’entrada i sortida dels paràmetres.
Materials: M1 i M2
Tasca: Donats l’algorisme i les capçaleres de les següents accions i funcions:
funcio function1( x: enter, y: enter) : enter;
funcio function2( x: enter, c: caracter) : boolea;
accio action1( ent x: enter, ent y: real, entsor b: boolea, entsor z: enter) ;
accio action2( ent c: caracter, sor x: enter, entsor y: enter);
algorisme algorithm
var
x, y: enter;
c : real;
d : caracter;
b: boolea;
fvar
x := 5;
y := 10;
c := 0.0;
d := readChar();
b := fals;
...
writeInteger (x + y);
writeRea l(c / 2.0);
writeChar (d);
b := (x + y) = (c / 2.0);
si (b) llavors
writeChar(‘S’);
sino
writeChar(‘N’);
fsi
falgorisme
4
5. Responeu a cada apartat si és correcte o no substituir el requadre gris de
l’algorisme algorithm per la instrucció que es dóna i, si no ho és, indiqueu-ne les
causes.
a) action2 (d, x, realToInt(c) );
Incorrecte. El tercer paràmetre de l’acció action2 és d’entrada i sortida i per
tant el paràmetre actual no pot ser una expressió. Caldria que fos una
variable de tipus enter.
b) action1 (function1(x, y), readChar(), function2(x, d), x);
Incorrecte. El segon paràmetre formal de l’acció action1 és de tipus real i
en canvi es passa una expressió de tipus caràcter. A més, el tercer
paràmetre formal de l’acció action1 és d’entrada sortida i per tant el
paràmetre actual hauria de ser una variable i no una expressió.
c) x := function1 (function1(x, y), y);
Correcte
d) b := function2 (action1 (x, c, b, x), d);
Incorrecte. El primer paràmetre actual no és una expressió ja que una
acció no retorna cap valor
5
6. Exercici 4: Disseny d’algorismes [15%]
Objectius: Entendre un algorisme i saber fer crides a accions i funcions.
Materials: M1 i M2
Tasca: Disposem d’un algorisme que ens retorna informació del resultat d’una
cursa. Llegeix del canal d’entrada estàndard el dni d’un conductor (numèric, sense
lletra) i un identificador de cursa, també numèric, i:
• Si es tracta d’una cursa de cotxes escriu al canal de sortida estàndard:
o ‘W’ si el conductor indicat ha guanyat la cursa, i ha igualat o superat
la velocitat mitja obtinguda en la resta de carreres, i si aquesta és la
carrera en que ha fet menys parades,
o i ‘L’ en la resta de casos.
• En cas de no ser una cursa de cotxes escriu ‘N’.
Ompliu les caixes, amb una única instrucció o expressió a cada una, per
aconseguir el comportament que us hem descrit. L’algorisme resultant ha d’utilitzar
obligatòriament les següents accions i funcions, que no heu d’implementar:
Acció que llegeix del canal d’entrada estàndard la informació del conductor i cursa:
accio getInfo (sor dni: enter, sor idRace: enter);
Acció que donats el dni d’un conductor i l’identificador de cursa retorna si aquest ha guanyat
la cursa, la velocitat mitja que ha portat a la cursa i el número d’aturades que ha fet:
accio getInfoRunnerRace (ent dni: enter, ent idRace: enter,
sor won: boolea, sor averageSpeed: real, sor numberStops: enter);
Acció que donat el dni d’un conductor retorna la velocitat mitja que ha portat a les curses
que ha fet, i el número mínim d’aturades que ha fet fins al moment en totes les seves
curses:
accio getInfoRaces ( ent dni: enter, sor averageSpeed: real, sor numberStops: enter);
Acció que donat un identificador de cursa retorna cert si és una cursa de cotxes i fals en cas
contrari:
funcio isCarRace (idRace: enter) : boolea;
6
7. algorisme RaceInfo
const
WIN : caracter = ‘W’;
LOSE : caracter = ‘L’;
NOCAR : caracter = ‘N’;
fconst
var
dni, idRace: enter;
bCarRace, wonRace: boolea;
averageSpeedRace, averageSpeed: real;
numberStopsRace, numberStopsMin: enter;
fvar
{Llegeix del canal d’entrada estàndard la informació del conductor i de la cursa
que hem de tractar}
getInfo (dni, idRace); ;
+
bCarRace := isCarRace(idRace) ;
si bCarRace llavors
{Obtenim la informació associada al conductor / cursa llegida del canal
estàndard}
getInfoRunnerRace(dni, idRace, wonRace, ;
averageSpeedRace, numberStopsRace)
{Obtenim la informació genèrica del conductor en totes les seves curses}
getInfoRaces(dni, averageSpeed, numberStopsMin) ;
{Decidim quin caràcter s'ha d'escriure}
si (wonRace) i (averageSpeedRace ≥ averageSpeed) i llavors
(numberStopsRace < numberStopsMin)
writeChar(WIN);
sino
writeChar(LOSE);
fsi
sino
writeChar(NOCAR);
fsi
falgorisme
7
8. Exercici 5: Disseny d’algorismes [15%]
Objectius: Dissenyar una funció/acció.
Materials: M1 i M2
Tasca: Es demana un mòdul (acció o funció) que determini el pagament a realitzar
per les entrades a un espectacle amb les següents condicions: només es poden
comprar fins a quatre entrades i, si es compra més d'una entrada, hi ha descompte:
al cost de dues entrades es descompta el 10%, al de tres entrades el 15%, i a la
compra de quatre entrades el 20%.
El mòdul ha de rebre com a paràmetres el número total d’entrades comprades i el
preu d’una entrada, i ha de retornar per una banda si el número total d’entrades
demanades està dintre dels límits, i per altra banda l’import total de les entrades
(retornarà import 0 en cas d’haver-ne demanat més entrades de les permeses).
accio computeTotalCost(ent ticketPrice: real, ent numTickets: enter, sor
numTicketsOK: boolea, sor totalCost: real)
const
NO_DISCOUNT: real = 0.0;
TWO_TICKETS_DISCOUNT: real = 0.10;
THREE_TICKETS_DISCOUNT: real = 0.15;
FOUR_TICKETS_DISCOUNT: real = 0.20;
fconst
var
discount: real;
fvar
si (numTikets < 1 o numTickets > 4) llavors
numTicketsOK:= fals;
totalCost:= 0;
sino
numTicketsOK:= cert;
si numTickets = 1 llavors
discount:= NO_DISCOUNT;
sino si numTickets = 2 llavors
discount:= TWO_TICKETS_DISCOUNT;
sino si numTickets = 3 llavors
discount:=THREE_TICKETS_DISCOUNT;
sino discount:= FOUR_TICKETS_DISCOUNT;
fsi
fsi
fsi
totalCost := intToReal(numTickets) * (ticketPrice);
totalCost:= totalCost – totalCost * discount;
fsi
faccio
8
9. Exercici 6: Seguiment de l’execució [15%]
Objectius: Fer el seguiment, pas a pas, de l’execució d’una funció. Mantenir una taula amb
els valors que van prenent els objectes a mida que avança l’execució.
Materials: M1 i M2
Tasca: Disposem d'un algorisme capaç de calcular els dies transcorreguts entre dues
dates a partir de la vigència del calendari gregorià (aprox. 1583). Aquest algorisme té en
compte el patró de distribució dels anys de traspàs.
L’algorisme és:
algorisme daysBetwen
var
day1, month1, year1, day2, month2, year2 : enter;
counter1, counter2: enter;
fvar
getData(day1, month1, year1);
getData(day2, month2, year2);
si wrongData (day1, month1, year1, day2, mont2, year2) llavors
writeCharacter ('E');
sino
counter1 := daysAfter1583(year1, month1, day1);
counter2 := daysAfter1583(year2, month2, day2);
writeInteger (counter2-counter1);
fsi
falgorisme
accio getData (sort day: enter, sort month:enter, sort year: enter)
day := readInteger();
month := readInteger();
year := readInteger();
faccio
funcio wrongData (day1:enter, month1:enter, years1:enter, day2:enter, mont2:enter,
year2:enter): boolea
var
wrong: boolea;
fvar
wrong:= false;
si (year2<year1) llavors
wrong:= true;
sino si ((year2=year1) i (month2<mont1)) llavors
wrong:= true;
sino si ((year2=year1) i (month2=mont1) i (day2<day1)) llavors
wrong:= true;
fsi
fsi
fsi
retorna (wrong);
ffuncio
9
10. funcio isLeapYear (year: enter): boolea
var
leap: boolea;
fvar
si (year mod 400 = 0) llavors
leap := true;
sino si (year mod 100 = 0 ) llavors
leap := false;
sino si (year mod 4 = 0 ) llavors
leap := true;
sino
leap := false;
fsi
fsi
fsi
retorna (leap);
ffuncio
funcio dayOfTheYear(year: enter, month:enter, day:enter): enter
var
daysCounter: enter;
fvar
daysCounter := day;
si (month >11) llavors
daysCounter := daysCounter + 30;
fsi
si (month >10) llavors
daysCounter := daysCounter + 31;
fsi
si (month >9) llavors
daysCounter := daysCounter + 30;
fsi
si (month >8) llavors
daysCounter := daysCounter + 31;
fsi
si (month >7) llavors
daysCounter := daysCounter + 31;
fsi
si (month >6) llavors
daysCounter := daysCounter + 30;
fsi
si (month >5) llavors
daysCounter := daysCounter + 31;
fsi
si (month >4) llavors
daysCounter := daysCounter + 30;
fsi
si (month >3) llavors
daysCounter := daysCounter + 31;
fsi
si (month >2) llavors
daysCounter := daysCounter + 28;
fsi
si (month >1) llavors
daysCounter := daysCounter + 31;
fsi
si (isLeapYear(year) i month > 2) llavors
daysCounter := daysCounter + 1;
fsi
retorna (daysCounter);
ffuncio
10
11. funcio daysYearsAfter1583 (year:enter) : enter
var
daysCounter: enter;
currentYear: enter;
leap: boolean;
fvar
daysCounter := 0;
currentYear := 1583;
mentre (currentYear < year)fer
daysCounter := daysCounter + 365;
leap := isLeapYear(currentYear)
si (leap) llavors
daysCounter := daysCounter +1;
fsi
currentYear := currentYear + 1;
fmentre
retorna (daysCounter);
ffuncio
funcio daysAfter1583(year: enter, month:enter, day:enter): enter
retorna (daysYearsAfter1583 (year) + dayOfTheYear(year, month, day));
ffuncio
a) Ompliu la taula amb tots els valors que van prenent en la function
daysYearsAfter1583 els objectes si el valor rebut com paràmetre és 1586 (empreu
una línia de la taula per cada canvi de valor d'una de les variables; hi ha més fileres
que les necessàries).
currentYear daysCounter
1583 (2) 0 (1) En negreta els valors que
1584 (4) 365 (3) prenen les variables.
730 (5)
1585 (7) 731 (6) Entre parèntesi l'ordre amb què
1586 (9) 1096 (8) van prenent nous valors les
variables
b) Ompliu la taula amb els valors de la variable daysCounter en la function
dayOfTheYear si els paràmetres de la crida són (1956, 3, 13).
(Hi ha més caselles que les necessàries).
13 41 72 73
c) Suposant que la seqüència d’entrada és < 15 12 2000 15 12 2000>, què s’escriurà
a la sortida estàndard?
S’escriurà la xifra 0
11
12. Exercici 7: Programació [15%]
Objectius: Codificar un algorisme en llenguatge PHP. Fer proves per a veure si el
funcionament és correcte.
Materials: Guia bàsica de PHP i miniguies.
Tasca: Codifiqueu en llenguatge PHP i proveu l’ algorisme de l’exercici 6.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//ES"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="ES" dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>PAC2_Exer7</title>
</head>
<body>
<h3>PAC2_Exer7</h3>
<h3>***** NOM DE L'ESTUDIANT ******</h3> <!-- No oblideu posar el nom -->
<div>
<?php
/* Llegeix de la crida la variable cadena: que conté
sis números enters del tipus D1 M1 A1 D2 M2 A2 i
que construeixen dues dates:
data1 : D1/M1/A1
data2 : D2/M2/A2
ambdues dates són posteriors al 12/12/1582.
Si data2 >= data1 escriura els dies entre ambdues dates
Si data2 < data1 escriura el missatge d'error
exercici 7 - PAC2 - setembre-2011 gener 2012
autor:
*/
/****************** FUNCTIONS ********************/
function getData(&$day, &$month, &$year, &$numeros)
{
$day = array_shift($numeros);
$month = array_shift($numeros);
$year = array_shift($numeros);
}// de getData
function wrongData($day1, $month1, $year1, $day2, $month2, $year2)
{
$wrong = false;
if ($year2<$year1) $wrong = true;
else if (($year2==$year1) && ($mont2<$mont1)) $wrong = true;
else if (($year2==$year1) && ($mont2==$mont1) && ($day2<$day1))
$wrong = true;
return $wrong;
}//de wrongData
function isLeapYear ($year)
{
if ($year % 400 == 0) $leap = true;
else if ($year % 100 == 0) $leap = false;
else if ($year % 4 == 0) $leap = true;
else $leap = false;
return $leap;
}// de isLeapYear
12
13. function dayOfTheYear ($day, $month, $year)
{
$daysCounter = $day;
if ($month>11) $daysCounter+=30;
if ($month>10) $daysCounter+=31;
if ($month>9) $daysCounter+=30;
if ($month>8) $daysCounter+=31;
if ($month>7) $daysCounter+=31;
if ($month>6) $daysCounter+=30;
if ($month>5) $daysCounter+=31;
if ($month>4) $daysCounter+=30;
if ($month>3) $daysCounter+=31;
if ($month>2) $daysCounter+=28;
if ($month>1) $daysCounter+=31;
if (isLeapYear($year) && ($month>2)) $daysCounter++;
return $daysCounter;
}// de dayOfTheYear
function daysYearsAfter1583($year)
{
$daysCounter = 0;
$currentYear = 1583;
while ($currentYear<$year)
{
$daysCounter += 365;
if (isLeapYear($currentYear)) $daysCounter++;
$currentYear++;
}
return $daysCounter;
}// de daysYearsAfter1583
function daysAfter1583($year, $month, $day)
{
return (daysYearsAfter1583($year) + dayOfTheYear($day, $month, $year));
}
/************* MAIN PROGRAM ****************/
$cadena = $_GET["cadena"];
$numeros = explode(" ", $cadena);
getData($day1, $month1, $year1, $numeros);
getData($day2, $month2, $year2, $numeros);
if (wrongData($day1, $month1, $year1, $day2, $month2, $year2))
print "<strong>E</strong>. La segona data no pot ser anterior a la primera
<br />";
else
{
$counter1 = daysAfter1583($year1, $month1, $day1);
$counter2 = daysAfter1583($year2, $month2, $day2);
print "Entre $day1/$month1/$year1 i $day2/$month2/$year2 hi ha ".($counter2-
$counter1)." dies <br />";
}
?>
</div>
</body>
</html>
13
14. Exercici 8: Codificació [10%]
Objectius: Comprensió d’algorismes en PHP.
Materials: Guia bàsica de PHP i miniguies.
Tasca 1: El model de calendari gregorià, va substituir el calendari julià que considerava
anys de traspàs tots els múltiples de 4. Creeu una function isLeapYearJulian equivalent a
isLeapYear, però seguint les normes del calendari julià:
function isLeapYearJulian ($year)
{
return ($year % 4 == 0)
}// de isLeapYearJulian
Tasca 2: L'any 1582, quan es va aplicar el calendari gregorià, es va haver de fer un
reajustament del calendari de manera que el dia posterior al 5 d'octubre va ser el 15
d'octubre (els dies 6 al 14 no van existir). Modifiqueu la function dayOfTheYear per tal que
fos vàlida també per l'any 1582
La function continua essent vàlida però per al cas especial de 1582 i per dates posteriors al
14 d'octubre s'haurà de restar 9 $daysCounter
function dayOfTheYear ($day, $month, $year)
{
$daysCounter = $day;
if ($month>11) $daysCounter+=30;
if ($month>10) $daysCounter+=31;
if ($month>9) $daysCounter+=30;
if ($month>8) $daysCounter+=31;
if ($month>7) $daysCounter+=31;
if ($month>6) $daysCounter+=30;
if ($month>5) $daysCounter+=31;
if ($month>4) $daysCounter+=30;
if ($month>3) $daysCounter+=31;
if ($month>2) $daysCounter+=28;
if ($month>1) $daysCounter+=31;
if (isLeapYear($year) && ($month>2)) $daysCounter++;
if ($year==1582)
if (($month>10) || (($month==10)&&($day>14))) $daysCounter-=9;
return $daysCounter;
}// de dayOfTheYear
Tasca 3: Sabem que el dia 1 de gener de 1583 (primer any complet amb vigència del
calendari gregorià) va ser dissabte.
Creeu la function weekDay en PHP que rebi en un paràmetre la quantitat de dies passats
des de 1-1-1583 fins una data determinada i escrigui el dia de la setmana de què es tracta
aquesta data.
Determinar el dia de la setmana a què correspon una xifra és una cosa simple i es
fonamenta en el càlcul del mòdul 7 de la xifra, de manera que si el resultat és 1 el dia de la
setmana és el mateix que el 1-1-1583, si és 2 equivaldrà al 2-1-1583, etc.
El codi podria ser:
14
15. function weekDay ($amountDays)
{
$day = ($amountDays)%7;
switch ($day)
{
case 0: $missage=" divendres";
case 1: $missage=" dissabte";
case 2: $missage=" diumenge";
case 3: $missage=" dilluns";
case 4: $missage=" dimarts";
case 5: $missage=" dimecres";
case 6: $missage=" dijous";
}
print "El dia de la setmana era $missage";
}
També podria fer-se amb if/else i el codi podria ser:
function weekDay ($amountDays)
{
$day = ($amountDays)%7;
if ($day== 0) $missage=" divendres";
else if ($day== 1) $missage=" dissabte";
else if ($day== 2) $missage=" diumenge";
else if ($day== 3) $missage=" dilluns";
else if ($day== 4) $missage=" dimarts";
else if ($day== 5) $missage=" dimecres";
else $missage=" dijous";
print "El dia de la setmana era $missage";
}
15