Goal
By the end of this lab you have a small truth-table engine in truth.py: give it any formula as a Python function and it prints the table, tells you whether the formula is a tautology, contradiction or contingency, and checks whether two formulas are equivalent. It is the playground on the week 2 page, rebuilt by you.
Steps
Make your own private copy
⏱ 2 min- Sign in to github.com. No account yet? Create one first (2 minutes).
- Click the orange Create your copy button at the top of this page. It opens GitHub’s “Create a new repository” form, already set to the Lab 1 template.
- Fill in the form exactly like this:
| Field | Value |
|---|---|
| Owner | your own username |
| Repository name | dm-2026-lab01 (exactly this; the grader looks for this name) |
| Visibility | Private |
- Click Create repository. You now have
your-username/dm-2026-lab01.
Write your name in the README
⏱ 1 minStill on the repository page, open README.md, click the pencil icon ✎ and fill in the two lines:
- Name: Ada Lovelace
- Student ID: 23xxxxxxxClick Commit changes… and then Commit changes. This is how your GitHub username is matched to you in the grade list.
Open it in Codespaces
⏱ 2–3 min the first timeOn your repository page:
- Click the green Code button.
- Choose the Codespaces tab.
- Click Create codespace on main.
A VS Code editor opens in your browser. The first start takes a minute or two while Python and the tests are installed; watch the terminal at the bottom until it is ready.
Look around and run the checks once
⏱ 3 minIn the file explorer on the left you see:
| File | What it is |
|---|---|
truth.py | your work: every function marked TODO |
lab01.ipynb | playground notebook, not graded |
check.py | the friendly test runner |
tests/ | the tests the autograder runs (do not edit) |
In the terminal, run the checks before writing any code:
$ python check.py:| implies(p, q) matches the truth table of p → q
not implemented yet (still raises NotImplementedError)
...
0/21 checks passed Every check shows :| because nothing is implemented yet. Your job is to turn them all into :).
Part A: the connectives
⏱ 10 minOpen truth.py. Python has not, and and or. Write implies, iff and xor. Replace each raise NotImplementedError with a return statement.
Use the lecture: is false only when is true and is false, so it equals . For booleans, is “same value” and is “different value”.
$ python check.py:) implies(p, q) matches the truth table of p → q
:) iff(p, q) matches the truth table of p ↔ q
:) xor(p, q) matches the truth table of p ⊕ q Part B: every row
⏱ 10 minrows(n) returns every assignment of n variables as a list of tuples, True before False, the last variable changing fastest. For two variables:
rows(2) == [(True, True), (True, False), (False, True), (False, False)]itertools.product (already imported) does exactly this. Try it in the terminal first:
$ python -c "from itertools import product; print(list(product([True, False], repeat=2)))" Watch out: product returns an iterator, and the function must return a list. And what should rows(0) be? One row with no variables, [()]. Check that product agrees.
Part C: tables and verdicts
⏱ 20 minA formula is a Python function. For example lambda p, q: implies(p, q) takes two booleans and returns one. To evaluate it on a row (a tuple), unpack the tuple: f(*row).
Write, in this order, reusing each function in the next:
truth_table(f, n): a list of(row, f(*row))pairs, for every row ofrows(n).is_tautology: true in every row. Python’sall()is ∀.is_satisfiable: true in at least one row. Python’sany()is ∃. (You will meet ∀ and ∃ again in week 4.)is_contradiction: true in no row.equivalent(f, g, n): same value in every row.count_true(f, n): how many rows are true.
Part D: pretty printing
⏱ 10 minformat_table(f, names, label) returns the table as one string. The format must match exactly, because the autograder compares strings:
p q | p∧q
1 1 | 1
1 0 | 0
0 1 | 0
0 0 | 0Values separated by one space, the result after " | ", lines joined with "\n", no trailing newline. Tips: " ".join(...), and "1" if v else "0".
Then run the demo at the bottom of the file:
$ python truth.pyp q | p→q
1 1 | 1
1 0 | 0
0 1 | 1
0 0 | 1
(p → q) ↔ (¬q → ¬p) is a tautology: True
(p → q) ↔ (q → p) is a tautology: False You just proved, by exhaustion, that the contrapositive is equivalent and the converse is not.
Part E: English to Python
⏱ 10 minLet : “the server is overloaded”, : “the request is served from cache”, : “the response is slow”. Translate each sentence into a Python expression over p, q, r. You may use your own implies.
spec1: The response is slow only if the server is overloaded and the request is not served from cache.spec2: The request is served from cache unless the server is overloaded.spec3: Neither is the server overloaded nor is the response slow.
These are the translation exercises from the lecture. If a check fails, look at the week 2 notes on “only if” and “unless”.
Submit
⏱ 1 minSubmitting = pushing your work to GitHub. Type these three lines in the terminal:
$ git add -A$ git commit -m "Lab 1"$ git push Prefer buttons? Use the Source Control icon on the left of VS Code: type a message, click Commit, then Sync Changes.
Then check that it arrived:
- Open your repository on github.com. Your latest commit message (“Lab 1”) is shown at the top of the file list.
- Next to it, after about a minute, a ✅ (all checks passed) or ❌ (some failed) appears. Click it, then Details, to see the same
:)/:(list aspython check.py.
How to submit
Good to know:
- What is graded. After the deadline the instructor runs the official tests on your last push, so changing the files in
tests/does not change your grade.python check.pyshows you exactly what the grader will see. - Late work. Pushes up to five days late are graded with 10% off per day, as in the syllabus. After that, nothing is accepted.
- Time stamps. The deadline is checked against the time GitHub received your push, not the clock on your computer.
- Working with others. Discuss ideas, not code. Every line you submit must be yours, and you must be able to explain it.
Explore: the notebook
lab01.ipynb is not graded. It shows why truth tables explode ( rows), counts how many different truth tables exist, and plays with logic on bits. Open it in your codespace (pick the Python kernel when asked) or in Colab with the button below.
Lab 1 · Explore notebook
Read it here, run it in Colab or in your cs50.dev workspace.
Challenges (optional, not graded)
- Parser. Write
parse("(p -> q) & ~p")that turns a string into a Python function, so your engine works on typed formulas like the playground on the week page. - Minimal formula. For a given table, output a formula that produces it (hint: one
and-term per true row, joined withor, called the disjunctive normal form). - Bits. Write
bit_and(a, b),bit_or,bit_xorfor bit strings of equal length like"0110"without using&,|,^.