Página 1
Parcial 1: Gestión de Operaciones (QuindíoExpress)
Asignatura: Estructuras de Datos
Integrantes: Tomas Suaza y Juan Esteban Herrera
Institución: Universidad del Quindío
Lenguaje: Java
PARTE A. Análisis y Diseño
A.1. Selección y justificación de estructuras de datos
C.7. Respuestas argumentadas
Página 8
PARTE D. Uso Justificado de Inteligencia Artificial
D.1. Bitácora de consultas
Parte
Herramienta
Qué preguntamos
Por qué la
consultamos
Cómo verificamos
Qué modificamos
B
Main
Main
As a student presenter (Juan), I want to explain that the project is divided into layers — model, structures, service, and main — so that I can justify the architectural reasoning behind the division. As a student presenter, I want to explain the model layer and the service layer in depth, including the purpose of each class such as Repartidor and Paquete, and why validations are created directly in the constructor, so that I can demonstrate thorough understanding of the codebase. As a student presenter, I want a well-generated PDF with images and explanations of everything, organized around my assigned part (Juan), so that I can study and present effectively. As a student presenter, I want prepared questions with answers covering all topics, so that I can be fully prepared for the defense. The project name is sustentacion-juan.
El sistema guarda referencias de cada Paquete en varias colecciones, cada una escogida por la operación que
más se repite en esa necesidad.
Necesidad
Estructura elegida
Operación
principal
Complejidad
Alternativa
descartada
Justificación
orden de llegada
ArrayDeque
(Queue)
offer / poll
O(1)
rápida por código
HashMap
get(código)
O(1) prom.
ArrayList
recorrido
Llega directo a la cubeta del código. En
una lista habría que revisar uno por
uno: O(n).
duplicados
HashSet
add
O(1) prom.
ArrayList +
contains
Rechaza repetidos al instante; con una
lista hay que recorrerla en cada
inserción: O(m).
orden alfabético
TreeSet
add /
recorrer
O(log m)
HashSet +
ordenar
Árbol balanceado: siempre ordenado y
sin repetidos. Ordenar en cada reporte
costaría O(m log m).
primero la mayor
prioridad
PriorityQueue
peek / poll
O(1) / O(log n)
Lista + sort
Con el Comparator (prioridad →
tiempo → código) deja al más urgente
en la raíz sin reordenar todo: ordenar
en cada registro costaría O(n log n).
orden de entrega
ListaSimplement
eEnlazada
agregar
O(1)
LinkedList
(prohibida)
Hecha desde cero. Guarda cabeza y
cola, así agregar al final no recorre la
lista.
→ Paquete
HashMap<String,
Paquete>
put / get
O(1) prom.
TreeMap
Es una relación clave-valor. TreeMap
cuesta O(log n) por guardar los
códigos ordenados, orden que aquí no
se necesita.
La operación más frecuente es buscar un paquete por su código. Comparación:
Página 2
PARTE C. Análisis Algorítmico y Pruebas de Escritorio
C.1 y C.2. Pilas de llamadas de los métodos recursivos
Se usan los datos del enunciado: peso total hacia Armenia con PQ101 Armenia 4.5, PQ203 Salento 3.0,
PQ415 Armenia 7.2 y PQ730 Armenia 2.3; y conteo con prioridad ≥ 4 sobre 5, 2, 4, 1, 5, 3, 4.
Pregunta
calcularPesoTotalRecursivo
contarPrioridadRecursivo
Caso base
indice >= lista.size() → 0.0
indice >= lista.size() → 0
Caso recursivo
pesoActual + rec(indice + 1)
(prioridad ≥ 4 ? 1 : 0) + rec(indice + 1)
Avance al caso base
El índice sube de 1 en 1
El índice sube de 1 en 1
Parámetros de cada
llamada
Misma lista, "armenia", índice 0...4
Misma lista, mínimo 4, índice 0...7
Llamadas pendientes
Todas las anteriores esperan la suma
Todas las anteriores esperan la suma
Se alcanza el caso base
En la 5.a llamada (índice 4)
En la 8.a llamada (índice 7)
Orden de los retornos
Al revés: 4, 3, 2, 1, 0
Al revés: 7, 6, ... , 0
Valor final
14.0 kg
4 paquetes
Tabla de la pila: peso total
Llamada
Paquete
Peso
Retorna
rec(0)
PQ101 Arm.
4.5
4.5 + 9.5 = 14.0
rec(1)
PQ203 Sal.
0.0
0.0 + 9.5 = 9.5
rec(2)
PQ415 Arm.
7.2
7.2 + 2.3 = 9.5
rec(3)
PQ730 Arm.
2.3
2.3 + 0.0 = 2.3
rec(4)
—
—
caso base: 0.0
Tabla de la pila: conteo por prioridad
Llamada
Prioridad
Suma
Retorna
rec(0)
5
1
1 + 3 = 4
rec(1)
2
0
0 + 3 = 3
rec(2)
4
1
1 + 2 = 3
rec(3)
1
0
0 + 2 = 2
rec(4)
5
1
1 + 1 = 2
rec(5)
3
0
0 + 1 = 1
rec(6)
4
1
1 + 0 = 1
rec(7)
—
—
caso base: 0
C.3. Búsqueda binaria por código
Firma: Paquete busquedaBinariaRecursiva(List<Paquete> lista, String codigo, int
inicio, int fin)
Precondición: la lista tiene que estar ordenada por código. Si se usara la lista de llegada, el algoritmo podría
descartar la mitad donde está el paquete y decir que no existe. Por eso el sistema ordena una copia antes de
buscar. Traza buscando PQ731 en la lista del enunciado: PQ105, PQ214, PQ318, PQ421, PQ567, PQ731,
PQ842, PQ942.
Paso
inicio
fin
medio
Código en medio
Decisión
1
0
7
3
PQ421
PQ421 < PQ731 → descarta la izquierda
2
4
7
5
PQ731
Encontrado en 2 comparaciones (una búsqueda lineal haría 6)
Página 3
Pila de ejecución hacia arriba: calcularPesoTotalRecursivo("Armenia")
Las llamadas se apilan hasta el caso base (rec(i=4)); al desapilar, cada una recibe en verde el resultado de la de arriba, suma su peso y retorna. Main recibe 14.0 kg.
Main
total =
calcular()
Main
total =
calcular()
calcularPeso
res=rec(0)
Main
total =
calcular()
calcularPeso
"Armenia"
res=rec(0)
rec(i=0)
PQ101 Arm.
peso = 4.5
resto=rec(1)
Main
total =
calcular()
calcularPeso
res=rec(0)
rec(i=0)
peso = 4.5
resto=rec(1)
rec(i=1)
PQ203 Sal.
peso = 0.0
resto=rec(2)
Main
total =
calcular()
calcularPeso
res=rec(0)
rec(i=0)
peso = 4.5
resto=rec(1)
rec(i=1)
PQ203 Sal.
peso = 0.0
resto=rec(2)
rec(i=2)
PQ415 Arm.
peso = 7.2
resto=rec(3)
Main
total =
calcular()
calcularPeso
"Armenia"
res=rec(0)
rec(i=0)
PQ101 Arm.
peso = 4.5
resto=rec(1)
rec(i=1)
PQ203 Sal.
peso = 0.0
resto=rec(2)
rec(i=2)
PQ415 Arm.
peso = 7.2
resto=rec(3)
rec(i=3)
PQ730 Arm.
peso = 2.3
resto=rec(4)
Main
total =
calcular()
calcularPeso
"Armenia"
res=rec(0)
rec(i=0)
PQ101 Arm.
peso = 4.5
resto=rec(1)
rec(i=1)
PQ203 Sal.
peso = 0.0
resto=rec(2)
rec(i=2)
PQ415 Arm.
peso = 7.2
resto=rec(3)
rec(i=3)
PQ730 Arm.
peso = 2.3
resto=rec(4)
rec(i=4)
4 ≥ 4: base
return 0.0
Main
total =
calcular()
calcularPeso
"Armenia"
res=rec(0)
rec(i=0)
PQ101 Arm.
peso = 4.5
resto=rec(1)
rec(i=1)
PQ203 Sal.
peso = 0.0
resto=rec(2)
rec(i=2)
PQ415 Arm.
peso = 7.2
resto=rec(3)
rec(i=3)
PQ730 Arm.
peso = 2.3
resto=0.0
return 2.3
Main
total =
calcular()
calcularPeso
res=rec(0)
rec(i=0)
peso = 4.5
resto=rec(1)
rec(i=1)
peso = 0.0
resto=rec(2)
rec(i=2)
PQ415 Arm.
peso = 7.2
resto=2.3
return 9.5
Main
total =
calcular()
calcularPeso
"Armenia"
res=rec(0)
rec(i=0)
PQ101 Arm.
peso = 4.5
resto=rec(1)
rec(i=1)
PQ203 Sal.
peso = 0.0
resto=9.5
return 9.5
Main
total =
calcular()
calcularPeso
"Armenia"
res=rec(0)
rec(i=0)
PQ101 Arm.
peso = 4.5
resto=9.5
return 14.0
Main
total =
calcular()
calcularPeso
"Armenia"
res=14.0
return 14.0
Main
total =
14.0 kg
Página 4
Pila de ejecución hacia arriba: contarPrioridadRecursivo(mínimo 4)
Cada llamada aporta 1 si la prioridad es ≥ 4 y 0 si no. Al llegar a rec(i=7) se retorna 0 y, al replegarse, Main recibe 4 paquetes.
Main
n=contar(4)
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=rec(4)
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=rec(4)
rec(i=4)
prio 5 → 1
resto=rec(5)
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=rec(4)
rec(i=4)
prio 5 → 1
resto=rec(5)
rec(i=5)
prio 3 → 0
resto=rec(6)
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=rec(4)
rec(i=4)
prio 5 → 1
resto=rec(5)
rec(i=5)
prio 3 → 0
resto=rec(6)
rec(i=6)
prio 4 → 1
resto=rec(7)
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=rec(4)
rec(i=4)
prio 5 → 1
resto=rec(5)
rec(i=5)
prio 3 → 0
resto=rec(6)
rec(i=6)
prio 4 → 1
resto=rec(7)
rec(i=7)
7 ≥ 7: base
return 0
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=rec(4)
rec(i=4)
prio 5 → 1
resto=rec(5)
rec(i=5)
prio 3 → 0
resto=rec(6)
rec(i=6)
prio 4 → 1
resto=0
return 1
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=rec(4)
rec(i=4)
prio 5 → 1
resto=rec(5)
rec(i=5)
prio 3 → 0
resto=1
return 1
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=rec(4)
rec(i=4)
prio 5 → 1
resto=1
return 2
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=rec(3)
rec(i=3)
prio 1 → 0
resto=2
return 2
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=rec(2)
rec(i=2)
prio 4 → 1
resto=2
return 3
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=rec(1)
rec(i=1)
prio 2 → 0
resto=3
return 3
Main
n=contar(4)
contarPaq.
min = 4
res=rec(0)
rec(i=0)
prio 5 → 1
resto=3
return 4
n=contar(4)
contarPaq.
min = 4
res=4
return 4
Main
n = 4
Página 5
C.4. Divide y vencerás: paquete de mayor peso
Firma: Paquete mayorPesoDivideYVenceras(List<Paquete> lista, int inicio, int fin).
Pesos del enunciado: 4.5, 12.0, 3.2, 18.7, 7.4, 5.1.
[0..5] medio=2
máx = 18.7
[0..2] medio=1
máx = 12.0
[3..5] medio=4
máx = 18.7
[0..1] medio=0
máx = 12.0
[2] base
3.2
[3..4] medio=3
máx = 18.7
[5] base
5.1
[0] base
4.5
[1] base
12.0
[3] base
18.7
[4] base
7.4
Divide (bajando) / Combina (subiendo con el máximo)
Figura 3. Árbol de subproblemas: se divide bajando y se combina subiendo con el máximo.
Etapa
En el ejemplo
Caso base
inicio == fin: un solo paquete es el más pesado (cajas verdes).
División
medio = inicio + (fin − inicio) / 2 → [0..5] se parte en [0..2] y [3..5].
Subproblema izquierdo
[0..2] = {4.5, 12.0, 3.2} → 12.0
Subproblema derecho
[3..5] = {18.7, 7.4, 5.1} → 18.7
Combinación
Se compara el ganador de cada lado: 12.0 vs 18.7.
Resultado final
18.7 kg
Página 6
Pila de ejecución hacia arriba: mayorPesoDivideYVenceras(0, 5)
Cada bloque es una llamada con su rango [inicio..fin]. Primero se resuelve toda la mitad izquierda (izq) y sus llamadas salen de la pila; solo después se apila la derecha (der). Por
eso la pila nunca pasa de 4 niveles sobre Main, aunque se hacen 11 llamadas. Main recibe 18.7 kg.
Main
res = ?
Main
res = ?
[0..5]
izq = ?
der = ?
Main
res = ?
[0..5]
izq = ?
der = ?
[0..2]
izq = ?
der = ?
Main
res = ?
[0..5]
izq = ?
der = ?
[0..2]
izq = ?
der = ?
[0..1]
izq = ?
der = ?
Main
res = ?
[0..5]
izq = ?
der = ?
[0..2]
izq = ?
der = ?
[0..1]
izq = ?
der = ?
base [0]
peso 4.5
ret 4.5
Main
res = ?
[0..5]
izq = ?
der = ?
[0..2]
izq = ?
der = ?
[0..1]
izq = 4.5
der = ?
Main
res = ?
[0..5]
izq = ?
der = ?
[0..2]
izq = ?
der = ?
[0..1]
izq = 4.5
der = ?
base [1]
peso 12.0
ret 12.0
Main
res = ?
[0..5]
izq = ?
der = ?
[0..2]
izq = ?
der = ?
[0..1]
izq = 4.5
der = 12.0
ret 12.0
Main
res = ?
[0..5]
izq = ?
der = ?
[0..2]
izq = 12.0
der = ?
Main
res = ?
[0..5]
izq = ?
der = ?
[0..2]
izq = 12.0
der = ?
base [2]
peso 3.2
ret 3.2
Main
res = ?
[0..5]
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = ?
der = ?
[3..4]
ret 18.7
Main
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = 18.7
der = ?
Main
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = 18.7
der = ?
base [5]
peso 5.1
ret 5.1
Main
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = 18.7
der = 5.1
ret 18.7
Main
res = ?
[0..5]
izq = 12.0
der = 18.7
ret 18.7
Main
res = 18.7
Página 7
C.5. Pruebas de escritorio de la lista propia y del despacho
Caso
Lista inicial
Operación
Resultado
Qué pasa por dentro
[ ]
eliminar("A")
false
estaVacia() corta antes de tocar nodos.
elemento
[A]
eliminar("A")
true
cabeza = null y cola = null; tamaño 0.
[A → B → C]
eliminar("A")
true
cabeza = cabeza.siguiente
[A → B → C]
eliminar("B")
true
anterior.siguiente = actual.siguiente
[A → B → C]
eliminar("C")
true
Igual que el intermedio y además cola = B.
[A → B → C]
eliminar("Z")
false
Recorre todo sin cambiar nada.
Despacho prioritario con el ejemplo del enunciado (prioridad, tiempo): PQ420 (3, 30), PQ731 (5, 45),
PQ105 (5, 25), PQ942 (4, 20). PQ731 y PQ105 empatan en prioridad y gana PQ105 por menor tiempo; luego
sigue PQ942 por prioridad 4. Orden obtenido: PQ105 → PQ731 → PQ942 → PQ420, igual al esperado.
Lista propia: eliminar / obtener(i)
O(n) / O(i)
O(1)
Hay que avanzar nodo por nodo desde la cabeza.
Lista propia: tamaño / vacía
O(1)
O(1)
Se lleva un contador.
Despachar (poll + remove de la otra
cola)
O(n)
O(1)
poll es O(1) u O(log n), pero quitarlo de la otra cola es O(n).
Registrar paquete
O(log n)
O(1)
¿Por qué no se ordena directamente la lista de llegada para la búsqueda binaria?
Porque se perdería el orden de registro que se usa para auditoría y para la atención FIFO. Se ordena una copia.
¿Por qué el mayor peso es divide y vencerás y el peso total no?
El peso total quita un elemento por llamada. El mayor peso parte el problema en dos mitades independientes,
las resuelve por separado y combina los resultados.
Gemini
Cómo encadenar tres
criterios de desempate
en un Comparator.
Había que invertir la
prioridad (mayores
primero) sin invertir el
orden alfabético del
código.
Probamos en
consola el despacho
con el ejemplo del
enunciado.
Constante
DESPACHO_PRIORITARIO.
B
Gemini
Cómo permitir for-each
en una lista propia
hecha desde cero.
El historial debía
imprimirse desde el
menú sin exponer los
nodos.
Recorrimos el
historial desde el
menú.
Iterable<T> en la interfaz y un
Iterator interno.
Revisar el programa
con datos malos
(tiempo negativo, letras
en el peso, municipios
sin tilde).
Un dato malo borraba
todo lo escrito o
cerraba el programa.
Repetimos las
mismas entradas
malas después del
cambio.
Los lectores repiten solo el
campo inválido y “x” cancela.
B
Claude
Por qué el despacho se
bloqueaba después de
pocos paquetes.
Los repartidores
quedaban ocupados
para siempre.
Despachamos hasta
agotar repartidores y
registramos
entregas.
Separamos despachar de
registrar la entrega (opción 14).
C
Claude
Cómo representar las
pilas de llamadas.
Necesitábamos la
tabla y la gráfica paso
a paso.
Comparamos con la
ejecución hecha a
mano.
Tablas y gráficas de las dos pilas
obligatorias.
D.2. Respuesta cuestionable de IA detectada y corregida
Respuesta original
Problema detectado
Análisis
Solución final
Para la búsqueda binaria,
la IA recomendó aplicar C
ollections.sort(paq
uetesOrdenLlegada)
directamente sobre la
colección principal.
El enunciado exige
conservar el orden exacto
de registro (auditoría y
atención por llegada).
Ordenar la lista principal lo
destruye para siempre.
Restricción incumplida y
comportamiento: la búsqueda
funcionaría, pero los reportes por
orden de llegada y la auditoría
quedarían mal. Es un efecto
secundario que no se ve hasta
que se consulta el orden original.
Ordenar una copia: new ArrayLis
t<>(paquetesOrdenLlegada) y
buscar en ella. Cuesta O(n) de
memoria extra, pero la lista original
queda intacta.
Juan is the student responsible for presenting and defending his assigned portion of the sustentacion-juan project. His role is defined by preparing for and delivering an oral defense.
Goals
Inputs
Decisions
Observable Success
Constraints
Supporting Actors (Systems)
Actor: Juan, estudiante presentador.
Objetivo: justificar por qué el proyecto se divide en las capas modelo, estructuras, servicio y main.
Recorrido:
Repartidor y Paquete.Resultado: Juan puede explicar la razón arquitectónica de la separación y mostrar cómo las capas colaboran sin confundirse entre sí.
Actor: Juan.
Objetivo: explicar con profundidad la función del modelo, especialmente las clases Repartidor y Paquete, y justificar las validaciones realizadas directamente en los constructores.
Recorrido:
Paquete como una clase del modelo que representa la información de un paquete dentro del dominio del proyecto.Repartidor representa al repartidor y sus datos o estado dentro de las operaciones de despacho y entrega.x permite cancelar.Resultado: Juan puede explicar no solo qué representa cada clase, sino también por qué la validez de sus datos debe garantizarse desde su creación.
Actor: Juan, al presentar la ejecución del cálculo.
Objetivo: explicar el funcionamiento de calcularPesoTotalRecursivo("Armenia") y el uso de la pila de llamadas.
Recorrido:
Main solicita el cálculo y recibe el resultado mediante calcular() y calcularPeso.res = rec(0) para los paquetes asociados a "Armenia".rec(i=0), el paquete PQ101 tiene peso 4.5; la función guarda ese peso y continúa con resto = rec(1).rec(i=1), el paquete PQ203 tiene peso 0.0; la función continúa con resto = rec(2).2.3 y se continúa con resto = rec(4).rec(i=4), se cumple la condición 4 ≥ 4, que constituye el caso base. La función retorna 0.0.Main recibe finalmente un total de 14.0 kg.Resultado: se demuestra la diferencia entre la fase de apilamiento, en la que se alcanza el caso base, y la fase de retorno, en la que se suman los pesos.
Actor: Juan.
Objetivo: presentar el procedimiento que divide el rango de datos, resuelve subproblemas y combina sus resultados.
Recorrido:
[0..5] y calcula el punto medio 2.[0..2] y [3..5].[0..2], con valores {4.5, 12.0, 3.2}, obtiene 12.0.[3..5], calcula el punto medio 4 y continúa dividiendo los subrangos necesarios, entre ellos [3..4].12.0 con el resultado derecho y conserva el mayor valor.Resultado: Juan puede explicar la división [0..5], la resolución de [0..2] y [3..5], y la combinación de máximos sin confundir este algoritmo con el cálculo recursivo de pesos.
Actor: Juan.
Objetivo: demostrar cómo se ordenan los paquetes para el despacho.
Recorrido:
PQ420 (3, 30), PQ731 (5, 45), PQ105 (5, 25) y PQ942 (4, 20).PQ731 y PQ105 empatan con prioridad 5.PQ105 tiene 25 y PQ731 tiene 45, por lo que PQ105 se atiende antes.PQ942, con prioridad 4, y finalmente PQ420, con prioridad 3.PQ105 → PQ731 → PQ942 → PQ420, igual al esperado.Resultado: Juan puede explicar tanto la regla principal de prioridad como la regla secundaria usada en los empates.
Actor: Juan, mediante el menú.
Objetivo: explicar cómo se consulta el historial preservando la encapsulación de la estructura.
Recorrido:
Resultado: el historial puede consultarse y mostrarse sin romper la separación entre la interfaz del programa y la implementación de la estructura.
Actor: usuario del programa.
Objetivo: continuar la operación cuando se introduce un dato incorrecto.
Recorrido:
x para cancelarla.Resultado: la captura de datos es más resistente a errores y mantiene la continuidad de la interacción.
Actor: usuario del programa y repartidores representados por el modelo.
Objetivo: explicar la diferencia entre asignar un despacho y registrar posteriormente su entrega.
Recorrido:
14 permite registrar la entrega después del despacho, en lugar de asumir que ambos acontecimientos son la misma acción.Resultado: se representan correctamente tanto la disponibilidad de repartidores como la diferencia entre despachar un paquete y confirmar que fue entregado.
Actor: Juan.
Objetivo: estudiar y defender su parte del proyecto con explicaciones y respuestas preparadas.
Recorrido:
sustentacion-juan.Repartidor, Paquete y las validaciones de los constructores.Resultado: Juan queda preparado para presentar su parte, justificar las decisiones técnicas y responder preguntas sobre el funcionamiento del código.
[Design proposal; unspecified choices are defaults.]
Muse: Adham Dannaway. Headline: QuindíoExpress — Sustentación · Juan. The product is a study/defence surface for one student explaining a layered Java architecture (modelo, estructuras, servicio, main) at Universidad del Quindío. The visual system is dual-nature: an explanation half and a code/evidence half in dialogue.
Mode: light-first with a dark code panel. Palette (light): background #F4F1EA (warm paper), surface #FFFFFF, text/primary #141821 (deep ink), accent #E4572E (burnt orange), muted #6B7280. Code panel (inverted): ground #141821, text #F4F1EA, accent bar #E4572E. No blue anywhere. Contrast: #141821 on #F4F1EA ≈ 15:1; #F4F1EA on #141821 ≈ 15:1; #E4572E on #FFFFFF ≈ 4.6:1 (large text and non-text only); #6B7280 on #F4F1EA ≈ 4.6:1 (body-safe at 16px+).
Typography: headings Space Grotesk (700 titles, 500 split-half labels, tracking −0.02em, sentence case); body IBM Plex Sans; monospace IBM Plex Mono 400/500 for identifiers, complexity annotations and code. Scale 1.333 modular: 56/42/32/24/18/16. Display headline clamp(40px, 8vw, 96px); section headings clamp(28px, 4vw, 42px); sub-headings 24px; body 18px/1.6 (explanation half), 15px/1.7 (code annotations); micro-labels 12px uppercase, 0.08em tracking, IBM Plex Mono. Headings never exceed two lines at 375px; they wrap, never clip.
Shape and spacing: 8-pt spacing scale. Sharp 4px corners on cards and code panels — no pills, no soft blobs. The central split is a 2px vertical rule in #E4572E on desktop, becoming a 2px horizontal rule at ≤768px. Hairline 1px borders in rgba(20,24,33,0.12) separate rows inside model/service tables. Code panels are dark rectangles with a 4px left accent bar in #E4572E. Complexity badges (O(1), O(log m), O(n), O(n log n)) are small monospace rectangles, never pills.
Layout: persistent two-column split on desktop — left 55% explanation on #F4F1EA, right 45% code/evidence on #141821, sharing a baseline grid. Each topic (modelo, estructuras, servicio, main, validaciones en el constructor, Repartidor, Paquete, despacho, recursión) is a spread. A sticky vertical topic index in the left margin is the navigation. At 768px the split stacks (code below explanation); at 375px the index becomes a horizontally scrollable chip row. Every table is a real table with aligned label/value columns, never a grid of identical cards.
Imagery: no stock photography. Imagery is the project itself, generated as inline SVG so it scales at 375px without loss and never covers text: (1) 2px-stroke layer-stack schematics (Main → Servicio → Estructuras → Modelo) with accent arrows; (2) box-and-arrow diagrams for the FIFO ArrayDeque, TreeSet ordering, HashMap bucket lookup, own singly linked list with head/tail, and PriorityQueue heap; (3) call-stack visualisations for calcularPesoTotalRecursivo and contarPrioridadRecursivo as stacked labelled rectangles; (4) a recursion tree for the divide-and-conquer maximum with weights 4.5, 12.0, 3.2, 18.7, 7.4, 5.1 at the leaves and the winner propagating up; (5) a keyboard-shortcut cheat sheet as keycaps.
Readable text and controls stay whole at 375px, 768px and 1280px, wrapping or scaling to fit; imagery and decoration may bleed or overlap but never cover readable text or controls.
[Design proposal; unspecified choices are defaults.]
The split is the pedagogy, not decoration. QuindíoExpress is itself a split — model vs. service, code vs. explanation, dry structure vs. oral defence — so the interface is a full-height 2px #E4572E rule dividing every screen into an explanation half (#F4F1EA) and a code/evidence half (#141821). The dark panel is where the Java fragments live; the light panel is where Juan's spoken explanations live. The two halves are one document.
Signature moves:
#E4572E split rule on every screen, becoming horizontal at ≤768px — the split is the navigation and the pedagogy.#E4572E left border and the whole spread slides to align with it.#E4572E outline around its definition in the dark code panel, and vice versa.#E4572E.Public entry (first accepted page): a full-viewport split, not a centred hero. A single 2px #E4572E vertical rule runs top to bottom, slightly left of centre. Left, on #F4F1EA: a small IBM Plex Mono label 'ESTRUCTURAS DE DATOS · UNIVERSIDAD DEL QUINDÍO · PARCIAL 1', then an oversized Space Grotesk headline in #141821 reading 'QuindíoExpress' at clamp(40px, 8vw, 96px) stacked over three lines ('Quindío', 'Express', 'Sustentación · Juan'), then one sentence of IBM Plex Sans body and one accent-underlined link 'Empezar por las capas ↓'. Right, on #141821: a live-looking Java code panel showing the actual layer skeleton — package declarations for modelo, estructuras, servicio and main — with the four package names in #E4572E and class names in #F4F1EA. Both halves are the same height and share a baseline grid; the vertical rule is the only ornament. No gradient, no blob, no centred stack of headline + subtext + button.
Avoid: centred headline + subtext + blue button hero; gradient blobs; blue or indigo primary/accent (#0057FF, #2563EB, #4F46E5, #6366F1); Inter, Roboto, Arial, Helvetica, Poppins, Lato; grids of identical hover-lift cards; glassmorphism or frosted panels; photographic stock imagery; pill buttons and 16px+ radii (corners stay at 4px); decorative motion (bounce, particles, parallax) or any animation longer than 400ms.
[Design proposal; unspecified choices are defaults.]
Interaction Model: Animated Motion Tempo: restrained Hero Dimensionality: layered_2d
Focal subject: the 2px #E4572E split rule and the two halves it divides — the warm explanation half and the dark Java code panel showing the layer skeleton (modelo, estructuras, servicio, main).
Input → transformation → outcome thesis: as the page loads, the split rule draws from top edge to bottom edge over 400ms with cubic-bezier(0.16, 1, 0.3, 1); the four package names in the code panel then resolve from muted to #E4572E in sequence, and the accent-underlined link 'Empezar por las capas ↓' draws its underline left-to-right. The outcome is a composed first frame: two halves in dialogue, the split as the only ornament, the layer skeleton legible as the product's defining state.
Motion vocabulary: one purposeful reveal per spread; a 400ms accent-bar draw; a 2px #E4572E underline that draws left-to-right; 200ms crossfade on topic switches; 1px #E4572E outline on cross-half hover. No parallax, no bounce, no particles.
Composed first frame: the split rule fully drawn, the headline 'QuindíoExpress' stacked over three lines on #F4F1EA, the code panel on #141821 with the four package names in #E4572E, both halves sharing a baseline grid.
Reduced-motion state: with prefers-reduced-motion, the accent bar and underlines appear instantly, the topic index becomes a plain stacked list, and the first frame is the same composed split with no animation.
Criterio
ArrayList<Paquete>
HashMap<String, Paquete>
Tiempo de búsqueda
O(n): ≈ 250.000 comparaciones en promedio y
500.000 si no existe.
O(1) promedio: 1 o 2 comparaciones.
Memoria adicional
Baja: solo el arreglo de referencias (≈ 2 a 4 MB).
Alta: un nodo por entrada más la tabla (≈ 25 a 30
MB).
Ventaja
Ocupa poco, conserva el orden de llegada y permite
get(i) en O(1).
La búsqueda no se vuelve más lenta cuando la
empresa crece.
Desventaja
Con 10.000 consultas al día serían ≈ 2.500 millones
de comparaciones.
Más memoria, sin orden y depende de un buen
hashCode().
C.6. Análisis de complejidad
Algoritmo / operación
Tiempo
Espacio
Por qué
Peso total y conteo (recursivos)
O(n)
O(n) de pila
Una llamada por paquete; todas quedan en la pila hasta el
caso base.
Búsqueda binaria
O(log n)
O(log n) de pila
Cada llamada parte el rango a la mitad.
Ordenar la copia antes de buscar
O(n log n)
O(n)
Domina el costo de la opción 12.
Divide y vencerás (mayor peso)
O(n)
O(log n) de pila
2n − 1 llamadas, pero la pila solo crece log n.
Lista propia: agregar
O(1)
O(1)
Gracias a la referencia cola.
Lo más caro es insertarlo en la PriorityQueue.
¿Qué pasa con la recursión lineal si llegamos a 500.000 paquetes?
Cada paquete agrega un marco a la pila; con 500.000 se produciría un StackOverflowError. En ese caso
convendría un ciclo o divide y vencerás, cuya pila solo llega a unos 20 niveles.
¿Por qué el historial se recorre con Iterator y no con obtener(i)?
Cada obtener(i) empieza desde la cabeza, así que recorrer con un for costaría O(n2). El Iterator avanza un nodo
por paso: O(n) en total, y además el código externo nunca ve los nodos.
Escogemos HashMap, porque la búsqueda por código es la operación que más se repite y la diferencia por
consulta es de cientos de miles de comparaciones. No perdemos el orden: el HashMap se usa junto con un
ArrayList que guarda el registro cronológico, y los dos apuntan a los mismos objetos.
El sistema guarda referencias de cada Paquete en varias colecciones, cada una escogida por la operación que
más se repite en esa necesidad.
ArrayList
Política FIFO estricta. Con ArrayList,
sacar el primero obliga a correr n−1
elementos: O(n).
Lo que sacrificamos: memoria. El mismo paquete está referenciado desde varias estructuras a cambio de
que cada operación sea rápida. No se duplican los objetos, solo las referencias.
A.2. Tiempo frente a memoria (500.000 paquetes)
der = ?
base [3]
peso 18.7
ret 18.7
Main
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = ?
der = ?
[3..4]
izq = 18.7
der = ?
Main
izq = 18.7
der = ?
base [4]
peso 7.4
ret 7.4
Main
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = ?
der = ?
[3..4]
izq = 18.7
der = 7.4
"Armenia"
"Armenia"
PQ101 Arm.
"Armenia"
PQ101 Arm.
"Armenia"
PQ101 Arm.
PQ203 Sal.
izq = ?
der = ?
[0..2]
izq = 12.0
der = 3.2
ret 12.0
Main
res = ?
[0..5]
izq = 12.0
der = ?
Main
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = ?
der = ?
Main
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = ?
der = ?
[3..4]
izq = ?
der = ?
Main
res = ?
[0..5]
izq = 12.0
der = ?
[3..5]
izq = ?
der = ?
[3..4]
izq = ?
B
Claude
No completed page designs yet.
Completed design pages will appear here when they are ready to preview.
No completed page designs yet.
Completed design pages will appear here when they are ready to preview.
No comments yet. Be the first!