REVIT ARCHITECTURE (984) – PYTHON – Bucles (68) – Bucle While. De la Conjetura de Collatz a la Automatización en Revit

Objetivos

En este artículo aprenderás a:

  • Usar el bucle while en Python.
  • Traducir un proceso definido verbalmente en un algoritmo real.
  • Aplicar la lógica a un caso concreto dentro de un proyecto open source para Revit.

Escenario: La Conjetura de Collatz

En 1937, el matemático alemán Lothar Collatz formuló una hipótesis aún sin demostrar:

  1. Toma cualquier número natural (mayor que 0).

  2. Si es par, divídelo entre 2.

  3. Si es impar, multiplícalo por 3 y súmale 1.

  4. Repite el proceso hasta llegar al número 1.

Lo interesante es que ningún número probado hasta hoy escapa de la secuencia y todos terminan en 1.

Ejemplo en Python

Vamos a implementar este proceso con un bucle while. El programa pedirá un número al usuario, lo procesará según la regla y mostrará todos los pasos hasta llegar a 1, contando además cuántas iteraciones han sido necesarias.

Ejemplo de ejecución para el número 15:

Explicando cada línea de código:

  • input(...) muestra el mensaje y lee texto del usuario.

  • int(...) convierte ese texto a entero (si el usuario escribe algo no convertible, lanza ValueError).

  • Asigna el valor convertido a la variable c0, que será nuestro número actual en la secuencia.

Inicializa un contador de iteraciones. Empezamos en 0 porque aún no hemos aplicado ninguna regla.

Inicia un bucle while que continuará mientras c0 sea distinto de 1. Cuando  c0  llegue a 1, el bucle termina.

Comprueba si c0 es par.

  • c0 % 2 calcula el resto de dividir c0 entre 2.

  • Si el resto es 0, es par.

Si es par, reemplaza c0 por c0 // 2.

  • // es división entera (redondea hacia abajo). Como c0 es no negativo, equivale a “dividir por 2 y quedarse con el entero”.

Si es impar, aplica la regla de Collatz: 3*c0 + 1. Se actualiza c0 con ese nuevo valor.

Muestra el nuevo valor de c0 tras aplicar la regla. Por eso la salida empieza con el primer valor transformado, no con el inicial.

Incrementa el contador de pasos en 1. Equivale a pasos = pasos + 1.
Cada vuelta del bucle cuenta como una transformación.

Fuera del bucle (es decir, cuando c0 ya es 1), imprime el total de pasos.
print con comas separa con un espacio por defecto, de modo que la salida queda como steps = 17.

Notas útiles y pequeños detalles

  • Entrada 1: si el usuario introduce 1, el while no se ejecuta y steps = 0.

  • Entrada inválida: si escribe algo no numérico o un número negativo/cero, el código tal cual fallará o no tendrá sentido para el problema.

  • Tamaño de números: Python maneja enteros grandes (precisión arbitraria), así que no hay desbordamiento aunque 3*c0+1 crezca mucho.

  • Orden de print y pasos: primero imprimimos el nuevo c0 y luego sumamos 1 al contador. Esto hace que el número de líneas impresas coincida con steps.

También se puede realizar una versión del código con validación mínima  (opcional), que podría ser la siguiente:

De la Matemática al Mundo BIM: Aplicación en Revit

Ahora, llevemos esta idea al proyecto Revit Open Source Converter.

En Revit, un flujo muy común es recorrer elementos del modelo y aplicarles reglas, de forma similar al proceso de Collatz. Por ejemplo:

  • Si el elemento cumple cierta condición (ej. es un muro de hormigón), aplicar una conversión o exportación.

  • Si no cumple, aplicar otra regla (ej. agruparlo, renombrarlo, o excluirlo).

  • Repetir hasta que todos los elementos hayan sido procesados.

El esquema es el mismo que en Collatz: un bucle que va transformando los datos paso a paso.

Ejemplo práctico con Revit (simplificado)

Supongamos que tenemos una lista de elementos de un modelo en formato genérico (open source) y queremos transformarlos a un formato más ligero para exportación.

Posible salida:

Explicación línea a línea

