Skip to main content
  1. Digital Odyssey/

LifeClock (Part 1/2): From Memento Mori to Python

·1697 words·8 min·
Digital Odyssey CS50 Python Philosophy Memento-Mori Stoicism CLI Testing Personal-Project
Simon Bernbeck
Author
Simon Bernbeck
German-born AI Engineering student at International University, documenting my unconventional journey from non-CS background to AI practitioner. Currently navigating the path to becoming a digital nomad in Brazil, specifically Rio de Janeiro. Sharing learnings, travel experiences, and philosophical reflections along the way.
Table of contents
LifeClock - This article is part of a series.
Part : This article

LifeClock (Part 1/2): From Memento Mori to Python
#

Have you ever seen your entire life laid out on a single sheet of paper? In his article “Your Life in Weeks,” Tim Urban presents a starkly powerful image: a grid of tiny boxes, one for each week of a 90-year life. Staring at this grid, you realize that your life isn’t an abstract, endless expanse. It’s finite, fully countable, and surprisingly short when visualized this way.

This single image inspired me to turn a profound philosophical concept into a tangible, personal artifact for my CS50 Python final project. The result is “LifeClock,” a command-line tool that generates a personalized “Your Life in Weeks” poster. This post will walk through the most impactful takeaways from building it, from ancient philosophy to modern Python. This isn’t just about writing code; it’s about using code as a lens to examine one’s own life.

LifeClock series: This is Part 1/2. Next up: LifeClock (Part 2/2): Refactoring to Clean Architecture.

LifeClock poster: life visualized as a grid of weeks

Each square = one week. Dark brown = past, red = current, tan = future, purple = birthdays.

The Spark: An Idea Worth Coding
#

The inspiration for LifeClock was twofold. First was the concept from Tim Urban’s article, which describes our weeks as a “tiny handful” of “precious” gems that are “fully countable.” When you compress a 90-year life into a single image, the weeks become tangible—roughly the volume of a tablespoon of diamonds. Suddenly, the question “Are you making the most of your weeks?” hits differently.

Second, this modern visual tool connects directly to the ancient Stoic practice of Memento Mori, a Latin phrase meaning “remember you will die.” The practice is not meant to be depressing. Instead, it is a tool to create priority, meaning, and urgency, encouraging us to treat our time as a gift and not waste it on the trivial. As the philosopher Marcus Aurelius wrote:

“You could leave life right now. Let that determine what you do and say and think.”

The project became an exercise in using code to create a modern vanitas—a symbolic work of art that serves as a personal reminder of life’s fleeting nature.

The Blueprint: Structuring Philosophy into Functions
#

Translating a philosophical idea into a logical code structure was the first technical challenge. Just as Stoicism asks us to separate what we can control from what we can’t, good software design asks us to separate a program’s responsibilities. To keep the project clean and manageable, I adopted a two-file functional architecture based on the principle of Separation of Concerns. The logic for user interaction lives in helpers.py, distinct from the unchangeable mathematics of a lifetime in project.py.

The two files are:

lifeclock/
├── project.py        # Core logic: compute_expectancy, life_stats, render_weeks_poster
├── helpers.py        # User interaction and validation utilities
├── test_project.py   # 25 comprehensive tests (100% coverage)
└── requirements.txt  # pillow, pytest

The core functions handle distinct responsibilities:

  • compute_expectancy(): Calculates life expectancy based on lifestyle factors
  • life_stats(): Determines where you are on the timeline
  • render_weeks_poster(): Transforms data into visual art

This separation wasn’t just about files; it extended to the functions themselves. Using features like keyword-only arguments made the code self-documenting and less prone to errors, reinforcing the goal of creating a clear and robust tool for reflection.

The Engine: The Mathematics of a Lifetime
#

The heart of the LifeClock application is the compute_expectancy() function. This is where abstract lifestyle choices are quantified and translated into a concrete number: your estimated life expectancy in years. The algorithm begins with a baseline expectancy and then applies a series of deltas, or adjustments, based on four key lifestyle factors.

The model is surprisingly nuanced:

  • Activity: High activity adds 2.0 years, while a low activity level subtracts 2.0 years
  • Smoking: A heavy smoking habit subtracts a significant 8.0 years
  • Sleep: Getting less than 6 hours of sleep subtracts 1.0 year, while optimal sleep (6-9 hours) adds a modest half-year
  • BMI: A healthy BMI (18.5-25) adds 0.5 years, while an obese one (≥30) subtracts 3.0 years

After all deltas are applied, the final calculated expectancy is clamped to a range between 40 and 120 years. This ensures the final output remains within a realistic human lifespan.

# Simplified example of lifestyle adjustments
delta = 0.0
if activity == "high": delta += 2.0
if smoking == "heavy": delta -= 8.0
if sleep_hours < 6: delta -= 1.0
# ... (BMI calculations)
adjusted = baseline + delta
return max(40, min(120, adjusted))  # Clamp to realistic range

This model demonstrates how small daily choices—an hour of exercise, seven hours of sleep, a cigarette avoided—compound into years of life expectancy.

The Surprise: The Counter-intuitive Drift of a Birthday
#

