TENTAMEN Programmering Grundkurs (HI1900) Skrivtid 13:15-18:15 Tisdagen 26 april 2011 Tentamen består av 8 sidor Hjälpmedel Förutom dator med installerad Code::Blocks, Utforskaren, Acrobat reader och Notepad (inga andra program), den kurslitteratur som använts under kursen, samt egna anteckningar, programlistningar och böcker. Dock inga egna disketter, CD-ROM eller USB-minne. Under W:\PROV\C finns program- och datafiler som kan komma till användning vid lösandet av uppgifterna. Kopiera över dessa till ditt konto. Till alla uppgifter ska ett program levereras i form av källkod (C eller CPP-fil). Dina bidrag lägger du i en katalog i roten på H:. Katalogen ska ha samma namn som prefixet i din mailadress. Exempelvis för Kalle Kula: HDI02KEKA. Namnen på lösningarna ska ges UPPG1.C till UPPG8.C. De är endast dessa filer som kommer att bedömas. Inled varje program med ditt namn på en kommentarrad. Rättningen görs genom att programmen körs ett antal gånger för olika indata. Om resultatet överensstämmer med det förväntade bedöms programmet som korrekt och ger 2 poäng. Om ett program ej kan kompileras utan fel, är det knappast troligt att det kommer att ge några poäng. I det fall där programmet läser från och eller skriver till en fil, testas programmet oftast med en annan fil än den bifogade. Betygsgränser (HI1900): Poäng 14-16 12-13 10-11 8-9 7 6 Betyg A B C D E Fx Resultatet anslås på kursens hemsida ingforum.haninge.kth.se/c i kodat skick och i Bilda Lycka till! Håkan Strömberg Strömberg 1 KTH STH
Uppgift 1. Den saknade punkten Adam är på jakt efter koordinaterna till en rektangel placerad i ett vanligt koordinatsystem, med sidorna parallella med axlarna. Tyvärr har han bara tre punkter. Skriv ett program som tar emot koordinaterna till de tre punkterna, som Adam har, och som bestämmer den fjärde. Alla koordinater är heltal. Lösning: Punkt 1 x? 30 Punkt 1 y? 20 Punkt 2 x? 10 Punkt 2 y? 10 Punkt 3 x? 10 Punkt 3 y? 20 Punkt 4 x: 30 Punkt 4 y: 10 2 int main(void){ 3 int x1,y1,x2,y2,x3,y3,x4,y4; 4 printf("punkt 1 x? "); scanf("%d",&x1); 5 printf("punkt 1 y? "); scanf("%d",&y1); 6 printf("punkt 2 x? "); scanf("%d",&x2); 7 printf("punkt 2 y? "); scanf("%d",&y2); 8 printf("punkt 3 x? "); scanf("%d",&x3); 9 printf("punkt 3 y? "); scanf("%d",&y3); 10 if(x1==x2) printf("x: %d\n",x3); 11 if(x1==x3) printf("x: %d\n",x2); 12 if(x2==x3) printf("x: %d\n",x1); 13 if(y1==y2) printf("y: %d\n",y3); 14 if(y1==y3) printf("y: %d\n",y2); 15 if(y2==y3) printf("y: %d\n",y1); 16 } Strömberg 2 KTH STH
Uppgift 2. Åldersfixering Adam, Bertil och Curt är alla olika gamla, mellan 10 och 99 år. När man adderar Adams och Bertils ålder och vänder på siffrorna i den summan får man Curts ålder. När man adderar Adams och Curts ålder och vänder på siffrorna i den summan får man Bertils ålder. När man adderar Bertils och Curts ålder och vänder på siffrorna i den summan får man Adams ålder. Skriv ett program som listar de tre åldrarna för samtliga, möjliga lösningar. Lösning: 2 int main(void){ 3 int adam,bertil,curt; 4 int a1,a2,b1,b2,c1,c2; 5 for(adam=10;adam<=97;adam++) 6 for(bertil=adam+1;bertil<=98;bertil++) 7 for(curt=bertil+1;curt<=99;curt++){ 8 a1=adam/10; a2=adam%10; 9 b1=bertil/10; b2=bertil%10; 10 c1=curt/10;c2=curt%10; 11 if(adam+bertil==10*c2+c1 && 12 adam+curt==10*b2+b1 && 13 bertil+curt==10*a2+a1) 14 printf("%d %d %d\n",adam,bertil,curt); 15 } 16 } Strömberg 3 KTH STH
Figur 1: Från vänster: Påse, Sax, Sten Uppgift 3. Sten Sax Påse Adam, Bertil och Curt spelar Sten, Sax. Påse. Ett enkelt spel, för två spelare, där spelarna bakom ryggen, med höger hand, väljer en av de tre tecknen i figur 1. På en given signal visar man så samtidigt upp sina händer. Sten vinner över Sax och ger 1 poäng. Sax vinner över Påse och ger 1 poäng. Påse vinner över Sten och ger 1 poäng. Om båda spelarna visar upp samma tecken, är spelet oavgjort, som inte ger någon poäng Skriv ett program som genomför tre matcher, i tur och ordning: Adam-Bertil, Adam-Curt och Bertil-Curt. På filen stensaxpase.txt finns uppgifter om vad spelarna tänkt visa för tecken. Filen inleds ett tal n < 100 som anger hur många spel som ingår i en match. Därefter följer 6 rader med n tecken i varje. Följande tecken används S betyder Sax P betyder Påse R betyder Sten Den första raden innehåller de tecken Adam tänker visa i matchen mot Bertil. Den andra raden innehåller de tecken Bertil tänker visa i samma match och så vidare enligt spelschemat ovan Programmet ska presentera en tabell med hur många poäng de tre spelarna fått totalt under sina matcher. Ett körningsexempel: Adam 21 Bertil 32 Curt 16 Strömberg 4 KTH STH
Lösning: 2 #include <string.h> 3 4 void match(char h[],char b[],int *hp,int *bp){ 5 int i; 6 *bp=0; 7 *hp=0; 8 for(i=0;i<strlen(h);i++){ 9 if(h[i]== S && b[i]== P ) (*hp)++; 10 if(h[i]== S && b[i]== R ) (*bp)++; 11 if(h[i]== P && b[i]== S ) (*bp)++; 12 if(h[i]== P && b[i]== R ) (*hp)++; 13 if(h[i]== R && b[i]== P ) (*bp)++; 14 if(h[i]== R && b[i]== S ) (*hp)++; 15 } 16 } 17 18 int main(void){ 19 FILE *fil; 20 int i,tab[3]={0},hp,bp,h,b,antal; 21 char hemma[100],borta[100]; 22 char namn[3][10]={"adam","bertil","curt"}; 23 24 fil=fopen("stensaxpase2.txt","rt"); 25 fscanf(fil,"%d",&antal); 26 for(h=0;h<2;h++) 27 for(b=h+1;b<3;b++){ 28 fscanf(fil,"%s",hemma); 29 fscanf(fil,"%s",borta); 30 match(hemma,borta,&hp,&bp); 31 tab[h]+=hp; 32 tab[b]+=bp; 33 } 34 for(i=0;i<3;i++) 35 printf("%-8s %d\n",namn[i],tab[i]); 36 fclose(fil); 37 } Strömberg 5 KTH STH
Uppgift 4. Påskdejt Adam och Britt har bestämt att träffas utanför konditori Pallas mellan klockan xx : xx och yy : yy. Om Adam kommer först till mötet tänker han vänta på Britt i z minuter och om Britt kommer först, väntar hon på Adam i u minuter. Skriv ett program som simulerar detta möte och bestämmer sannolikheten att de över huvud taget kommer att mötas. Utför simuleringen 100000 gånger och bestäm ett medelvärde. Adam och Britt anländer slumpmässigt under det angivna tidsintervallet. Två körningsexempel med olika lösningsmetoder: Från klockslag? 15.00 Till klockslag? 15.30 Adam väntar (min)? 7 Britt väntar (min)? 5 Sannolikheten att mötas är 37.3% Från klockslag? 15.00 Till klockslag? 15.30 Adam väntar (min)? 7 Britt väntar (min)? 5 Sannolikheten att mötas är 35.9% Observera att tiden ges som ett flyttal med två decimaler, där heltalet anger timmar och decimalerna minuter och att båda tiderna gäller samma dygn. Observera också att resultatet varierar beroende på om Adam och Britt endast kan anlända hela minuter, det vill säga 15.00, 15.01, 15.02,... 15.30 (det första körningsexemplet) eller om de två kan komma vilken tid helst mellan 15.00 och 15.30. Båda lösningarna godkänns (och den senare är mer matematiskt korrekt). Strömberg 6 KTH STH
Lösning: 2 #include <time.h> 3 #include <stdlib.h> 4 5 int main(void){ 6 float fran,till,bertilk,adamk; 7 int adamv,bertilv,traff=0; 8 int fran1,till1,minuter,test; 9 srand(time(0)); 10 printf("från? "); 11 scanf("%f",&fran); 12 printf("till? "); 13 scanf("%f",&till); 14 printf("adam väntar? "); 15 scanf("%d",&adamv); 16 printf("bertil väntar? "); 17 scanf("%d",&bertilv); 18 fran1=(int)(fran*100+0.5); 19 till1=(int)(till*100+0.5); 20 minuter=(60*(till1/100)+till1%100)-(60*(fran1/100)+fran1%100); 21 for(test=1;test<=100000;test++){ 22 adamk=(float)rand()/(rand_max+1)*minuter; 23 bertilk=(float)rand()/(rand_max+1)*minuter; 24 if(adamk<=bertilk && adamk+adamv>=bertilk) 25 traff++; 26 if(bertilk<adamk && bertilk+bertilv>=adamk) 27 traff++; 28 } 29 printf("sannolikheten att träffas %.1f%%\n",traff/1000.0); 30 } Strömberg 7 KTH STH
Uppgift 5. Påskäggen En grupp vänner har som tradition att ge en eller flera av sina vänner i gruppen ett påskägg på skärtorsdagen. Allt givande och mottagande kan läsas på filen paskagg.txt. Filen har följande struktur. Filen inleds med ett tal n 10, som anger hur många vänner som ingår i gruppen. Därefter följer n rader med vännernas namn ett på varje. Namnen består 12 tecken. Sedan följer n grupper av information. Varje grupp inleds med namnet på givaren På nästa rad ges enhetspriset, i kronor, på de påskägg han har givit bort. På nästa rad anges antal m n ägg givaren gav bort. Gruppen avslutas med namnen på de m mottagarna. Ett namn på varje rad. En givare betalade lika mycket för samtliga ägg han skänkte. Namnen på givare och mottagare kommer inte i någon given ordning. Skriv ett program som i en tabell, för varje person, skriver ut skillnaden i kr mellan värdet på de påskägg han givit bort och de han mottagit. Ett körningsexempel: Adam 230 Bertil -355 Curt 327 David -280 Erik -172 Filip 250 Strömberg 8 KTH STH
Lösning: 2 struct persontyp{ 3 char namn[12]; 4 int belopp; 5 }; 6 7 struct persontyp person[10]; 8 9 int main(void){ 10 FILE *fil; 11 int i,j,k,np,n,givarenr,mottagarenr,pris; 12 char givare[12],mottagare[12]; 13 14 fil=fopen("paskagg2.txt","rt"); 15 fscanf(fil,"%d",&np); 16 for(i=0;i<np;i++){ 17 fscanf(fil,"%s",person[i].namn); 18 person[i].belopp=0; 19 } 20 for(i=0;i<np;i++){ 21 fscanf(fil,"%s",givare); 22 for(j=0;j<np;j++) 23 if(strcmp(givare,person[j].namn)==0) 24 givarenr=j; 25 fscanf(fil,"%d",&pris); 26 fscanf(fil,"%d",&n); 27 for(j=0;j<n;j++){ 28 fscanf(fil,"%s",mottagare); 29 for(k=0;k<np;k++) 30 if(strcmp(mottagare,person[k].namn)==0) 31 mottagarenr=k; 32 person[givarenr].belopp-=pris; 33 person[mottagarenr].belopp+=pris; 34 } 35 } 36 for(i=0;i<np;i++) 37 printf("%-12s %4d\n",person[i].namn,person[i].belopp); 38 fclose(fil); 39 } Strömberg 9 KTH STH
Uppgift 6. Ärtburken På påskafton anordnades en gissningstävling för n 10 deltagare. Tävlingsledaren räknade i hemlighet ett antal ärtor som han lade ner i en glasburk och tillslöt med ett lock. De tävlande skulle sedan gissa hur många ärtor burken innehöll. Vinnare blev förstås den som gissade rätt eller kom närmast. Skriv ett program som från filen artor.txt läser in deltagarnas gissningar och resultaten (hur långt från det rätta antalet, gissningen hamnade) och som med denna information bestämmer det rätta antalet ärtor i burken. Filen inleds med ett tal n 10 som anger antalet deltagare. På följande n rader finns gissningarna i form av ett heltal. Därefter följer n rader med tal som anger hur långt ifrån det rätta antalet gissningarna var, givna i en godtycklig ordning i förhållande till de tidigare givna gissningarna. Det fanns 151 ärtor i burken Strömberg 10 KTH STH
Lösning: 2 #include <limits.h> 3 4 int main(void){ 5 FILE *fil; 6 int i,j,giss[10],res[10],akt[10]; 7 int gmax=0,gmin=int_max,rmax=0; 8 int artor,antal,ok,s; 9 10 fil=fopen("artor1.txt","rt"); 11 fscanf(fil,"%d",&antal); 12 13 for(i=0;i<antal;i++){ 14 fscanf(fil,"%d",&giss[i]); 15 if(giss[i]>gmax) gmax=giss[i]; 16 if(giss[i]<gmin) gmin=giss[i]; 17 } 18 19 for(i=0;i<antal;i++){ 20 fscanf(fil,"%d",&res[i]); 21 if(res[i]>rmax) rmax=res[i]; 22 } 23 fclose(fil); 24 25 for(artor=gmax-rmax;artor<=gmin+rmax;artor++){ 26 for(j=0;j<antal;j++) 27 akt[j]=0; 28 for(i=0;i<antal;i++){ 29 s=abs(giss[i]-artor); 30 for(j=0;j<antal;j++) 31 if(res[j]==s) 32 akt[j]=1; 33 } 34 ok=1; 35 for(j=0;j<antal;j++) 36 if(!akt[j]) 37 ok=0; 38 if(ok) 39 printf("antal ärtor är %d\n",artor); 40 } 41 } Strömberg 11 KTH STH
Uppgift 7. Solitär Figur 2: Solitär kallas det enmansspel som visas i figur 2. Målet med spelet är att avlägsna alla, utom en kula från brädet. En kula får flyttas (hoppa) i fyra riktningar: uppåt, nedåt, åt höger och åt vänster, om det ligger en kula intill och platsen omedelbart bakom är tom. Två möjliga drag visas i figuren. Den överhoppade kulan avlägsnas från brädet. Inga diagonala drag är tillåtna. Skriv ett program som läser in en ställning i spelet från filen solitar.txt och bestämmer hur många möjliga drag det finns i ställningen. Filen består av 7 rader med 7 tecken på varje. o (litet o) betecknar en kula.. (punkt) betecknar tom plats. (minustecken) betecknar platser som ligger utanför spelplanen. Ett körningsexempel: Det finns 11 möjliga drag Strömberg 12 KTH STH
Lösning: 2 3 int main(void){ 4 FILE *fil; 5 int brade[11][11],i,j,antal=0; 6 char str[8]; 7 8 for(i=0;i<11;i++) 9 for(j=0;j<11;j++) 10 brade[i][j]=2; 11 12 fil=fopen("solitar2.txt","rt"); 13 for(i=0;i<7;i++){ 14 fscanf(fil,"%s",str); 15 for(j=0;j<7;j++){ 16 if(str[j]== o ) brade[i+2][j+2]=1; 17 if(str[j]==. ) brade[i+2][j+2]=0; 18 } 19 } 20 fclose(fil); 21 for(i=2;i<=8;i++) 22 for(j=2;j<=8;j++) 23 if(brade[i][j]==1){ 24 if(brade[i][j+1]==1 && brade[i][j+2]==0) antal++; 25 if(brade[i][j-1]==1 && brade[i][j-2]==0) antal++; 26 if(brade[i+1][j]==1 && brade[i+2][j]==0) antal++; 27 if(brade[i-1][j]==1 && brade[i-2][j]==0) antal++; 28 } 29 printf("antal drag %d\n",antal); 30 } Strömberg 13 KTH STH
Uppgift 8. Arbetskrafttillhörighet struct grupptyp{ int akt; int kon; int cs; int barn; float tab[71]; }; Den binära filen arbetskraft.dat innehåller poster skapade med postbeskrivningen ovan och innehåller månadsvis information om arbetskrafttillhörighet från och med april 2005 till och med februari 2011 (71 månader). Uppgifterna är hämtade från SCB. Totalt är materialet indelat i 64 grupper (det finns 64 poster på filen). Genom att kombinera de olika koderna i tabellerna nedan, kan man man nå de olika grupperna. För vare grupp är givet 71 data i en tabell. Cellerna innehåller antalet individer i denna grupp i landet under en viss månad, från april 2005 räknat och framåt. Talen är givna i 1000-tals individer, med en decimal. ArbetskraftTillhörighet (akt) Kod Totalt 1 Arbetslösa 2 Ej i arbetskraften 3 Sysselsatta 4 Civilstånd (cs) Kod Gift/Sambo 1 Ensamstående 2 Kön (kon) Kod Män 1 Kvinnor 2 Barn (barn) Kod Samtliga med/utan barn 1 Med barn under 19 år 2 Därav med barn under 7 år 3 utan barn under 19 år 4 Skriv ett program som för given grupp bestämmer under vilken månad under den givna perioden gruppen har varit som störst. Arbetskrafttillhörighet? 2 Kön? 1 Civilstånd? 2 Barn? 3 Max år 2006 månad 4 med 3800 Strömberg 14 KTH STH
Lösning: 2 3 struct grupptyp{ 4 int akt; 5 int kon; 6 int cs; 7 int barn; 8 float tab[71]; 9 }; 10 int main(void){ 11 FILE *fil; 12 int i,j,akt,kon,cs,barn,maxmanad,manad,ar; 13 struct grupptyp kategori; 14 float max=0.0; 15 16 fil=fopen("arbetskraft.dat","rb"); 17 printf("arbetskrafttillhörighet? "); scanf("%d",&akt); 18 printf("kön? "); scanf("%d",&kon); 19 printf("civilstånd? "); scanf("%d",&cs); 20 printf("barn? "); scanf("%d",&barn); 21 for(i=1;i<=64;i++){ 22 fread(&kategori,sizeof(struct grupptyp),1,fil); 23 if(kategori.akt==akt && kategori.kon==kon && 24 kategori.cs==cs && kategori.barn==barn){ 25 max=0.0; 26 for(j=0;j<71;j++) 27 if (kategori.tab[j]>max){ 28 max=kategori.tab[j]; 29 maxmanad=j+1; 30 } 31 printf("\n"); 32 } 33 } 34 if(maxmanad<=9){ 35 ar=2005; manad=maxmanad+3; 36 } 37 else 38 if(maxmanad>=70){ 39 ar=2011; manad=72-maxmanad; 40 } 41 else{ 42 manad=(maxmanad-10)%12+1; 43 ar=(maxmanad-10)/12+2006; 44 } 45 printf("%.1f år %d månad %d (%d)\n",max,ar,manad,maxmanad); 46 fclose(fil); 47 } Strömberg 15 KTH STH