Declaración de la variable elementos: es una lista que contiene tres diccionarios.

  • Cada diccionario representa un elemento del modelo (a modo de ejemplo).

  • Claves: id (entero), tipo (string: «muro», «puerta», «ventana»), material (string).
    En un flujo real con Revit, estos elementos serían objetos del API con parámetros, pero aquí se usan diccionarios para simplificar.

Crea una lista vacía procesados donde guardaremos la versión transformada (resultado del procesamiento/normalización).

Inicializa el índice i en 0. Este índice se usará para recorrer la lista por posición.

Bucle while que itera mientras i sea menor que len(elementos) (la longitud de la lista).

  • len(elementos) devuelve 3 en este ejemplo.

  • La condición garantiza que se acceda a índices válidos: 0, 1 y 2.
    Nota: si la lista cambiara tamaño dentro del bucle, esto podría alterar las iteraciones.

Se asigna a elem el diccionario que está en la posición i de la lista.

  • elem es una referencia al diccionario original; si se mutara elem cambiaría el elemento en la lista.

Comprueba si el valor asociado a la clave "tipo" es exactamente la cadena "muro".

  • Si la clave "tipo" no existiera, esto lanzaría un KeyError. En código más robusto usaríamos elem.get("tipo").

Si el elemento es un muro: crea un nuevo diccionario nuevo con tres claves:

  • id: copia el id original.

  • categoria: se normaliza a "Wall" (convención inglesa que tal vez sea la requerida al exportar).

  • export: booleano True indicando que este tipo debe incluirse en la exportación.
    Este nuevo es independiente del diccionario original (no se modifica el original).

Para cualquier otro tipo (puerta, ventana, etc.):

  • categoria se construye a partir de elem["tipo"].capitalize(), que pone la primera letra en mayúscula (por ejemplo «puerta» → «Puerta»).

  • export se pone a False (no exportar por defecto).
    Es un comportamiento sencillo; en producción probablemente querrás reglas más precisas.

Añade el diccionario nuevo a la lista procesados. Así vamos acumulando el resultado del procesamiento.

Incrementa el índice i en 1. Equivalente a i = i + 1. Esto permite avanzar al siguiente elemento en la siguiente iteración del while.

Imprime por pantalla la lista completa procesados. Python mostrará la representación literal de la lista de diccionarios.

Conclusión

Lo que hemos visto es un patrón de programación universal:

  • En la Conjetura de Collatz: números que siguen reglas hasta llegar a 1.

  • En un proyecto BIM Open Source: elementos de un modelo que siguen reglas hasta transformarse en datos exportables.

En ambos casos, Python y los bucles while nos permiten convertir procesos verbales en instrucciones repetitivas y sistemáticas, lo que abre la puerta a la automatización.

Notas prácticas y mejoras

Forma más idiomática en Python
Es más claro usar un for en vez de manejar índices manualmente:

Evitar KeyError usando .get()
Si no estás 100% seguro de que las claves existen:

Usar un mapa de conversión (más escalable que if/else)
Si tienes muchas reglas de tipo → categoría/flag, usa un diccionario de mapeo:

Ventaja: centralizas reglas y es fácil añadir o cambiar mapeos.

En contexto Revit real

  • Los elementos llegarían desde el API (por ejemplo FilteredElementCollector) y no como diccionarios.

  • Para leer parámetros usarías métodos del API (ej. elem.GetParameters("Material") o elem.LookupParameter("Material").AsString()).

  • El id sería elem.Id.IntegerValue o similar según la API.

  • En lugar de print, en un add-in usarías logs o escribirías a un archivo/JSON para la exportación.

Inmutabilidad
Crear nuevo evita tocar el diccionario original. En pipelines de conversión esto es buena práctica para auditar cambios.

Testing y trazabilidad
Añadir logging en vez de print y tests unitarios que verifiquen que el mapeo produce lo esperado.

En el próximo artículo exploraremos cómo refinar este código usando funciones en Python para que sea aún más reutilizable dentro del flujo de trabajo de un Revit Open Source Converter.

Licencia Creative Commons@Yolanda Muriel Attribution-NonCommercial-NoDerivs 3.0 Unported (CC BY-NC-ND 3.0)

Deja un comentario