Eleven Plates

A night almanacA day almanac of CS50x · Anno MMXXV

Eleven Plates from bits to browsers

The lecture notes and problem sets Kamalraaj Senthilkumar kept while taking Harvard's CS50x in 2025, engraved as eleven plates. His programs run on the page.

Plate 0, page 1 · One byte is eight bits · switch the lamps

Plate 0, page 3, in bytes:
Eleven weeks · 214 pages of notes · seven programs in C and one in Python Turn to the contents

Plate 0 Week 0 4 pages

Plate 0: Scratch

Where a light bulb becomes a bit.

Four pages to begin. Unary, then binary: one byte is eight bits, the place values run 128 down to 1, and the lecture spells 01000001, with “bit” and “Byte” written over the stills in yellow. Then ASCII (65 is A, 97 is a), the three lines of a phone-book search and its thirteen lines of pseudocode, and 72, 73, 33 in red, green and blue boxes.

Specimen 0·a An illustration of the week's idea

The phone book, halved

Lecture 0’s phone book, run as the thirteen lines on page 3 of the notes. Each tear throws away half of what is left, so a thousand pages need about ten tears, and four billion need thirty-two.

  1. Pick up phone book
  2. Open to middle of phone book
  3. Look at page
  4. If person is on page
  5.     Call person
  6. Else if person is earlier in book
  7.     Open to middle of left half of book
  8.     Go back to line 3
  9. Else if person is later in book
  10.     Open to middle of right half of book
  11.     Go back to line 3
  12. Else
  13.     Quit

Looking for Senthilkumar, on page 810.

Pages 1 to 1,024 in hand. No tears yet.

One page at a time
1,024 pages, at worst
Two at a time
512 turns
Halving
10 tears

Plate I Week 1 43 pages

Plate I: C

Semicolons, loops, and a staircase of hashes.

The notebook first repeats Week 0’s four pages; C begins on page 5, with source code, machine code and make hello. His own agree.c goes from a buggy first try to “Agreed.”, an if / else-if is drawn as a flowchart by hand, a doubling dollar overflows its integer, and on page 23 his mario.c prints a four-row staircase, flush left. CS50’s shorts fill the rest: types, operators, Boolean logic, loops, the Linux command line and magic numbers.

Specimen I·a His program, ported line for line

Hello, me

The first program in the folder, with Kamal's own prompt. Answer it.

./hello
what is your name?Kamal
hello, Kamal

His prompt stops at the question mark with no space, so the answer runs straight on: what is your name?Kamal.

Source Hello me.c 9 lines

Verbatim from PS - 01/Hello me.c.

Specimen I·b His program, ported line for line

Mario, less

The course asked for a pyramid pushed against the right edge. Kamal's prints row i with i + 1 hashes and no padding, so his staircase climbs from the left. Set a height.

Try 0, −3 or a word: his do … while (height < 1) simply asks again. Up to 40 are drawn.

./mario
what is the height of the pyramid?8
#
##
###
####
#####
######
#######
########

No upper bound: the specification's pyramid stopped at 8, his loop only refuses heights below 1, so 9, 20 or 40 print happily.

No leading spaces: the rows are flush left, the mirror image of the specification's right-aligned pyramid.

Source mario less.c 30 lines

Verbatim from PS - 01/mario less.c.

Specimen I·c His program, ported line for line

Credit

His program walks the number with two loops: one doubles every other digit from the second-to-last, the other adds the digits in between. A total ending in 0 passes Luhn's test; then the first two digits name the card. Nothing typed here leaves the page.

CS50's test numbers:
Edges of his logic:
  1. 3as is3
  2. 7×2 141+45
  3. 8as is8
  4. 2×2 44
  5. 8as is8
  6. 2×2 44
  7. 2as is2
  8. 4×2 88
  9. 6as is6
  10. 3×2 66
  11. 1as is1
  12. 0×2 00
  13. 0as is0
  14. 0×2 00
  15. 5as is5
checksum_1 doubled digits, their digits added
27
checksum_2 the digits in between
33
total last digit must be 0
60
first two digits
37
AMEX

It starts 37 and the total 60 ends in 0: AMEX.

./credit
Insert C/C number: 378282246310005
AMEX

VISA means 40 or 41 to his code, not any 4. CS50's own 13-digit test VISA, 4222222222222, prints INVALID.

No length per brand: any 13 to 17 digits pass the length check, so a 16-digit number starting 34 that satisfies Luhn prints AMEX.

