Informatikaren Oinarriak eman ta zabal zazu Universidad del país vasco 2008 / 2009 Ikasturtea Euskal herriko unibertsitatea Bilbo, 2009ko ekainak 10 Denbora: 2:15 'Bollullos de Ayala' futbol taldea probintziaren txapelketan finalera heldu da. Biztanleak poz­pozik daudenez, finala ikustera denek joan nahi dute, baina ez dago behar adina sarrera. Hori dela eta, herriko alkateak, arazorik ez izateko, sarrerak biztanleen artean zozketatuko ditu. Gainera, familiak eta lagun taldeak ez banatzearren, zozketa taldeka egingo da. Prozesua honako era honetan burutuko da: 1. Taldeka parte hartu ahal da zozketan. Taldean 1, 2, 3, 4 edo 5 kide egon daitezke. Baina, pertsona bakoitzak talde bakar batean eman dezake izena. 2. Zozketa egiteko, talde bakoitzari zenbaki batzuk emango zaizkio; zenbaki kopurua, kideen kopuruaren funtzioan dagoelarik. Eta taldeko zenbakiren bat sarituta suertatuz gero, taldeko partaide guztiek partidua ikusteko sarrera jasoko dute. Talde bakoitzari sari bakarra tokatu ahal zaio. Hau da, nahiz eta saritutako zenbaki bat baino gehiago eduki, partidua ikusteko sarrera bakarra emango zaio taldekide bakoitzari. Bestela esanda, sari bat lortuta, hurrengoak ez dira kontuan izango. Hori dela eta, programa informatikoa egiteko agindua eman digu alkateak zozketaren arazoak konpontzeko: taldekideen izena eman, ausazko zozketa egin, saridunen zerrenda atera, … DATUEN EGITURA: Analisia egin ondoren, gure programak erabiliko dituen datuen egiturak honako hauek izango direla erabaki dugu: • “taldeak.dat” izeneko fitxategia. Zozketan izena eman duten taldeen informazioa gordeko du honek. Talde bakoitzaren erregistroak honako informazioa edukiko du: Talde Zenbakia Integer Taldearen identifikatzailea Zenbaki korrelatiboak (1, 2,…) Taldekide kopurua Integer 1eta 5 bitarteko zenbakia Kateen arraya Taldekideen NAk Taldekideen NA* zerrenda * Nortasun Agiria Adibi dez: Taldea Perts. Kop. 1 1 11111111 2 2 22222222 12345678 3 2 12121212 12121213 4 1 22223333 5 4 33333333 Taldeko pertsonen NA 44444444 55555555 66666666 Bestalde, taldeen eta zozketaren zenbakien arteko erlazioak gordeko dituen “zozketa.dat” fitxategia dugu. Honek biltegiratzen duen informazioa oso garrantzitsua da; honen bidez, saritua izan den jakin dezake talde bakoitzak. (Saria izanez gero, informazio hau Zenbakia eremuan egongo da, non zozketaren zenbaki sariduna gordeko den): Talde Zenbakia Integer Taldearen identifikatzailea Taldekide Kopurua Integer 1eta 5 bitarteko zenbakia Tartearen beheko LongInt muga Zozketan parte hartzeko, taldeari eman zaizkion zenbakien beheko muga Tartearen goiko muga LongInt Zozketan parte hartzeko, taldeari eman zaizkion zenbakien goiko muga Zenbakia Integer Zozketan sarituak izanez gero, saritutako zenbakia, bestela 0 Adibide z: Zozketa egin aurretik: Taldea Perts Kop 1 1 2 2 3 2 4 1 5 4 . Zozketa egin ondoren: Honako zenbakiak atera badira: 15, 29, 24, 3 Beheko Goiko Zenbakia Muga Tartea Muga Tartea 1 5 0 6 11 12 17 18 22 23 30 30 . Taldea Perts . Kop Beheko Goiko Zenbakia Muga Tartea Muga Tartea 1 1 1 0 2 2 6 0 3 2 0 4 1 0 5 4 5 11 12 17 18 22 23 30 3 0 15 0 29 PROGRAMA: Menu honen bidez antolaturik dagoen programa bakarra egingo da: Menua 1. Zozketan parte hartzeko talde berria gehitu 2. Partiduko sarreren zozketa egin 3. Saridunen NAak zerrendatu 0. Amaitu Exekuzioaren hasieran, taldeen fitxategiaren izena eta zozketaren fitxategiaren izena eskatuko ditu programak. Taldeen fitxategia existitzen den egiaztatu ondoren, ez badago sortu egingo du. OHARRA: Programak fitxategiaren izena eskatuko du eta '.DAT' luzapena gehituko dio. Adibidea: fitxategiaren izena eskatuta, 'GRP-09' irakurtzen badu, 'GRP-09.DAT' izena sortuko du. Gero, aurreko menua pantailaratuko du eta erabiltzaileak hautatutakoa exekutatuko du ( prozesu hau behin eta berriro egingo da Amaitu aukeratu arte) 1. Aukera: Zozketan parte hartzeko talde berria gehitu Taldekideen kopurua galdetuko du. Honen ondoren, taldekide guztien Nortasun Agiria irakurriko ditu (Norbait beste talde batean badago errore­mezua emango du eta berriro NA eskatuko du). Informazio honekin eta taldeari identifikatzailea eman ondoren (1, 2, 3,…), taldeen fitxategian elementu berri bat gehituko du. Adibidea : Taldekide kopurua sartu: (1..5): 2 NA : 22222222 NA : 11111111 HONEK IZENA EMAN DU BESTE TALDE BATEAN, SARTU BESTE PERTSONA BAT,MESEDEZ NA : 12345678 2. Aukera: Partiduko sarreren zozketa egin Lehenengo eta behin zozketaren fitxategia sortuko da. Honetan, taldeak beste elementu izango dira. Eta taldeari dagokion zenbaki kopurua taldekide kopuruaren funtzioan dago, honako formula honen bidez: Zenbaki kopurua = 5 + ( Taldekide kopurua – 1 ) Adibidea: Taldekide bat = 5 Zenbaki; 2 Taldekide = 6 Zenbaki; … 5 Taldekide = 9 Zenbaki. Zozketaren zenbakiak kontsekutiboak izango dira adibidean azaltzen den bezala: 1. Taldea: taldekide 1, 5 zenbaki ⇒ tartea 1 .. 5 2. Taldea: 2 taldekide, 6 zenbaki ⇒ tartea 6 .. 11 3. Taldea: 2 taldekide, 6 zenbaki ⇒ tartea 12 .. 17 4. Taldea: taldekide 1, 5 zenbaki ⇒ tartea 18 .. 22 5. Taldea: 4 taldekide, 8 zenbaki ⇒ tartea 23 .. 30 Taldea Grupo Zozketarako 30 Zenbaki eman dira adibidean Beheko Num Perts Inf Comp Kop Muga Rango 1 1 1 2 2 6 3 2 4 1 5 4 Goiko Sup Nú mero Zenbakia Muga Rango 5 0 0 11 0 12 17 18 22 23 30 0 0 Zenbakia izeneko eremua 0 balioz hasieratu behar da. Jarraian, zozkatzen diren sarreren kopuru minimoa eskatuko da. Kopuru hau zozketan sartzen diren pertsonen kopurua baino txikiagoa edo berdina dela ematen da. Hau ez da egiaztatu behar (aurreko adibidean, sarrera kopurua 10 baino txikiagoa edo berdina dela suposatzen da) Amaitzeko, zozketan sartzen den azken zenbakia lortuko du programak (adibidean 30 izango da) eta saritutako zenbakiak ausazko zenbakien bidez sortuko dira, sarrera guztiak esleitu arte. Saritutako zenbaki bakoitzeko ea zein taldek duen bilatuko da; eta talde honek aurreko saririk ez badu jaso, taldekideei sarrera bana esleituko zaie eta Zenbaki eremuari zozketan atera den zenbakia biltegiratuko da. A d i b i d e a : Zozketa eman ondoresn: Sari hauek atera badira 15, 29, 24, 3 Zenbakia eremua aldatuko da 3, 5 eta 1. taldeetan (orden honetan) . Taldea Perts . Kop Beheko Muga Tartea 1 1 1 2 2 6 3 2 4 1 5 4 Goiko Zenbakia Muga Tartea 5 11 12 17 18 22 23 30 3 0 15 0 29 OHARRAK: Logikoa denez, sari kopurua ez dator bat sarrera kopuruarekin. Izan ere, sari bakoitzeko taldekide beste sarrera ematen baita. Era berean, sarrera kopuru minimoa eskatu da lehen. Honela, saritutako azken taldeak behar beste sarrera ziurta daiteke Adibidea: Zozketan gutxienez 7 sarrera badago: 15, 29, 24, 3 zenbakiak (orden honetan ) ateratzen badira , 7 sarrera (2 + 4 + 0 + 1) banatuko dira 3, 6, 12, 29 zenbakiak (orden honetan ) ateratzen badira , 9 sarrera (1 + 2 + 1 + 4) banatuko dira. 3. Aukera: Saridunen NAak zerrendatu Zozketaren fitxategia existitzen dela egiaztatu ondoren, honako era honetan pantailaratuko dira sarituen datuak: Tald Behek .. Goiko Zenbakia NA­ak 1 1 .. 5 3 11111111 3 12 .. 17 15 12121212 12121213 5 23 .. 30 29 33333333 44444444 55555555 66666666 0. Aukera: Amaitu Programaren exekuzioa amaituko da. Gutxienez egin behar den programak honako azpiprograma hauek izan behar ditu: • PertsonaBaDago: azpiprogramak sartutako NA zenbakiak taldeko fitxategian aurretik badagoela ala ez jakinarazten du • ZozketaFitxategiSortu: azpiprogramak talde fitxategitik dauden datutik Zozketa fitxategia sortuko du • AzkenZenbakia: azpiprogramak zozketan emandako azken zenbakia itzuliko du. Zenbaki hau zozketa fitxategi azken erregistroren goiko mugaren balioa izango da • TaldeSariemaileBilatu: azpiprogramak pasatutako zenbakia (Taldearen identifikatzailea bezala hartuz) taldea aurretik sari­emaile bada zozketa fitxategian duen kokapena itzuliko du, Bestela, –1 itzuliko du • TaldekideakEskuratu: azpiprogramak taldearen identifikatzailea hartuz taldekide guztien NA itzuliko du • Ariketa honen kalifikazioa nota osoaren % 75koa da • Gainditzeko, azterketa osatzen duten parte bakoitzaren notaren % 50a lortzea, gutxienez, behar­beharrezkoa da PROGRAM FI_Jun_2009 ; USES Crt ; CONST EXT_ARCHIVOS = '.DAT' ; TYPE tsCadenas = STRING [15] ; tsCadDNI = STRING [8] ; tasListaDNIs = ARRAY [1..5] OF tsCadDNI ; trgGruposPersonas = RECORD iNumGrupo, iNumComp : Integer ; asDNIs : tasListaDNIs ; END ; trgParticipaciones = RECORD iNumGrupo, iNumComp, iRangoInf, iRangoSup, iNumSorteo : Integer ; { Si ha salido en el sorteo } { Si NO vale 0 } END ; tfbrgFicherosGrupos = FILE OF trgGruposPersonas ; tfbrgFicherosParticipaciones = FILE OF trgParticipaciones ; VAR cOpcion, cEspera : Char ; sNomFichGrupos, sNomFichSorteo: tsCadenas ; FUNCTION fncLeerOpcion : Char ; VAR cOpcion : Char ; BEGIN ClrScr ; Writeln ('--------------Menú de opciones ---------------') ; Writeln ('1 Añadir nuevo grupo para el sorteo') ; Writeln ('2 Realizar el sorteo') ; Writeln ('3 Listar los grupos afortunados en el sorteo'); Writeln ('0 Terminar') ; Write ('Pulsa el codigo de la opcion: ') ; REPEAT cOpcion := ReadKey ; UNTIL ('0' <= cOpcion) AND (cOpcion <= '3') ; WriteLn (cOpcion) ; fncLeerOpcion := cOpcion ; END ; { fncLeerOpcion } PROCEDURE CrearSiNoExiste (sNomFichGrupos : tsCadenas) ; VAR fbrgFichGrupos : tfbrgFicherosGrupos ; BEGIN Assign (fbrgFichGrupos, sNomFichGrupos) ; {$I-} Reset (fbrgFichGrupos) ; {$I+} IF IOResult <> 0 THEN Rewrite (fbrgFichGrupos) ; Close (fbrgFichGrupos) ; Fundamentos de Informática Junio­2009 1 END ; { CrearSiNoExiste } Fundamentos de Informática Junio­2009 2 FUNCTION fnboExistePersona (sDNIBuscado : tsCadDNI ; sNomFichGrupos : tsCadenas) : Boolean ; VAR rgGrupo : trgGruposPersonas ; fbrgFichGrupos : tfbrgFicherosGrupos ; i : Integer ; boEncontrado : Boolean ; BEGIN boEncontrado := FALSE ; Assign (fbrgFichGrupos, sNomFichGrupos) ; Reset (fbrgFichGrupos) ; WHILE NOT EOF (fbrgFichGrupos) DO BEGIN Read (fbrgFichGrupos, rgGrupo) ; WITH rgGrupo DO FOR i := 1 TO iNumComp DO IF asDNIs[i] = sDNIBuscado THEN boEncontrado := TRUE ; END ; Close (fbrgFichGrupos) ; fnboExistePersona := boEncontrado END ; { fnboExistePersona } PROCEDURE AniadirGrupoAlFichero (CONST rgGrupo : trgGruposPersonas ; sNomFichGrupos: tsCadenas) ; VAR rgGrupoNuevo : trgGruposPersonas ; fbrgFichGrupos : tfbrgFicherosGrupos ; BEGIN Assign (fbrgFichGrupos, sNomFichGrupos) ; Reset (fbrgFichGrupos) ; Seek (fbrgFichGrupos, FileSize (fbrgFichGrupos)) ; rgGrupoNuevo := rgGrupo ; { Rellenar el campo iNumGrupo antes de escribir el GRUPO en el fichero} rgGrupoNuevo.iNumGrupo := FileSize (fbrgFichGrupos) + 1 ; Write (fbrgFichGrupos, rgGrupoNuevo) ; Close (fbrgFichGrupos) ; END ; PROCEDURE AniadirGrupo (sNomFichGrupos: tsCadenas) ; VAR rgGrupo : trgGruposPersonas ; i : Integer; BEGIN WITH rgGrupo DO BEGIN Write ('Escribe número de personas del grupo (1..5): ') ; ReadLn (iNumComp) ; i := 1 ; WHILE i <= iNumComp DO BEGIN Write (' ReadLn (asDNIs[i]) ; Fundamentos de Informática DNI de la persona: ') ; Junio­2009 3 IF fnboExistePersona (asDNIs[i], sNomFichGrupos) THEN Writeln ('ESA PERSONA YA ESTA APUNTADA EN OTRO GRUPO') ELSE i := i + 1 ; END ; { No se ha rellenado el campo iNumGrupo. Se rellenará antes de escribir el GRUPO en el fichero } END ; END ; AniadirGrupoAlFichero (rgGrupo, sNomFichGrupos) ; PROCEDURE CrearFichSorteo (sNomFichGrupos, sNomFichSorteo: tsCadenas) ; VAR rgGrupo : trgGruposPersonas ; fbrgFichGrupos : tfbrgFicherosGrupos ; rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; iUltimoNumero : Integer ; BEGIN Assign (fbrgFichGrupos, sNomFichGrupos) ; Reset (brgFichGrupos) ; Assign (fbrgFichSorteo, sNomFichSorteo) ; Rewrite (fbrgFichSorteo) ; iUltimoNumero := 0 ; WHILE NOT EOF (fbrgFichGrupos) DO BEGIN Read (fbrgFichGrupos, rgGrupo) ; WITH rgParticipacion DO BEGIN iNumGrupo := rgGrupo.iNumGrupo ; iNumComp := rgGrupo.iNumComp ; iRangoInf := iUltimoNumero + 1 ; iRangoSup := iUltimoNumero + 5 + (rgGrupo.iNumComp - 1 ) ; iNumSorteo := 0 ; iUltimoNumero := iRangoSup ; { para la siguiente vez } END ; Write (fbrgFichSorteo, rgParticipacion) ; END ; Close (fbrgFichGrupos) ; CLose (fbrgFichSorteo) ; END ; FUNCTION fniUltimoNumero (sNomFichSorteo : tsCadenas) : Integer ; VAR rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; iUltNumSorteo : Integer ; BEGIN Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; Seek (fbrgFichSorteo, FileSize (fbrgFichSorteo) - 1 ) ; IF FilePos (fbrgFichSorteo) > 0 THEN BEGIN Read (fbrgFichSorteo, rgParticipacion) ; iUltNumSorteo := rgParticipacion.iRangoSup END ELSE iUltNumSorteo := 0 ; Close (fbrgFichSorteo) ; Fundamentos de Informática Junio­2009 4 fniUltimoNumero := END ; iUltNumSorteo ; FUNCTION fniBuscarGrupoPremiado (iNumeroAleat: Integer ; sNomFichSorteo: tsCadenas) : Integer ; VAR rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; boEncontrado : Boolean ; BEGIN Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; boEncontrado := FALSE ; WHILE NOT EOF (fbrgFichSorteo) AND NOT boEncontrado DO BEGIN Read (fbrgFichSorteo, rgParticipacion) ; WITH rgParticipacion DO IF (iRangoInf <= iNumeroAleat) AND (iNumeroAleat <= iRangoSup) THEN boEncontrado := TRUE END ; IF boEncontrado AND (rgParticipacion.iNumSorteo = 0) THEN { Encontrado el grupo con ese número. Al que no le ha tocado antes } fniBuscarGrupoPremiado := FilePos (fbrgFichSorteo) - 1 ELSE fniBuscarGrupoPremiado := -1 ; Close (fbrgFichSorteo) ; END ; { fniBuscarGrupoPremiado } PROCEDURE SortearEntradas (sNomFichSorteo: tsCadenas) ; VAR iNumeroMayor, iEntradasDisponibles, iEntradasAsignadas : Integer ; rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; iNumeroAleat, iPosicPremiado : Integer ; boEncontrado : Boolean ; BEGIN Randomize ; Write ('Escribe número mínimo de entradas a sortear : ') ; ReadLn (iEntradasDisponibles) ; iNumeroMayor := fniUltimoNumero (sNomFichSorteo) ; iEntradasAsignadas := 0 ; WHILE iEntradasAsignadas < iEntradasDisponibles DO BEGIN iNumeroAleat := Random (iNumeroMayor) + 1 ; iPosicPremiado := fniBuscarGrupoPremiado (iNumeroAleat, sNomFichSorteo) ; IF iPosicPremiado <> -1 THEN BEGIN {------------------ Actualizar el fichero de Sorteo ----------} Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; Seek (fbrgFichSorteo, iPosicPremiado) ; Read (fbrgFichSorteo, rgParticipacion) ; rgParticipacion.iNumSorteo := iNumeroAleat ; Seek (fbrgFichSorteo, iPosicPremiado) ; Write (fbrgFichSorteo, rgParticipacion) ; Fundamentos de Informática Junio­2009 5 Close (fbrgFichSorteo) ; iEntradasAsignadas := iEntradasAsignadas + rgParticipacion.iNumComp ; END { IF } END ; { WHILE } END ; { SortearEntradas2 } PROCEDURE ObtenerPersonasGrupo ( iNumeroGrupo sNomFichGrupos VAR asDNIsGrupo VAR iNumCompGrupo : : : : Integer ; tsCadenas ; tasListaDNIs ; Integer ) ; { Dado el uso que se va a hacer de este subprograma: No sería necesario retornar la información iNumCompGrupo, pues desde donde se efectúa la llamada ya se conoce esa información } VAR rgGrupo : trgGruposPersonas ; fbrgFichGrupos : tfbrgFicherosGrupos ; boEncontrado : Boolean ; BEGIN Assign (fbrgFichGrupos, sNomFichGrupos) ; Reset (fbrgFichGrupos) ; boEncontrado := FALSE ; WHILE NOT EOF (fbrgFichGrupos) AND NOT boEncontrado DO BEGIN Read (fbrgFichGrupos, rgGrupo) ; IF rgGrupo.iNumGrupo = iNumeroGrupo THEN BEGIN asDNIsGrupo := rgGrupo.asDNIs ; iNumCompGrupo := rgGrupo.iNumComp ; boEncontrado := TRUE ; END ; END ; Close (fbrgFichGrupos) ; END ; { ObtenerPersonasGrupo } PROCEDURE ListaGruposPremiados (sNomFichPremiados, sNomFichGrupos : tsCadenas); VAR rgParticipacion : trgParticipaciones ; fbrgFichPremiados : tfbrgFicherosParticipaciones ; asDNIs : tasListaDNIs ; iNumCompGrupo, i : Integer ; BEGIN Assign (fbrgFichPremiados, sNomFichPremiados) ; Reset (fbrgFichPremiados) ; Writeln ('Listado de Grupos premiados') ; Writeln ; Writeln ('Grupo':5, 'Inf':7, ' .. ', 'Sup':3, 'Premiado':10, ' DNIs de las personas del grupo') Writeln ('================================================================') ; WHILE NOT EOF (fbrgFichPremiados) DO BEGIN Read (fbrgFichPremiados, rgParticipacion) ; ; IF rgParticipacion.iNumSorteo <> 0 THEN WITH rgParticipacion DO Fundamentos de Informática Junio­2009 6 BEGIN ObtenerPersonasGrupo (iNumGrupo, sNomFichGrupos, asDNIs, iNumCompGrupo) ; Write (iNumGrupo:5, iRangoInf:7, iRangoSup:7, iNumSorteo:10) ; { Listar los DNIs de las personas del grupo } { Se puede utilizar tanto iNumGrupo como iNumCompGrupo } FOR i:= 1 TO iNumComp DO Write (asDNIs[i]:10) ; Writeln ; END ; END ; Writeln ('---------------------------- Fin de listado ------------------') ; Close END ; (fbrgFichPremiados) ; FUNCTION fnboExisteFichero (sNomFichSorteo : tsCadenas) : Boolean ; VAR fbrgFichSorteo : tfbrgFicherosParticipaciones ; BEGIN Assign (fbrgFichSorteo, sNomFichSorteo) ; {$I-} Reset (fbrgFichSorteo) ; {$I+} IF IOResult <> 0 THEN fnboExisteFichero := FALSE ELSE BEGIN Close (fbrgFichSorteo) ; fnboExisteFichero := TRUE END ; END ; BEGIN {--------------------- PROGRAMA PRINCIPAL ----------------------} Write ('Nombre del fichero con los grupos de personas que participan: ') ; ReadLn (sNomFichGrupos) ; sNomFichGrupos := sNomFichGrupos + EXT_ARCHIVOS ; CrearSiNoExiste (sNomFichGrupos) ; Write ('Nombre del fichero del sorteo: ') ; ReadLn (sNomFichSorteo) ; sNomFichSorteo := sNomFichSorteo + EXT_ARCHIVOS ; Writeln (sNomFichSorteo) ; REPEAT cOpcion := fncLeerOpcion ; CASE cOpcion OF '1' : AniadirGrupo (sNomFichGrupos) ; '2' : BEGIN CrearFichSorteo (sNomFichGrupos, sNomFichSorteo) ; SortearEntradas (sNomFichSorteo) ; Writeln ('---- Finalizado el sorteo de las entradas ----') END ; '3' : IF fnboExisteFichero (sNomFichSorteo) THEN ListaGruposPremiados (sNomFichSorteo, sNomFichGrupos) ELSE Writeln ('ERROR: no se ha efectuado el sorteo') ; END ; IF cOpcion <> '0' THEN Fundamentos de Informática Junio­2009 7 cEspera := ReadKey ; UNTIL cOpcion = '0' ; END. {----------------------- Fin del programa de Junio de 2009 Fundamentos de Informática Junio­2009 --------------} 8 Otra forma de realizar el proceso del sorteo de entradas: PROCEDURE SortearEntradas (sNomFichSorteo: tsCadenas) ; VAR iNumeroMayor, iNumeroAleat, iPosicPremiado, iEntradasDisponibles, iEntradasAsignadas : Integer ; rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; BEGIN Randomize ; Write ('Escribe número mínimo de entradas a sortear : ') ; ReadLn (iEntradasDisponibles) ; Writeln ; iNumeroMayor := fniUltimoNumero (sNomFichSorteo) ; Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; iEntradasAsignadas := 0 ; WHILE iEntradasAsignadas < iEntradasDisponibles DO BEGIN iNumeroAleat := Random (iNumeroMayor) + 1 ; iPosicPremiado := fniBuscarGrupoPremiado (iNumeroAleat, sNomFichSorteo) ; IF iPosicPremiado <> -1 THEN BEGIN Seek (fbrgFichSorteo, iPosicPremiado) ; Read (fbrgFichSorteo, rgParticipacion) ; rgParticipacion.iNumSorteo := iNumeroAleat ; { Actualizar el fichero de Sorteo } Seek (fbrgFichSorteo, iPosicPremiado) ; Write (fbrgFichSorteo, rgParticipacion) ; iEntradasAsignadas := iEntradasAsignadas + rgParticipacion.iNumComp ; END END ; Close (fbrgFichSorteo) ; END ; { SortearEntradas } Fundamentos de Informática Junio­2009 9 PROGRAM Sortear3 ; USES Crt ; CONST EXT_ARCHIVOS = '.DAT' ; TYPE tsCadenas = STRING [15] ; tsCadDNI = STRING [8] ; tasListaDNIs = ARRAY [1..5] OF tsCadDNI ; trgGruposPersonas = RECORD iNumGrupo, iNumComp : Integer ; asDNIs : tasListaDNIs ; END ; trgParticipaciones = RECORD iNumGrupo, iNumComp, iRangoInf, iRangoSup, iNumSorteo : Integer ; { Si ha salido en el sorteo } { Si NO vale 0 } END ; tfbrgFicherosGrupos = FILE OF trgGruposPersonas ; tfbrgFicherosParticipaciones = FILE OF trgParticipaciones ; VAR cOpcion, cEspera : Char ; sNomFichGrupos, sNomFichSorteo: tsCadenas ; FUNCTION fncLeerOpcion : Char ; VAR cOpcion : Char ; BEGIN ClrScr ; Writeln ('--------------Menú de opciones ---------------') ; Writeln ('1 Añadir nuevo grupo para el sorteo') ; Writeln ('2 Realizar el sorteo') ; Writeln ('3 Listar los grupos afortunados en el sorteo'); Writeln ('0 Terminar') ; Write ('Pulsa el codigo de la opcion: ') ; REPEAT cOpcion := ReadKey ; UNTIL ('0' <= cOpcion) AND (cOpcion <= '3') ; WriteLn (cOpcion) ; fncLeerOpcion := cOpcion ; END ; { fncLeerOpcion } PROCEDURE CrearSiNoExiste (sNomFichGrupos : tsCadenas) ; VAR fbrgFichGrupos : tfbrgFicherosGrupos ; BEGIN Assign (fbrgFichGrupos, sNomFichGrupos) ; {$I-} Reset (fbrgFichGrupos) ; {$I+} IF IOResult <> 0 THEN Rewrite (fbrgFichGrupos) ; Close (fbrgFichGrupos) ; Fundamentos de Informática No publicada_Junio­2009 1 END ; { CrearSiNoExiste } FUNCTION fnboExistePersona (sDNIBuscado : tsCadDNI ; sNomFichGrupos : tsCadenas) : Boolean ; VAR rgGrupo : trgGruposPersonas ; fbrgFichGrupos : tfbrgFicherosGrupos ; i : Integer ; boEncontrado : Boolean ; BEGIN boEncontrado := FALSE ; Assign (fbrgFichGrupos, sNomFichGrupos) ; Reset (fbrgFichGrupos) ; WHILE NOT EOF (fbrgFichGrupos) DO BEGIN Read (fbrgFichGrupos, rgGrupo) ; WITH rgGrupo DO FOR i := 1 TO iNumComp DO IF asDNIs[i] = sDNIBuscado THEN boEncontrado := TRUE ; END ; Close (fbrgFichGrupos) ; fnboExistePersona := boEncontrado END ; { fnboExistePersona } PROCEDURE AniadirGrupoAlFichero (CONST rgGrupo : trgGruposPersonas ; sNomFichGrupos: tsCadenas) ; VAR rgGrupoNuevo : trgGruposPersonas ; fbrgFichGrupos : tfbrgFicherosGrupos ; BEGIN Assign (fbrgFichGrupos, sNomFichGrupos) ; Reset (fbrgFichGrupos) ; Seek (fbrgFichGrupos, FileSize (fbrgFichGrupos)) ; rgGrupoNuevo := rgGrupo ; { Rellenar el campo iNumGrupo antes de escribir el GRUPO en el fichero} rgGrupoNuevo.iNumGrupo := FileSize (fbrgFichGrupos) + 1 ; Write (fbrgFichGrupos, rgGrupoNuevo) ; Close (fbrgFichGrupos) ; END ; { AniadirGrupoAlFichero } PROCEDURE AniadirGrupo (sNomFichGrupos: tsCadenas) ; VAR rgGrupo : trgGruposPersonas ; i : Integer; BEGIN WITH rgGrupo DO BEGIN REPEAT Write ('Escribe número de personas del grupo (1..5): ') ; ReadLn (iNumComp) ; UNTIL (1 <= iNumComp) AND (iNumComp <= 5) ; i := 1 ; Fundamentos de Informática No publicada_Junio­2009 2 WHILE i <= iNumComp DO BEGIN Write (' DNI de la persona: ') ; ReadLn (asDNIs[i]) ; IF fnboExistePersona (asDNIs[i], sNomFichGrupos) THEN Writeln ('ESA PERSONA YA ESTA APUNTADA EN OTRO GRUPO. ', 'INDICA OTRA, POR FAVOR') ELSE i := i + 1 ; END ; { No se ha rellenado el campo iNumGrupo. Se rellenará antes de escribir el GRUPO en el fichero } END ; AniadirGrupoAlFichero (rgGrupo, sNomFichGrupos) ; END ; { AniadirGrupo } PROCEDURE CrearFichSorteo (sNomFichGrupos, sNomFichSorteo: tsCadenas) ; VAR rgGrupo : trgGruposPersonas ; fbrgFichGrupos : tfbrgFicherosGrupos ; rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; iUltimoNumero : Integer ; BEGIN Assign (fbrgFichGrupos, sNomFichGrupos) ; Reset (fbrgFichGrupos) ; Assign (fbrgFichSorteo, sNomFichSorteo) ; Rewrite (fbrgFichSorteo) ; iUltimoNumero := 0 ; WHILE NOT EOF (fbrgFichGrupos) DO BEGIN Read (fbrgFichGrupos, rgGrupo) ; WITH rgParticipacion DO BEGIN iNumGrupo := rgGrupo.iNumGrupo ; iNumComp := rgGrupo.iNumComp ; iRangoInf := iUltimoNumero + 1 ; iRangoSup := iUltimoNumero + 5 + (rgGrupo.iNumComp - 1 ) ; iNumSorteo := 0 ; iUltimoNumero := iRangoSup ; { para la siguiente vez } END ; Write (fbrgFichSorteo, rgParticipacion) ; END ; Close (fbrgFichGrupos) ; CLose (fbrgFichSorteo) ; END ; { CrearFichSorteo } FUNCTION fniUltimoNumero (sNomFichSorteo : tsCadenas) : Integer ; VAR rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; iUltNumSorteo : Integer ; BEGIN Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; Seek (fbrgFichSorteo, FileSize (fbrgFichSorteo) - 1 ) ; Fundamentos de Informática No publicada_Junio­2009 3 IF FilePos (fbrgFichSorteo) > 0 THEN BEGIN Read (fbrgFichSorteo, rgParticipacion) ; iUltNumSorteo := rgParticipacion.iRangoSup END ELSE { FilePos (fbrgFichSorteo) = 0 } iUltNumSorteo := 0 ; Close (fbrgFichSorteo) ; fniUltimoNumero := iUltNumSorteo ; END ; { fniUltimoNumero } PROCEDURE SortearEntradas (sNomFichSorteo: tsCadenas) ; VAR iNumeroMayor, iEntradasDisponibles, iEntradasAsignadas : Integer ; rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; iNumeroAleat, iPosicPremiado : Integer ; boEncontrado : Boolean ; BEGIN Randomize ; Write ('Escribe número mínimo de entradas a sortear : ') ; ReadLn (iEntradasDisponibles) ; Writeln ; iNumeroMayor := fniUltimoNumero (sNomFichSorteo) ; Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; iEntradasAsignadas := 0 ; WHILE iEntradasAsignadas < iEntradasDisponibles DO BEGIN iNumeroAleat := Random (iNumeroMayor) + 1 ; {--- Buscar en le fichero para ver si ya existe ese DNI ----} boEncontrado := FALSE ; Seek (fbrgFichSorteo, 0) ; WHILE NOT EOF (fbrgFichSorteo) AND NOT boEncontrado DO BEGIN Read (fbrgFichSorteo, rgParticipacion) ; WITH rgParticipacion DO IF (iRangoInf <= iNumeroAleat) AND (iNumeroAleat <= iRangoSup) THEN boEncontrado := TRUE END ; antes } IF boEncontrado AND (rgParticipacion.iNumSorteo = 0) THEN { Encontrado grupo con ese número. Al grupo no le ha tocado iPosicPremiado := FilePos (fbrgFichSorteo) - 1 ELSE iPosicPremiado := -1 ; {---------------------- Fin de la búsqueda ----------------------} IF iPosicPremiado <> -1 THEN BEGIN Seek (fbrgFichSorteo, iPosicPremiado) ; Fundamentos de Informática No publicada_Junio­2009 4 Read (fbrgFichSorteo, rgParticipacion) ; rgParticipacion.iNumSorteo := iNumeroAleat ; { Actualizar el fichero de Sorteo } Seek (fbrgFichSorteo, iPosicPremiado) ; Write (fbrgFichSorteo, rgParticipacion) ; iEntradasAsignadas := iEntradasAsignadas + rgParticipacion.iNumComp ; END END ; Close (fbrgFichSorteo) ; END ; { SortearEntradas2 } PROCEDURE ObtenerPersonasGrupo ( iNumeroGrupo sNomFichGrupos VAR asDNIsGrupo VAR iNumCompGrupo : : : : Integer ; tsCadenas ; tasListaDNIs ; Integer ) ; { Dado el uso que se va a hacer de este subprograma: No sería necesario retornar la información iNumCompGrupo, pues desde donde se efectúa la llamada ya se conoce esa información } VAR rgGrupo : trgGruposPersonas ; fbrgFichGrupos : tfbrgFicherosGrupos ; boEncontrado : Boolean ; BEGIN Assign (fbrgFichGrupos, sNomFichGrupos) ; Reset (fbrgFichGrupos) ; boEncontrado := FALSE ; WHILE NOT EOF (fbrgFichGrupos) AND NOT boEncontrado DO BEGIN Read (fbrgFichGrupos, rgGrupo) ; IF rgGrupo.iNumGrupo = iNumeroGrupo THEN BEGIN asDNIsGrupo := rgGrupo.asDNIs ; iNumCompGrupo := rgGrupo.iNumComp ; boEncontrado := TRUE ; END ; END ; Close (fbrgFichGrupos) ; END ; { ObtenerPersonasGrupo } PROCEDURE ListaGruposPremiados (sNomFichPremiados, sNomFichGrupos : tsCadenas); VAR rgParticipacion : trgParticipaciones ; fbrgFichPremiados : tfbrgFicherosParticipaciones ; asDNIs : tasListaDNIs ; iNumCompGrupo, i : Integer ; BEGIN Assign (fbrgFichPremiados, sNomFichPremiados) ; Reset (fbrgFichPremiados) ; Writeln ('Listado de Grupos premiados') ; Writeln ; Fundamentos de Informática No publicada_Junio­2009 5 Writeln ('Grupo':5, 'Inf':7, ' .. ', 'Sup':3, 'Premiado':10, ' DNIs de las personas del grupo') Writeln ('=================================================', '==============================') ; ; WHILE NOT EOF (fbrgFichPremiados) DO BEGIN Read (fbrgFichPremiados, rgParticipacion) ; IF rgParticipacion.iNumSorteo <> 0 THEN WITH rgParticipacion DO BEGIN ObtenerPersonasGrupo (iNumGrupo, sNomFichGrupos, asDNIs, iNumCompGrupo) ; Write (iNumGrupo:5, iRangoInf:7, iRangoSup:7, iNumSorteo:10) ; END ; { Listar los DNIs de las personas del grupo } { Se puede utilizar tanto iNumGrupo como iNumCompGrupo } FOR i:= 1 TO iNumComp DO Write (asDNIs[i]:10) ; Writeln ; END ; Writeln ; Writeln ('-------------------------------- Fin de listado ----', '---------------------------') ; Close (fbrgFichPremiados) ; END ; { ListaGruposPremiados } FUNCTION fnboExisteFichero (sNomFichSorteo : tsCadenas) : Boolean ; VAR fbrgFichSorteo : tfbrgFicherosParticipaciones ; BEGIN Assign (fbrgFichSorteo, sNomFichSorteo) ; {$I-} Reset (fbrgFichSorteo) ; {$I+} IF IOResult <> 0 THEN fnboExisteFichero := FALSE ELSE BEGIN Close (fbrgFichSorteo) ; fnboExisteFichero := TRUE END ; END ; BEGIN {--------------------- PROGRAMA PRINCIPAL ----------------------} Write ('Nombre del fichero con los grupos de personas que participan: ') ; ReadLn (sNomFichGrupos) ; sNomFichGrupos := sNomFichGrupos + EXT_ARCHIVOS ; CrearSiNoExiste (sNomFichGrupos) ; Write ('Nombre del fichero del sorteo: ') ; ReadLn (sNomFichSorteo) ; sNomFichSorteo := sNomFichSorteo + EXT_ARCHIVOS ; Writeln (sNomFichSorteo) ; Fundamentos de Informática No publicada_Junio­2009 6 REPEAT cOpcion := fncLeerOpcion ; CASE cOpcion OF '1' : AniadirGrupo (sNomFichGrupos) ; '2' : BEGIN CrearFichSorteo (sNomFichGrupos, sNomFichSorteo) ; SortearEntradas (sNomFichSorteo) ; Writeln ; Writeln ('---- Finalizado el sorteo de las entradas ----') END ; '3' : IF fnboExisteFichero (sNomFichSorteo) THEN ListaGruposPremiados (sNomFichSorteo, sNomFichGrupos) ELSE Writeln ('ERROR: no se ha efectuado el sorteo') ; END ; IF cOpcion <> '0' THEN cEspera := ReadKey ; UNTIL cOpcion = '0' ; END. {--------------- Fin del programa de Junio de 2009 ------------------} Fundamentos de Informática No publicada_Junio­2009 7 FUNCTION fniBuscarGrupoPremiado (iNumeroAleat: Integer ; sNomFichSorteo: tsCadenas) : Integer ; VAR rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; boEncontrado : Boolean ; BEGIN Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; boEncontrado := FALSE ; WHILE NOT EOF (fbrgFichSorteo) AND NOT boEncontrado DO BEGIN Read (fbrgFichSorteo, rgParticipacion) ; WITH rgParticipacion DO IF (iRangoInf <= iNumeroAleat) AND (iNumeroAleat <= iRangoSup) THEN boEncontrado := TRUE END ; IF boEncontrado AND (rgParticipacion.iNumSorteo = 0) THEN { Encontrado el grupo con ese número. Al grupo no le ha tocado antes } fniBuscarGrupoPremiado := FilePos (fbrgFichSorteo) - 1 ELSE fniBuscarGrupoPremiado := -1 ; Close (fbrgFichSorteo) ; END ; { fniBuscarGrupoPremiado } PROCEDURE SortearEntradas (sNomFichSorteo: tsCadenas) ; VAR iNumeroMayor, iNumeroAleat, iPosicPremiado, iEntradasDisponibles, iEntradasAsignadas : Integer ; rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; BEGIN Randomize ; Write ('Escribe número mínimo de entradas a sortear : ') ; ReadLn (iEntradasDisponibles) ; Writeln ; iNumeroMayor := fniUltimoNumero (sNomFichSorteo) ; Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; iEntradasAsignadas := 0 ; WHILE iEntradasAsignadas < iEntradasDisponibles DO BEGIN iNumeroAleat := Random (iNumeroMayor) + 1 ; iPosicPremiado := fniBuscarGrupoPremiado (iNumeroAleat, sNomFichSorteo) ; IF iPosicPremiado <> -1 THEN BEGIN Seek (fbrgFichSorteo, iPosicPremiado) ; Read (fbrgFichSorteo, rgParticipacion) ; rgParticipacion.iNumSorteo Fundamentos de Informática := iNumeroAleat ; No publicada_Junio­2009 8 { Actualizar el fichero de Sorteo } Seek (fbrgFichSorteo, iPosicPremiado) ; Write (fbrgFichSorteo, rgParticipacion) ; iEntradasAsignadas := iEntradasAsignadas + rgParticipacion.iNumComp ; END END ; Close (fbrgFichSorteo) ; END ; { SortearEntradas } Otra manera: Pasar como parámetro la variable ficheo FUNCTION fniBuscarGrupoPremiado (iNumeroAleat: Integer ; fbrgFichSorteo : tfbrgFicherosParticipaciones) : Integer ; VAR rgParticipacion : trgParticipaciones ; ; boEncontrado : Boolean ; BEGIN Seek (fbrgFichSorteo, 0) ; boEncontrado := FALSE ; WHILE NOT EOF (fbrgFichSorteo) AND NOT boEncontrado DO BEGIN Read (fbrgFichSorteo, rgParticipacion) ; WITH rgParticipacion DO IF (iRangoInf <= iNumeroAleat) AND (iNumeroAleat <= iRangoSup) THEN boEncontrado := TRUE END ; IF boEncontrado AND (rgParticipacion.iNumSorteo = 0) THEN { Encontrado el grupo con ese número. Al grupo no le ha tocado antes } fniBuscarGrupoPremiado := FilePos (fbrgFichSorteo) - 1 ELSE fniBuscarGrupoPremiado := -1 ; END ; { fniBuscarGrupoPremiado } PROCEDURE SortearEntradas (sNomFichSorteo: tsCadenas) ; VAR iNumeroMayor, iNumeroAleat, iPosicPremiado, iEntradasDisponibles, iEntradasAsignadas : Integer ; rgParticipacion : trgParticipaciones ; fbrgFichSorteo : tfbrgFicherosParticipaciones ; BEGIN Randomize ; Write ('Escribe número mínimo de entradas a sortear : ') ; ReadLn (iEntradasDisponibles) ; Writeln ; iNumeroMayor := fniUltimoNumero (sNomFichSorteo) ; Fundamentos de Informática No publicada_Junio­2009 9 Assign (fbrgFichSorteo, sNomFichSorteo) ; Reset (fbrgFichSorteo) ; iEntradasAsignadas := 0 ; WHILE iEntradasAsignadas < iEntradasDisponibles DO BEGIN iNumeroAleat := Random (iNumeroMayor) + 1 ; iPosicPremiado := fniBuscarGrupoPremiado (iNumeroAleat, fbrgFichSorteo) ; IF iPosicPremiado <> -1 THEN BEGIN Seek (fbrgFichSorteo, iPosicPremiado) ; Read (fbrgFichSorteo, rgParticipacion) ; rgParticipacion.iNumSorteo := iNumeroAleat ; { Actualizar el fichero de Sorteo } Seek (fbrgFichSorteo, iPosicPremiado) ; Write (fbrgFichSorteo, rgParticipacion) ; iEntradasAsignadas := iEntradasAsignadas + rgParticipacion.iNumComp ; END END ; Close (fbrgFichSorteo) ; END ; { SortearEntradas } Fundamentos de Informática No publicada_Junio­2009 10