One of the most surprising discoveries during development was a visual quirk in the final poster: the purple squares marking birthdays do not fall in the same week-column every year. Instead, they drift diagonally across the grid over time, creating a subtle “staircase” pattern.

The reason for this “drift” is simple mathematics:

  • A regular year has 365 days, which is exactly 52 weeks plus 1 extra day
  • A leap year has 366 days, which is 52 weeks plus 2 extra days

These extra days accumulate year after year. Approximately every 5-6 years, the accumulated offsets add up to a full week, causing the birthday square to shift over to the next column. This creates a visible “staircase” pattern on the poster. This required a specific helper function, safe_birthday(), to handle the logic of mapping a February 29th birthday to February 28th in non-leap years—a perfect example of a philosophical observation creating a concrete coding challenge.

Bringing It to Life: Visual Implementation
#

The poster generation uses Python’s Pillow (PIL) library to transform calculated data into visual art. The grid layout is carefully designed:

  • 52 columns representing weeks per year
  • 16×16 pixel cells for clarity without overwhelming detail
  • Color-coded squares: Dark brown for past weeks, bright red for your current week, light tan for future weeks, and purple highlighting birthdays throughout your timeline
  • Right-aligned statistics panel showing your life metrics at a glance

The rendering logic iterates through each week of your calculated lifespan, assigning colors based on whether that week is in your past, present, or future. Birthday weeks get special purple highlighting.

# Color each week based on time position
for week_index in range(total_weeks):
    if week_index in birthday_weeks:
        color = purple
    elif week_index < current_week:
        color = dark_brown
    elif week_index == current_week:
        color = red
    else:
        color = tan
    draw.rectangle([x0, y0, x1, y1], fill=color)

The rendering logic includes smart fallbacks—it tries to use your system’s Arial font but gracefully falls back to Pillow defaults for cross-platform compatibility. The result is a personalized PNG poster that serves as both data visualization and philosophical artifact.

The Proof: Building with Confidence via Testing
#

A key requirement of the CS50 project was to write tests for our code, and this proved to be one of the most valuable parts of the development process. The project includes a comprehensive test suite in test_project.py with a total of 25 tests. These tests cover the core functions in project.py, ensuring every piece of the application works as intended. They verify:

  • Calculation Accuracy: Confirming the life expectancy deltas and life statistics are computed correctly
  • Boundary Conditions: Checking that the clamping mechanism for life expectancy works at its minimum (40) and maximum (120) limits
  • Edge Cases: Testing tricky edge cases, like ensuring a person born on February 29th still has their birthday correctly plotted in common years, to prevent the logic from failing on uncommon inputs

Using the pytest framework to implement a Test-Driven Development (TDD) approach provided immense confidence. With 100% test coverage of the core logic, I could modify or refactor the complex calculation and rendering engines, knowing that the test suite would immediately catch any regressions.

The CS50 Journey
#

This project was built for Harvard’s CS50 Introduction to Programming with Python, an intensive course that teaches programming fundamentals through practical projects. The final project requirements demanded originality, comprehensive testing, and a video demonstration explaining the implementation.

LifeClock exceeded these requirements by combining technical depth with philosophical meaning. It’s not just a functional tool—it’s a conversation starter about mortality, time, and how we choose to spend our finite weeks.

See It in Action
#

Watch the full demonstration of LifeClock in action, from command-line prompts to final poster generation:

The video walks through the interactive prompts, lifestyle factor calculations, and the surprising moment when your life appears as a grid of colored squares—each one representing a week you’ve lived or have yet to experience.

Explore the Project Yourself
#

For those who want to dive deeper into the code or run the application themselves, here are the project resources:

  • GitHub Repository: Sims2k/LifeClock
  • Video Demo: YouTube
  • Required Libraries: To run the project, you will need pillow for image generation and pytest for running the test suite

To run the project:

cd lifeclock
pip install -r requirements.txt
python project.py

The tool will guide you through a series of prompts about your birthdate and lifestyle factors, then generate your personalized poster.

Additional Resources:

Your Turn to Fill the Weeks
#

This project was a journey from the profound ideas of Tim Urban and ancient Stoic philosophers to a functional Python application. It demonstrates how coding can be a powerful medium for exploring and interacting with abstract concepts about our own lives. The final poster is more than just an image; it’s a personalized tool for reflection.

Tim Urban calculated that all 4,680 weeks of a 90-year life equal roughly a tablespoon of diamonds. The grid of boxes—some filled, some empty—is ours to use wisely. This project was my way of filling a few of them, not just with code, but with meaning.

The Stoics were right: remembering that we will die doesn’t make us morbid. It makes us intentional. What will you build with your remaining diamonds?


This article is part of my Digital Odyssey series, where I document technical projects that bridge philosophy, productivity, and personal growth. LifeClock was my CS50 Python final project, completed in 2024.

LifeClock - This article is part of a series.
Part : This article

Related articles

LifeClock (Part 2/2): Refactoring to Clean Architecture
·7184 words·34 min
Digital Odyssey Clean-Architecture Python Refactoring Software-Design LifeClock Testing Architecture
Running Your Own Local WebDAV Server for Zotero (Windows 11)
·1360 words·7 min
Digital Odyssey Zotero WebDAV Docker Windows-11 Research-Tools Self-Hosting Guide Knowledge-Management