His loops stop at the 16th digit, so in a 17-digit number the first digit is never added.

Source credit.c 87 lines

Verbatim from PS - 01/credit.c.

Plate II Week 2 25 pages

Plate II: Arrays

A string is only an array of chars, and a cipher is only arithmetic.

Compiling in four steps, an off-by-one in his row.c caught in the debugger, and int scores[3] holding 72, 73 and 33. Then HI! laid out in memory, the Caesar cipher (HI! becomes IJ!, and UIJT XBT DT50 decodes back), argc and argv, and two full pages of colour handwriting: the anatomy of a function, and local against global scope.

Specimen II·a His program, ported line for line

Scrabble

Two players, his points table. Each word is upper-cased in place, printed, then scored letter by letter as POINTS[c - 65].

Pairs from the problem:
Player 1
  1. C3
  2. O1
  3. M3
  4. P3
  5. U1
  6. T1
  7. E1
  8. R1
14
Player 2
  1. S1
  2. C3
  3. I1
  4. E1
  5. N1
  6. C3
  7. E1
11

Player 1 wins

./scrabble
Player 1: COMPUTER
Player 2: science
COMPUTER
SCIENCE
Player 1 wins 
His POINTS table
  1. A1
  2. B3
  3. C3
  4. D2
  5. E1
  6. F4
  7. G2
  8. H4
  9. I1
  10. J8
  11. K5
  12. L1
  13. M3
  14. N1
  15. O1
  16. P3
  17. Q10
  18. R1
  19. S1
  20. T1
  21. U1
  22. V4
  23. W4
  24. X8
  25. Y4
  26. Z10

convert_upper() prints each word as it upper-cases it, so the transcript shows both words in capitals before the result.

He prints Player 1 wins and Tie! with a trailing space, where the specification had Player 1 wins!

Nothing filters out punctuation, digits or spaces; they index outside the table (try Question? against Question!).

Source Scrabble.c 69 lines

Verbatim from PS - 02/Scrabble.c.

Specimen II·b His program, ported line for line

Caesar

The key comes in on the command line, must be all digits, and turns every letter that many places round the alphabet, keeping its case. Turn the wheel, or type a key.

A becomes N

./caesar 13
plaintext: Be sure to drink your Ovaltine!
ciphertext: Or fher gb qevax lbhe Binygvar!

Any all-digit key is accepted, 26 or 999 included; only the remainder after 26 matters. A minus sign is not a digit, so -3 gets the usage line.

One edge his check lets through: an empty argument, ./caesar "", has no non-digits in it, so it passes and atoi makes it key 0.

Source caesar.c 58 lines

Verbatim from PS - 02/caesar.c.

Specimen II·c His program, ported line for line

Readability

Coleman-Liau: 0.0588 × L − 0.296 × S − 15.8, where L is letters and S sentences per hundred words. The grade moves as you type; below, the text as his loop reads it.

From the problem:

Congratulations! Today is your day. You're off to Great Places! You're off and away!

. sentence word break 9 a letter to his code only , not counted

Grade 3

The specification agrees.

letters
65
words
14
sentences
4
L per 100 words
464.29
S per 100 words
28.57
index
3.043
./readability
Text: 
Congratulations! Today is your day. You're off to Great Places! You're off and away!
3.042856 
3 
Grade 3

A letter, to his loop, is anything that is not a space, . ! ? , ' ". Digits, hyphens, colons, semicolons and every byte of an accented letter count.

Words are spaces followed by something, plus one: two spaces in a row make an extra word, a trailing space does not.

He prints the raw index and its rounding before the grade, two lines the specification did not ask for.

Source readability.c 80 lines

Verbatim from PS - 02/readability.c.

Plate III Week 3 15 pages

Plate III: Algorithms

Searching, sorting, and what each step costs.

Searching behind doors, linear and binary, beside a chart of growth from O(1) to O(n!). A phone book built from a typedef’d struct, the lecture’s race between selection, merge and bubble sort, and recursion unwinding f(4) down to 24. The shorts add the bounds: O(n²) and Ω(n²) for selection sort, O(n log n) for merge sort, and Collatz for good measure.

Specimen III·a His program, ported line for line

Plurality

Name the candidates on the command line, then vote: click a name, or type one exactly as his strcmp wants it. An empty line closes the polls and everyone holding the most votes is printed.

Polls open.

