11 - Ejemplo práctico 2: simulador de historial

11.1 Escenario del problema

Queremos recrear el comportamiento de un navegador: visitar URLs, volver atrás y adelante, y registrar el historial sin perder contexto. La solución emplea dos pilas para representar los movimientos de navegación.

11.2 Modelado con pilas

Mantenemos dos estructuras:

  • Pila Back: almacena las páginas visitadas en orden cronológico.
  • Pila Forward: guarda los destinos a los que se puede regresar tras usar "Atrás".

Visitar una nueva URL limpia la pila Forward (como en un navegador real) y apila la URL en Back.

11.3 Operaciones requeridas

  1. Visit: recibe una URL, la apila en Back y vacía Forward.
  2. Back: desapila el tope de Back, lo inserta en Forward y retorna la nueva página actual.
  3. Forward: desapila el tope de Forward, lo apila en Back y retorna la URL correspondiente.
  4. Print: muestra ambas pilas para depurar (top indica la página actual).

11.4 Casos especiales

  • Si Back tiene un solo elemento, no se puede ir más atrás.
  • Si Forward está vacía, la acción "Adelante" no debe modificar el estado.
  • Se puede limitar el tamaño de Back para simular historial acotado.
  • Los comandos deben ignorar URL vacías o repetidas consecutivas (opcional).

11.5 Implementación en Python

Usaremos listas como pilas (métodos append/pop) para mantener Back y Forward. A continuación un prototipo sencillo:

class Historial:
  def __init__(self, home: str):
    self.back = [home]
    self.forward = []
    self.actual = home

  def visitar(self, url: str):
    self.back.append(url)
    self.forward.clear()
    self.actual = url

  def atras(self):
    if len(self.back) <= 1:
      return self.actual
    previo = self.back.pop()
    self.forward.append(previo)
    self.actual = self.back[-1]
    return self.actual

  def adelante(self):
    if not self.forward:
      return self.actual
    siguiente = self.forward.pop()
    self.back.append(siguiente)
    self.actual = siguiente
    return self.actual

  def imprimir(self):
    print(f"Pagina actual: {self.actual}")
    print("BACK:")
    for url in reversed(self.back):
      sufijo = " <- top" if url == self.back[-1] else ""
      print(f"  {url}{sufijo}")
    print("FORWARD:")
    for url in reversed(self.forward):
      sufijo = " <- top" if url == (self.forward[-1] if self.forward else None) else ""
      print(f"  {url}{sufijo}")


if __name__ == "__main__":
  hist = Historial("https://inicio.com")
  hist.visitar("https://noticias.com")
  hist.visitar("https://docs.com")
  hist.atras()
  hist.adelante()
  hist.visitar("https://foros.com")
  hist.imprimir()

El programa permite probar visitas, retrocesos y avances, mostrando cómo se actualizan ambas pilas sin depender de memoria dinámica explícita.

11.6 Relación con entrevistas técnicas

Este ejemplo combina pilas, manejo de cadenas y estructuras auxiliares, todo muy frecuente en preguntas de diseño de sistemas. Extensiones comunes:

  • Persistir el historial en disco.
  • Contar visitas por dominio o categoría.