Este ejercicio recrea el acceso a una atracción popular con dos colas: general y FastPass. El sistema debe garantizar que por cada dos invitados con FastPass se atienda al menos uno de la cola general para mantener la percepción de justicia.
La operación diaria requiere:
El tablero muestra en tiempo real la cantidad de visitantes por cola y los ingresados en cada turno.
Utilizamos una cola circular simple para cada tipo de pase.
#define CAP_VISITANTES 40
#define MAX_NOMBRE 40
typedef struct {
char nombre[MAX_NOMBRE];
} Visitante;
typedef struct {
Visitante datos[CAP_VISITANTES];
int frente;
int final;
int cantidad;
} ColaVisitantes;
void cola_init(ColaVisitantes *cola) {
cola->frente = 0;
cola->final = 0;
cola->cantidad = 0;
}
int cola_push(ColaVisitantes *cola, Visitante v) {
if (cola->cantidad == CAP_VISITANTES) {
return 0;
}
cola->datos[cola->final] = v;
cola->final = (cola->final + 1) % CAP_VISITANTES;
cola->cantidad++;
return 1;
}
int cola_pop(ColaVisitantes *cola, Visitante *v) {
if (cola->cantidad == 0) {
return 0;
}
*v = cola->datos[cola->frente];
cola->frente = (cola->frente + 1) % CAP_VISITANTES;
cola->cantidad--;
return 1;
}
La estructura principal controla ambas colas y lleva contadores para el reporte.
typedef struct {
ColaVisitantes fastpass;
ColaVisitantes general;
int turnoFast;
int atendidosFast;
int atendidosGeneral;
} ControlAtraccion;
void control_init(ControlAtraccion *c) {
cola_init(&c->fastpass);
cola_init(&c->general);
c->turnoFast = 0;
c->atendidosFast = 0;
c->atendidosGeneral = 0;
}
int registrarVisitante(ControlAtraccion *c, const char *nombre, int esFastPass) {
Visitante v;
strncpy(v.nombre, nombre, MAX_NOMBRE - 1);
v.nombre[MAX_NOMBRE - 1] = '\0';
return esFastPass ? cola_push(&c->fastpass, v) : cola_push(&c->general, v);
}
int despachar(ControlAtraccion *c, Visitante *v) {
if (c->fastpass.cantidad > 0 && (c->turnoFast < 2 || c->general.cantidad == 0)) {
if (cola_pop(&c->fastpass, v)) {
c->turnoFast++;
c->atendidosFast++;
return 1;
}
}
if (cola_pop(&c->general, v)) {
c->turnoFast = 0;
c->atendidosGeneral++;
return 1;
}
if (cola_pop(&c->fastpass, v)) {
c->turnoFast = 1;
c->atendidosFast++;
return 1;
}
return 0;
}
void mostrarColas(const ControlAtraccion *c) {
printf("FastPass (%d):\n", c->fastpass.cantidad);
for (int i = 0, idx = c->fastpass.frente; i < c->fastpass.cantidad; ++i, idx = (idx + 1) % CAP_VISITANTES) {
printf(" FP - %s\n", c->fastpass.datos[idx].nombre);
}
printf("General (%d):\n", c->general.cantidad);
for (int i = 0, idx = c->general.frente; i < c->general.cantidad; ++i, idx = (idx + 1) % CAP_VISITANTES) {
printf(" GEN - %s\n", c->general.datos[idx].nombre);
}
}
void reporte(const ControlAtraccion *c) {
puts("--- Resumen ---");
printf("Atendidos FastPass: %d\n", c->atendidosFast);
printf("Atendidos General: %d\n", c->atendidosGeneral);
}
El menú permite registrar invitados, despachar y consultar el estado.
void limpiarEntrada(void) {
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
}
int main(void) {
ControlAtraccion control;
control_init(&control);
int opcion;
char nombre[MAX_NOMBRE];
Visitante v;
do {
puts("\n1) Registrar visitante general");
puts("2) Registrar visitante FastPass");
puts("3) Despachar siguiente");
puts("4) Mostrar colas");
puts("0) Cerrar atraccion");
printf("Opcion: ");
if (scanf("%d", &opcion) != 1) {
puts("Entrada invalida");
limpiarEntrada();
continue;
}
limpiarEntrada();
switch (opcion) {
case 1:
case 2:
printf("Nombre: ");
if (!fgets(nombre, sizeof nombre, stdin)) break;
nombre[strcspn(nombre, "\n")] = '\0';
if (registrarVisitante(&control, nombre, opcion == 2)) {
puts("Registrado.");
} else {
puts("Cola completa.");
}
break;
case 3:
if (despachar(&control, &v)) {
printf("Ingresando: %s\n", v.nombre);
} else {
puts("No hay visitantes en espera.");
}
break;
case 4:
mostrarColas(&control);
reporte(&control);
break;
case 0:
puts("Atraccion cerrada.");
reporte(&control);
break;
default:
puts("Opcion no valida.");
}
} while (opcion != 0);
return 0;
}
El siguiente listado reúne todo el simulador en un solo archivo:
#include <stdio.h>
#include <string.h>
#define CAP_VISITANTES 40
#define MAX_NOMBRE 40
typedef struct {
char nombre[MAX_NOMBRE];
} Visitante;
typedef struct {
Visitante datos[CAP_VISITANTES];
int frente;
int final;
int cantidad;
} ColaVisitantes;
typedef struct {
ColaVisitantes fastpass;
ColaVisitantes general;
int turnoFast;
int atendidosFast;
int atendidosGeneral;
} ControlAtraccion;
void cola_init(ColaVisitantes *cola);
int cola_push(ColaVisitantes *cola, Visitante v);
int cola_pop(ColaVisitantes *cola, Visitante *v);
void control_init(ControlAtraccion *c);
int registrarVisitante(ControlAtraccion *c, const char *nombre, int esFastPass);
int despachar(ControlAtraccion *c, Visitante *v);
void mostrarColas(const ControlAtraccion *c);
void reporte(const ControlAtraccion *c);
void limpiarEntrada(void);
void cola_init(ColaVisitantes *cola) { cola->frente = cola->final = cola->cantidad = 0; }
int cola_push(ColaVisitantes *cola, Visitante v) {
if (cola->cantidad == CAP_VISITANTES) return 0;
cola->datos[cola->final] = v;
cola->final = (cola->final + 1) % CAP_VISITANTES;
cola->cantidad++;
return 1;
}
int cola_pop(ColaVisitantes *cola, Visitante *v) {
if (cola->cantidad == 0) return 0;
*v = cola->datos[cola->frente];
cola->frente = (cola->frente + 1) % CAP_VISITANTES;
cola->cantidad--;
return 1;
}
void control_init(ControlAtraccion *c) {
cola_init(&c->fastpass);
cola_init(&c->general);
c->turnoFast = 0;
c->atendidosFast = 0;
c->atendidosGeneral = 0;
}
int registrarVisitante(ControlAtraccion *c, const char *nombre, int esFastPass) {
Visitante v;
strncpy(v.nombre, nombre, MAX_NOMBRE - 1);
v.nombre[MAX_NOMBRE - 1] = '\0';
return esFastPass ? cola_push(&c->fastpass, v) : cola_push(&c->general, v);
}
int despachar(ControlAtraccion *c, Visitante *v) {
if (c->fastpass.cantidad > 0 && (c->turnoFast < 2 || c->general.cantidad == 0)) {
cola_pop(&c->fastpass, v);
c->turnoFast++;
c->atendidosFast++;
return 1;
}
if (c->general.cantidad > 0) {
cola_pop(&c->general, v);
c->turnoFast = 0;
c->atendidosGeneral++;
return 1;
}
if (cola_pop(&c->fastpass, v)) {
c->turnoFast = 1;
c->atendidosFast++;
return 1;
}
return 0;
}
void mostrarColas(const ControlAtraccion *c) {
printf("FastPass (%d):\n", c->fastpass.cantidad);
for (int i = 0, idx = c->fastpass.frente; i < c->fastpass.cantidad; ++i, idx = (idx + 1) % CAP_VISITANTES) {
printf(" FP - %s\n", c->fastpass.datos[idx].nombre);
}
printf("General (%d):\n", c->general.cantidad);
for (int i = 0, idx = c->general.frente; i < c->general.cantidad; ++i, idx = (idx + 1) % CAP_VISITANTES) {
printf(" GEN - %s\n", c->general.datos[idx].nombre);
}
}
void reporte(const ControlAtraccion *c) {
puts("--- Resumen ---");
printf("Atendidos FastPass: %d\n", c->atendidosFast);
printf("Atendidos General: %d\n", c->atendidosGeneral);
}
void limpiarEntrada(void) {
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
}
int main(void) {
ControlAtraccion control;
control_init(&control);
int opcion;
char nombre[MAX_NOMBRE];
Visitante v;
do {
puts("\n1) Registrar visitante general");
puts("2) Registrar visitante FastPass");
puts("3) Despachar siguiente");
puts("4) Mostrar colas");
puts("0) Cerrar atraccion");
printf("Opcion: ");
if (scanf("%d", &opcion) != 1) {
puts("Entrada invalida");
limpiarEntrada();
continue;
}
limpiarEntrada();
switch (opcion) {
case 1:
case 2:
printf("Nombre: ");
if (!fgets(nombre, sizeof nombre, stdin)) break;
nombre[strcspn(nombre, "\n")] = '\0';
if (registrarVisitante(&control, nombre, opcion == 2)) {
puts("Registrado.");
} else {
puts("Cola completa.");
}
break;
case 3:
if (despachar(&control, &v)) {
printf("Ingresando: %s\n", v.nombre);
} else {
puts("No hay visitantes en espera.");
}
break;
case 4:
mostrarColas(&control);
reporte(&control);
break;
case 0:
puts("Atraccion cerrada.");
reporte(&control);
break;
default:
puts("Opcion no valida.");
}
} while (opcion != 0);
return 0;
}
En el siguiente ejemplo práctico integraremos sensores en tiempo real y almacenamiento persistente.