Skip to content

oscarzamora/horarios

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Generador de Horarios

Archivo histórico de un proyecto en Turbo Pascal · 1995-1996

Pascal Platform Graphics License: MIT

Era Status Lang Encoding Code preserved Sanitized

Generador combinatorio de horarios universitarios sin cruces hecho en MS-DOS, recuperado después de ~30 años

Historia · Arquitectura · Formato de datos · Cómo compilar · Saneamiento de datos


Autor original: Oscar Zamora Plasencia · ZmS Software © 1995-1996 Sitio del autor: ozamora.com Estado: Archivo histórico preservado. No se modifica el código fuente.


El origen (1995)

Tercer año de Ingeniería de Sistemas en la Universidad de Lima, 1995.

Inscribirse a los cursos cada semestre era una experiencia frustrante:

  • Llegabas al día de la matrícula con tu combinación ideal armada a mano, a lápiz, sobre una cuadrícula impresa.
  • En la cola, una clase estaba llena o cerrada y todo el horario se caía.
  • Había que rearmar combinaciones al vuelo, sin cruces, con la cola detrás y el reloj corriendo.
  • Encontrar otra combinación válida en minutos, manualmente, era casi imposible. Más de una vez terminé matriculado en lo que sobraba, no en lo que quería.

La idea fue simple: hacer todas las permutaciones por adelantado. Que el programa genere todas las combinaciones válidas (sin cruces) antes de ir a la matrícula, para llegar con un plan A, B, C, D… y si una sección se cae, saltar a la siguiente combinación ya lista.

El "foco se prendió" mientras hacía guardias como veedor en la sala de cómputo de la facultad — entre turnos sin mucho que hacer, iterando ideas, terminé de armar el algoritmo iterativo que evita la recursión y detecta cruces con un bitmap 15×6 (horas × días).

La conversación de 1998 que no pasó

En 1998 la universidad me pidió el código fuente. Decidí no entregarlo — quizás pensando en algún retorno financiero que nunca iba a llegar. Hoy, casi 30 años después, sé que probablemente no fue la decisión más acertada.

Por eso ahora lo publico como archivo histórico: fidedigno al original, con su Turbo Pascal y sus comentarios en español con CP850. Quizás el algoritmo de detección de cruces le sirva a alguien. Quizás no. Pero ya no se queda en un ZIP guardado en OneDrive.

Sobre la eficiencia del algoritmo (corroboración técnica)

El benchmark documentado verbatim en src/GDH.HLP reporta:

5 cursos · 84 secciones · 861 840 combinaciones evaluadas en 3 min 20 s sobre un 486DLC a 40 MHz con SMARTDRV → 125 030 horarios válidos generados · archivo temporal de 11.5 MB.

Las cifras dan:

  • ~4 309 combinaciones evaluadas por segundo
  • ~625 records válidos escritos a disco por segundo

Para un 486DLC de 1995 (≈6-8 MIPS escalar, disco mecánico con caché de software SMARTDRV), el programa está cerca del límite teórico de I/O: el caché absorbe los writes y la CPU casi no se aburre. El manual cita "alrededor de 1000 combinaciones/s" como cifra conservadora, pero el caso real medido es ~4× más rápido.

Las decisiones de diseño que lo hicieron eficiente (verificables en procedure genera de src/HORA.PAS):

Decisión Por qué importa en 1995
Enumeración iterativa (no recursiva) El stack era de 64 KB; recursión profunda en 15 cursos hubiera reventado el modelo de memoria DOS
Contador multi-base sobre top[1..totcur] Genera el producto cartesiano sin construir el árbol — memoria O(totcur) en vez de O(combinaciones)
Detección de cruce con bitmap 15×6 Cada celda es O(1); detecta colisión apenas ocurre, no al final
Early-exit en cruce (cruce := true) Apenas detecta una colisión deja de marcar el resto de horas
Salida streaming a disco (file of regcuadre) 125 030 horarios × 96 bytes = 12 MB → imposible en los 640 KB de memoria conventional de DOS
Reutilizar vaciohor como baseline del bitmap Las "horas no deseadas" se aplican gratis, no como filtro post-hoc
Records compactos (96 bytes/horario, reducidos desde 176 en la Beta) Reduce I/O y tamaño del archivo temporal en ~45%

