Skip to content
CCC Python Course

Lookup tables

Module
M3.5
Lesson
1 of 1
Reading time
4 min

In this lesson

  • Use a list or dictionary to map inputs to outputs.
  • Build a lookup table from problem data and query it quickly.
  • Avoid repeated computation by storing results in a lookup table.

Many problems have fixed data that you need to reference many times. Instead of computing the same result over and over, store it once in a lookup table and retrieve it as needed. A lookup table is a data structure that maps keys to values.

Lists as lookup tables

A list is an ordered collection. You can use the index as the key and the value at that index as the output.

Suppose you need the number of days in each month. Instead of writing if statements, store the numbers in a list:

Python
days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

The index 0 holds a placeholder (you do not count month 0). Index 1 holds 31 (January), index 2 holds 28 (February), and so on.

To look up the days in month 2, you just write:

Python
days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]month = 2print(days_in_month[month])

This prints 28. Indexing is very fast, even for long lists.

examples/month_days.py
days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
month = int(input())print(days_in_month[month])

Input

2

Output

28
Looking up the days in a month by index

The table above always gives February 28 days, which is wrong in a leap year. A lookup table stores fixed data, but a leap year is not fixed, so this is a case where the table needs one small adjustment rather than a bigger structure. Look up the value first, then correct it for the one case that depends on something outside the table. A year is a leap year when it divides evenly by 4, unless it also divides evenly by 100, in which case it needs to divide evenly by 400 as well:

Python
days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]year = 2024month = 2days = days_in_month[month]is_leap = year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)if month == 2 and is_leap:    days = 29print(days)

The lookup table still does most of the work. Only February needs the extra check, and only in a leap year, so the table handles eleven months on its own and this one small rule covers the twelfth.

Dictionaries as lookup tables

When the keys are not sequential numbers, use a dictionary instead of a list. A dictionary maps any key (like a string) to a value.

Python
grades = {"A": 90, "B": 80, "C": 70, "D": 60, "F": 0}letter = "B"print(grades[letter])

This prints 80. The key is "B", and the value is 80.

You can also build a dictionary from input:

Python
n = int(input())phone_numbers = {}
for i in range(n):    name, number = input().split()    phone_numbers[name] = number
query = input()print(phone_numbers[query])

This reads n pairs of name and phone number, stores them in a dictionary, and then looks up a query name. Building the table from input works the same way whether the source is a fixed list in your code or lines the judge gives you at runtime.

When to use a lookup table

Reach for a lookup table in three situations. The same query repeats many times. Computing the answer takes real effort, but retrieving a stored value is instantaneous. Or the underlying data is fixed, or changes rarely enough that building the table once is worth it.

A problem that says "you will be given 10,000 queries, each asking whether a number is prime" is a direct signal. Compute primality once for every number up to the maximum you will be asked about. Store the results, and each of the 10,000 queries becomes a single lookup instead of a fresh computation.

Without a lookup table, you would recompute primality for every query. Checking divisibility from scratch ten thousand times, once per query, costs far more than computing it once for every number up to the limit and reusing the answers.

Building a lookup table

You can build a lookup table by looping through the data and populating the structure:

Python
is_vowel = {}for char in "aeiouAEIOU":    is_vowel[char] = True
def check(char):    return is_vowel.get(char, False)
print(check("a"))

This creates a dictionary where every vowel maps to True. The .get() method returns the value if the key exists, or a default value (False) if it does not. This is safer than using is_vowel[char] directly, which would crash if the key is missing. The same pattern works for any yes-or-no lookup. Build a set or dictionary of everything that counts as "yes". Treat anything absent from it as "no", using the default in .get() to make that explicit.

Lookup tables and arrays

You can also use a multi-dimensional lookup table by nesting lists or dictionaries. For example, a 3x3 multiplication table:

Python
mult_table = [[1, 2, 3], [2, 4, 6], [3, 6, 9]]print(mult_table[2][1])

This prints 6 (row 2, column 1, where both rows and columns start counting from 0, the same convention as a plain list).

Common mistakes

The first is building the table too late. Build the entire lookup table before you start answering queries, not one entry at a time as queries arrive. Filling it in on the fly defeats the purpose, since a query for a value you have not built yet forces you back into computing it directly.

The second is confusing keys and values. The key is what you look up with; the value is what comes back. In is_vowel["a"], "a" is the key you search with, and True is the value stored under it.

The third is accessing a missing key directly. Writing dict[key] crashes with a KeyError the moment key is not present. Use .get(key, default) whenever a query might ask about something the table never stored.

The fourth is relying on dictionary order for correctness. Python 3.7 and later preserve insertion order, but a lookup table's job is answering queries by key, not by position. If a problem needs a specific order, sort the keys explicitly rather than assuming the dictionary already holds them that way.

Practice

Try these on the judges. Each link opens the problem on WMOJ or DMOJ.

  1. 2016 J4
    Arrival Time (opens on DMOJ in a new tab) DMOJ

    Look up an arrival time using a rule that changes across the day.

    Why DMOJ: A lookup-driven simulation, matching this lesson's table-first approach.

  2. 2024 S1
    Hat Circle (opens on WMOJ in a new tab) WMOJ

    Compare values at paired positions around a circular arrangement.

  3. 2023 J2
    Chili Peppers (opens on WMOJ in a new tab) WMOJ

    Look up a value for each item using a fixed table of entries.