Discrete Mathematics YMT211 · Fall 2026 Assoc. Prof. Ferhat Uçar

>_ Lab 1 · Week 2 · Monday, September 28, 2026

Truth-Table Engine

Write the connectives in Python, generate every row of a truth table, and build a tool that decides tautologies, contradictions and equivalences.

week
2 · Mon, Sep 28
due
Fri, Oct 2 · 23:59
assignment
lab01
points
10 (autograded)
time
75 min + finish at home
files you edit
truth.py

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

1

Make your own private copy

⏱ 2 min
  1. Sign in to github.com. No account yet? Create one first (2 minutes).
  2. 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.
  3. Fill in the form exactly like this:
FieldValue
Owneryour own username
Repository namedm-2026-lab01 (exactly this; the grader looks for this name)
VisibilityPrivate
  1. Click Create repository. You now have your-username/dm-2026-lab01.
2

Share it with the instructor

⏱ 1 min

In your new repository:

  1. Click Settings (top right of the repository page), then Collaborators in the left menu.
  2. Click Add people, type drferhatu, choose drferhatu and click Add to repository.

The instructor can only grade repositories shared with him. Your repository stays private: nobody else can see it.

3

Write your name in the README

⏱ 1 min

Still on the repository page, open README.md, click the pencil icon ✎ and fill in the two lines:

- Name: Ada Lovelace
- Student ID: 23xxxxxxx

Click Commit changes… and then Commit changes. This is how your GitHub username is matched to you in the grade list.

4

Open it in Codespaces

⏱ 2–3 min the first time

On your repository page:

  1. Click the green Code button.
  2. Choose the Codespaces tab.
  3. 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.

5

Look around and run the checks once

⏱ 3 min

In the file explorer on the left you see:

FileWhat it is
truth.pyyour work: every function marked TODO
lab01.ipynbplayground notebook, not graded
check.pythe friendly test runner
tests/the tests the autograder runs (do not edit)

In the terminal, run the checks before writing any code:

>_ terminal
$ 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 :).

6

Part A: the connectives

⏱ 10 min

Open truth.py. Python has not, and and or. Write implies, iff and xor. Replace each raise NotImplementedError with a return statement.

Use the lecture: p→qp \to q is false only when pp is true and qq is false, so it equals ¬p∨q\neg p \lor q. For booleans, p↔qp \leftrightarrow q is “same value” and p⊕qp \oplus q is “different value”.

>_ terminal
$ 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
7

Part B: every row

⏱ 10 min

rows(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:

>_ terminal
$ 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.

8

Part C: tables and verdicts

⏱ 20 min

A 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:

  1. truth_table(f, n): a list of (row, f(*row)) pairs, for every row of rows(n).
  2. is_tautology: true in every row. Python’s all() is ∀.
  3. is_satisfiable: true in at least one row. Python’s any() is ∃. (You will meet ∀ and ∃ again in week 4.)
  4. is_contradiction: true in no row.
  5. equivalent(f, g, n): same value in every row.
  6. count_true(f, n): how many rows are true.
9

Part D: pretty printing

⏱ 10 min

format_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 | 0

Values 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:

>_ terminal
$ 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.

10

Part E: English to Python

⏱ 10 min

Let pp: “the server is overloaded”, qq: “the request is served from cache”, rr: “the response is slow”. Translate each sentence into a Python expression over p, q, r. You may use your own implies.

  1. spec1: The response is slow only if the server is overloaded and the request is not served from cache.
  2. spec2: The request is served from cache unless the server is overloaded.
  3. 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”.

11

Submit

⏱ 1 min

Submitting = pushing your work to GitHub. Type these three lines in the terminal:

>_ 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:

  1. Open your repository on github.com. Your latest commit message (“Lab 1”) is shown at the top of the file list.
  2. Next to it, after about a minute, a ✅ (all checks passed) or ❌ (some failed) appears. Click it, then Details, to see the same :) / :( list as python 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.py shows 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 (2n2^n 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)

  1. 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.
  2. Minimal formula. For a given table, output a formula that produces it (hint: one and-term per true row, joined with or, called the disjunctive normal form).
  3. Bits. Write bit_and(a, b), bit_or, bit_xor for bit strings of equal length like "0110" without using &, |, ^.

Troubleshooting