Hoy el mismo cálculo correría en milisegundos en cualquier laptop, pero la estructura del algoritmo sigue siendo la correcta: iterativo, bitmap de colisión, early-exit, streaming. Es básicamente lo que un solver moderno haría con las mismas restricciones de memoria embebida.

El mouse: integrado en la versión final

En febrero de 1996 (BETA96) agregué al proyecto la unidad src/MOUSE.PAS: un driver completo que habla con el ratón vía INT 33h del BIOS, con 10 cursores gráficos personalizados (flecha, reloj de arena, mano apuntando, check, etc.). El objetivo era claro: la siguiente versión del programa iba a soportar mouse — click sobre la grilla 15×6 para marcar horas, click directo sobre los ítems de las listas, botones presionables con el cursor.

Durante mucho tiempo creí que esa integración había quedado incompleta. El código fuente preservado en src/ (HORA11, 16-abr-1996) lo respaldaba:

  • HORA.PAS declara uses crt, graph, uhora, uhora2; — sin mouse.
  • 11 readkey y 47 códigos de tecla literales — todo por teclado.
  • El manual de HORA11 (21 tópicos) no menciona el ratón.
  • La unidad MOUSE.PAS estaba presente desde feb-1996 pero sin enlazar.

Pero sí terminé de integrarla. La evidencia apareció en un backup de OneDrive bajo _Archived_/DOS Applications/Horarios/: el ejecutable compilado del 1 de junio de 1996 — 6 semanas posterior al source preservado — junto con su manual de ayuda actualizado. La evidencia decisiva está en el manual:

  • Nuevo tópico "Usando el Mouse" abriendo la ayuda y declarando textualmente: "Esta versión soporta mouse, y se pueden desarrollar todas las tareas usando el mouse".
  • 21 menciones de mouse, click o botón describiendo flujos específicos:
    • "click en un botón deseado del menú" (menú principal),
    • "click en el ítem deseado, y luego en el botón OK" (selectitem),
    • "click en las flechas de la ventana" (scrollbar de selectitem),
    • "click en el recuadro deseado" / "click en el bloque deseado para marcar o desmarcar la hora" (grilla 15×6 de tabla),
    • "click en el botón Cancel" (diálogos).
  • ✅ Manual ampliado: 24 tópicos vs. 21 del HORA11 anterior.
  • ✅ Menú renombrado: "Adicionar Curso" → "Adicionar Sección" (más correcto).
  • Lo que NO es evidencia válida: una búsqueda ingenua del opcode CD 33 (INT 33h) en el .EXE arroja una sola coincidencia, en bytes que claramente son datos comprimidos del runtime de Turbo Pascal (no instrucción). Las llamadas INT 33h reales están dentro del segmento de código de la unit MOUSE.TPU enlazada, empaquetada por el compilador, y no son directamente detectables por byte search.

El código fuente de esa versión final nunca se conservó. Solo sobrevivió el EXE compilado, en release/1996-06-FINAL/ junto al manual y los drivers BGI necesarios para ejecutarlo en DOSBox.

Reconstrucción moderna del fuente perdido

Como el fuente real está perdido pero el comportamiento esperado está documentado explícitamente en el manual de junio 1996, en reconstructed/1996-06-FINAL-with-mouse/ está una re-implementación del propio autor (2026) que integra MOUSE.PAS exactamente donde el manual dice que el mouse funcionaba: menú principal, diálogos msgbox, listas selectitem (ítems, flechas y track del scrollbar), formularios gettext, grilla 15×6 de tabla y visor impcuadres.

No es decompilación del EXE: es una reconstrucción por fuente perdido sobre HORA11 (v1.1), con la misma API, el mismo estilo del autor y click adicional al teclado. Cubre punto a punto la especificación del manual. Detalle completo, supuestos y falsabilidad en reconstructed/1996-06-FINAL-with-mouse/RECONSTRUCTION-NOTES.md.

Ver también docs/codigo/MOUSE.PAS.md para el detalle de la unidad MOUSE.


¿Qué hay aquí?

Este repositorio preserva cuatro snapshots reales del proyecto a lo largo de su evolución, más una reconstrucción moderna del fuente perdido de junio 1996, más documentación para entenderlo sin necesidad de ejecutarlo en DOS.