./plurality Alice Bob Charlie
Vote (Press ENTER to stop): ▌

The course's distribution code asked for the number of voters first. His main drops that and keeps taking votes until an empty line.

Close the polls before anyone votes and every candidate ties at zero, so all of them are printed.

Source plurality.c 96 lines

Verbatim from PS - 03/plurality.c.

Specimen III·b An illustration of the week's idea

Three sorts, racing

The week's three sorts on the same 32 bars. Each tick, every algorithm makes one more comparison; the counts are the race. Try an array that is already nearly sorted and watch bubble sort's early exit.

  1. Selection sort

    O(n²) · Ω(n²)

    0 comparisons 0 swaps

  2. Bubble sort

    O(n²) · Ω(n)

    0 comparisons 0 swaps

  3. Merge sort

    O(n log n) · Ω(n log n)

    0 comparisons 0 writes

32 bars, unsorted. Press Race.

Plate IV Week 4 45 pages

Plate IV: Memory

Addresses, pointers, and two strings that only look alike.

The longest notebook. It opens on pixel art and hexadecimal colour, then addresses: int *p = &n printing real ones, a lecture still with “0x123, Stored, Pointer” written over it, pointer arithmetic on HI!, and, on pages 11 and 12, compare.c, where s and t point at two separate HI! strings at 0x123 and 0x456. Then malloc and free, Valgrind, garbage values, swap and file I/O, with shorts on the heap, the stack and file pointers.

Specimen IV·a An illustration of the week's idea

Two strings that look alike

From the lecture's compare.c: two calls to get_string put two copies of “HI!” at two addresses, and s and t hold only those addresses. The addresses here are invented, in the lecture's style.

Compare with
s0x123
t0x456

s == t compares 0x123 with 0x456: two addresses, so Different, even though both strings read “HI!”.

./compare
s: HI!
t: HI!
Different

heap · string s

  1. 0x120
  2. 0x121
  3. 0x122
  4. sH0x123
  5. I0x124
  6. !0x125
  7. \00x126
  8. 0x127

heap · string t

  1. 0x450
  2. 0x451
  3. 0x452
  4. 0x453
  5. 0x454
  6. 0x455
  7. tH0x456
  8. I0x457
  1. !0x458
  2. \00x459
  3. 0x45A
  4. 0x45B
  5. 0x45C
  6. 0x45D
  7. 0x45E
  8. 0x45F

Plate V Week 5 29 pages

Plate V: Data Structures

Nodes, buckets and tries: memory given a shape.

A linked list built node by node until list → 3 → 2 → 1, a hash table of Nintendo characters, and a trie that spells TOADETTE. The section adds a “Hey!” → “Hi!” list and what makes a good hash function; the shorts cover structs and the arrow operator, singly and doubly linked lists, stacks, queues, hash tables with probing and chaining, and tries.

Specimen V·a An illustration of the week's idea

A hash table, by first letter

An array of 26 pointers, one per first letter, each the head of a linked list. New words go in at the head of their list, which costs one step however long it is; finding a word means walking the chain. Seeded with CS50's problem sets.

hash(word) = toupper(word[0]) − 'A'

16 words10 of 26 buckets usedlongest chain 3

  1. A[0]
  2. B[1]
  3. C[2]
    1. Caesar
    2. Credit
    3. Cash
  4. D[3]
  5. E[4]
  6. F[5]
    1. Filter
  7. G[6]
  8. H[7]
    1. Hello
  9. I[8]
    1. Inheritance
  10. J[9]
  11. K[10]
  12. L[11]
  13. M[12]
    1. Mario
  14. N[13]
  15. O[14]
  16. P[15]
    1. Plurality
  17. Q[16]
  18. R[17]
    1. Recover
    2. Runoff
    3. Readability
  19. S[18]
    1. Speller
    2. Substitution
    3. Scrabble
  20. T[19]
    1. Tideman
  21. U[20]
  22. V[21]
    1. Volume
  23. W[22]
  24. X[23]
  25. Y[24]
  26. Z[25]

Plate VI Week 6 19 pages

Plate VI: Python

The same program, in well under half the lines.

clang -o hello beside python hello.py, and his own Codespace, where hello.py says hello after two rounds of “command not found”. Then C and Python side by side: if and else, get_string and input, strcmp and ==, lists, string methods, range, dictionaries and csv.DictReader, with shorts on tuples, comprehensions, functions and a Student class.

Specimen VI·a His program, ported line for line

Readability, in two tongues

On 20 February 2025, a day after readability.c, Kamal committed the same program in Python. Type once; both run. The Python file was deleted from the repository on 24 March 2025 (commit 1ef03f3) and is recovered here from the history.

Where they part:

Both print Grade 3.

C · PS 2 · readability.c

Grade 3

letters
65
words
14
sentences
4
./readability
Text: 
Congratulations! Today is your day. You're off to Great Places! You're off and away!
3.042856 
3 
Grade 3

Python · PS 6 · Sentimental readability.py

Grade 3

letters
65
words
14
sentences
4
python "Sentimental readability.py"
Text: Congratulations! Today is your day. You're off to Great Places! You're off and away!
Grade 3

What Python took away

CPython
lines in the file8031
lines that are code5822
#include / import50
typed declarations170
semicolons310
braces180

No main, no types, no character-by-character test against seven punctuation marks: isalpha() and count(" ") do the work. Python’s round() also rounds halves to the even neighbour where C’s rounds them away from zero, and his Python prints a blank line after “Before Grade 1”.

Source readability.c beside Sentimental readability.py

Verbatim: the C from PS - 02/readability.c; the Python from PS - 06/Sentimental readability.py, as it stood before 24 March 2025.

Plate VII Week 7 6 pages

Plate VII: SQL

Asking a table questions.

The class’s favourite languages go from a Google Form to a CSV to Python, then into SQL: CREATE TABLE, sqlite3, SELECT DISTINCT language (Python, C, Scratch) and COUNT(DISTINCT language), which says 3. Then the clauses, INSERT and DELETE, and a page of data types.

Specimen VII·a An illustration of the week's idea

Questions for a small table

Ten invented rows, shaped like the lecture’s favorites table. Choose a question; the rows and columns it reads light up, and the answer comes back the way sqlite3 prints it. Nothing here is a database engine: each query is drawn by hand.

Ask
favorites, with the rows and columns this query reads lit
idlanguageproblem
1PythonHello, World
2CMario
3ScratchScratch
4PythonDNA
5CCredit
6CCaesar
7PythonReadability
8ScratchScratch
9CPlurality
10PythonMario

The query on page 3 of the notes; there, too, it answered Python, C, Scratch.

sqlite> SELECT DISTINCT language FROM favorites;
+----------+
| language |
+----------+
| Python   |
| C        |
| Scratch  |
+----------+

Plate VIII Week 8 21 pages

Plate VIII: HTML, CSS & JavaScript

Structure, style and behaviour, this page included.

The internet first: an early network map, routers, TCP/IP, HTTP against HTTPS, and status codes down to 418, I’m a Teapot. Then HTML and its DOM tree, his own list.html and video.html in the browser, regular expressions in form patterns, CSS selectors, and JavaScript beside Scratch with every event a page can hear. Shorts on DNS, DHCP, ports and DOM methods close it.

Specimen VIII·a An illustration of the week's idea

This page, under glass

The week in one page, this one. HTML gives it structure, CSS gives it a look, JavaScript gives it behaviour. Count its elements, listen to its events (the list on page 11 of the notes), or take the CSS away and see the bare HTML underneath.

The tree

elements
…

The outline the headings make:

    The events

    Heard on this page since it loaded. Move, click, type, tab.

    • blur0
    • change0
    • click0
    • drag0
    • focus0
    • keyup0
    • load0
    • mousedown0
    • mouseover0
    • mouseup0
    • submit0
    • touchmove0
    • unload0

    The style

    Every rule on this page lives in one stylesheet. Remove it; a button at the very top brings it back, and so does Escape.

    Plate IX Week 9 2 pages

    Plate IX: Flask

    One route, one response.

    Two pages. A raw request, GET /search?q=cats, and a whole Flask application: one route, /, returning “hello, world”. The second page lists a Flask project’s bones: app.py, requirements.txt, static/ and templates/.

    Specimen IX·a An illustration of the week's idea

    A request, followed

    Page 1 of the notes holds a whole web application: one route, one function, one string. Send it a request. No server runs here; the answers are the ones Flask’s development server gives this app.

    Or try:
    1. The request

      GET / HTTP/1.1
      Host: 127.0.0.1:5000
      Accept: text/html
    2. app.py

      from flask import Flask
       
      app = Flask(__name__)
       
      @app.route("/")
      def index():
          return "hello, world"
      • app.py
      • requirements.txt
      • static/
      • templates/
    3. The response

      HTTP/1.1 200 OK
      Content-Type: text/html; charset=utf-8
      Content-Length: 12
      
      hello, world

    / matches @app.route("/"); index() returns “hello, world”.

    Plate X Week 10 5 pages

    Plate X: The End

    A list of beginnings.

    Not a recap but a list of beginnings: where to host a website and a web app, where to ask questions and read the news, and the syllabi of CS50’s next courses, in Python, R, the web, AI, SQL and cybersecurity.

    Specimen X·a An illustration of the week's idea

    Eleven lamps

    The almanac began with eight lamps and one byte. It ends with eleven, one per plate, and each lights as its plate passes under your eyes (or when you press it). Eleven bits count to 2047.

    00000000000

    0 of 2047

    No plates read yet.

    Page 1 of these notes lists places to host a web app; vercel.com is one of them, and it is where this almanac is kept.

    The chronicle

    How the repository filled

    The course itself happened elsewhere; this is when its record landed on GitHub. Sixty-seven commits over five weeks, from the first README on 18 February 2025 to a spring clean on 24 March. Times are India Standard Time, as committed.

    1918 Feb19424 Feb41 Mar10 Mar18 Mar524 Mar
    Commits per day, 18 February to 24 March 2025: nineteen on each of the first two evenings, then a scatter of README edits, and five deletions to close.
    Commits per day
    DayCommits
    18 Feb19
    19 Feb19
    20 Feb4
    21 Feb3
    26 Feb4
    27 Feb3
    1 Mar2
    2 Mar3
    5 Mar1
    6 Mar2
    15 Mar2
    24 Mar5
    1. 22:18

      The repository is begun

      An initial commit and a README, rewritten three times in five minutes.

    2. 22:27 – 22:48

      Eleven notebooks, in twenty-one minutes

      Every plate in this almanac arrives in one evening, and not in order: Week 10 first, then Weeks 1 and 0, then 2 through 9. Two files are renamed on the way: “CS 50” loses a space, “Week-10” gains one.

    3. 22:06 – 22:27

      Problem sets 1 and 2, in C

      Hello me.c, mario less.c and credit.c; then Scrabble.c, readability.c and caesar.c, each with an empty .txt companion. Folders PS-01 and PS-02 are made, deleted and remade as PS - 01 and PS - 02.

    4. 20:56

      Readability again, in Python

      Sentimental readability.py lands in PS - 06: the Week 2 program rewritten in thirty-one lines. Plate VI sets the two side by side.

    5. Placeholders for what comes next

      Empty entries for PS - 03, 04, 05, 07 and 08.

    6. 13:18

      Plurality

      The PS - 03 placeholder gives way to plurality.c, the last C program in the record.

    7. 15:54

      Given to the public domain

      A CC0 1.0 licence. Around it, from 26 February to 15 March, thirteen more passes at the README.

    8. 20:33 – 20:34

      A spring clean

      Five deletions in a minute: the PS - 04, 05, 07 and 08 placeholders, and the PS - 06 folder with the Python inside it. The Python survives in the history, and on Plate VI.

    Colophon

    About this almanac

    Matter

    A personal study record. Kamalraaj Senthilkumar took Harvard's CS50x in 2025 and kept a notebook for every week: 214 pages across eleven weeks, with his problem sets in C and Python. Everything here comes from his repository, which he dedicated to the public domain under CC0 1.0.

    The specimens marked his program are ports of his code to JavaScript, checked against his C compiled with clang on the same inputs. Where his code behaves differently from the course's specification, the specimen behaves like his code and says so. The other specimens are illustrations of the week's idea, not his work.

    Type & colour

    Bodoni Moda for display, a Didone cut with optical sizes by Owen Earl. Newsreader for reading, by Production Type. Courier Prime for code and figures, a slab monospace by Alan Dague-Greene. All three under the SIL Open Font License, self-hosted.

    • Midnight ink
    • Parchment
    • Crimson seal
    • Gilt

    Credit & licence

    The lecture stills inside the notes come from CS50's lectures: CS50, Harvard University, licensed CC BY-NC-SA 4.0. This site is a personal record of study. It is not affiliated with, or endorsed by, Harvard University or CS50.

    Built by Kamalraaj Senthilkumar. More work at justkamalthings.com; the source of the notes and programs at github.com/Kamal007OLica/Harvard-CS50-2025.

    Plate Notebook

    PDF