Carpeta Contenido Estatus
release/1996-06-FINAL/ EXE final con mouse (1 jun 1996) Binario real — fuente perdida
reconstructed/1996-06-FINAL-with-mouse/ Reconstrucción del fuente con mouse Re-implementación del autor (2026) según el manual
src/ Versión HORA11 (16 abr 1996, v1.1 pre-final) Último source preservado, sin mouse integrado
history/1995-08-HORABETA/ v1.0 Beta — agosto 1995 Primera versión conservada
history/1995-09-HORA10/ v1.0 estable — septiembre 1995 Incluye CAMBIOS.TXT original
history/1996-02-BETA96/ Beta 96 — febrero 1996 Introduce HORA.PAS y MOUSE.PAS
docs/ Documentación moderna Historia, arquitectura, formatos, cómo compilar

Documentación

Estructura

horarios/
├── release/
│   └── 1996-06-FINAL/                ⭐ EXE final con mouse (1 jun 1996) — fuente perdida
├── reconstructed/
│   └── 1996-06-FINAL-with-mouse/     🔧 Re-implementación del fuente perdido (2026)
├── src/                              ★ HORA11 — último source preservado (16 abr 1996)
├── history/
│   ├── 1995-08-HORABETA/             v1.0 Beta
│   ├── 1995-09-HORA10/               v1.0 estable
│   └── 1996-02-BETA96/               Beta 96
├── docs/
│   ├── HISTORIA.md
│   ├── ARQUITECTURA.md
│   ├── FORMATO-DATOS.md
│   ├── COMPILACION.md
│   ├── SANEAMIENTO.md
│   ├── CAMBIOS-ORIGINALES.txt
│   └── codigo/                     Docs por unidad: HORA, HORARIO, UHORA, UHORA2, MOUSE
├── scripts/sanitize-data.ps1
├── .vscode/                        Asocia .PAS a Pascal con encoding CP850
├── .gitignore
└── .gitattributes

Convenciones de preservación

  • No se editan los .PAS ni .HLP originales. Toda la documentación es externa (docs/codigo/*.md).
  • Los binarios .DAT y .HOR fueron SANEADOS — contenían mis horarios reales de cada semestre, con los apellidos reales de mis profesores y el plan de estudios identificable. Decidí exponer mi propia historia pero no la de terceros. Estructura, tamaño, formato de records y timestamps preservados; contenido string reemplazado por placeholders sintéticos. Ver docs/SANEAMIENTO.md.
  • Timestamps preservados (LastWriteTime original de 1995-1996) en todas las copias.
  • Encoding original CP850 (DOS Latin español). VS Code lo reabre correctamente gracias a .vscode/settings.json.
  • CRLF mantenido en todos los archivos de texto (proyecto DOS).

Vistazo rápido al programa

  • Lenguaje: Turbo Pascal (modo gráfico VGA 640×480 vía unidad graph / BGI)
  • Capacidades: hasta 15 cursos · 25 secciones por curso · 375 secciones totales
  • Algoritmo: enumeración combinatoria iterativa con bitmap de cruces (~4 300 combinaciones/s en un 486DLC a 40 MHz — ver sección de eficiencia)
  • Salidas: visualización en pantalla + impresión a LPT1 (horario completo o lista de secciones)
  • Persistencia: typed files binarios (file of <record>), formato propietario
  • Entrada: teclado completo (flechas, Tab, Enter, Esc, F1, F5) en el código preservado; el binario FINAL agregó mouse según el manual de junio 1996 (reconstrucción en reconstructed/1996-06-FINAL-with-mouse/)

Ver docs/ARQUITECTURA.md para el detalle completo.


Sobre el autor

Oscar Zamora Plasencia Web GitHub

Ingeniero de Sistemas · Universidad de Lima · Promoción 1998


"Quizás el algoritmo de detección de cruces le sirva a alguien. Quizás no. Pero ya no se queda en un ZIP guardado en OneDrive."

About

Generador combinatorio de horarios universitarios sin cruces — Turbo Pascal MS-DOS, 1995-1996. Archivo histórico preservado byte-a-byte con documentación moderna.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages