CS U111 · Mid-sem · Lesson — how to start
Writing a program from a blank page
What to write in the first five minutes of a "write a C program" question, when you've read it and nothing comes. Five moves, shown on real mid-sem questions. The full questions, built step by step, are on the practice page.
1. Program writing is now most of the paper. In the three past mid-sems of this course's predecessor (CS F111), questions that ask you to write a program from scratch were worth 10 of 90 marks (Sem 1, 2024-25), then 28 of 90 (Sem 1, 2025-26), then 80 of 90 (Sem 2, 2025-26). Those papers had different examiners, and this year's format isn't confirmed yet. But the direction is clear, and the end-semester lab exam (25%) is program writing too.
2. About a third of those marks are for the start of the program, not the clever part. The 2026 marking schemes give 30 of their 80 marks for declarations, reading the input and printing the result: the parts every program has. A further 5 are for the dry run you should do anyway. Moves 1, 2 and 5 below write exactly those parts. So a student who freezes at the core logic but runs the routine still collects roughly a third of the marks.
3. Following a solution and starting one are different skills. Reading a model answer trains the first; writing from a blank page trains the second. "I understand it once I see it, but I can't begin" is what you'd expect from practising only the first. And nobody in the hall wrote C on paper, without a compiler, before joining. JEE doesn't teach it. This is new to everyone, and it's a drilled habit, not a talent.
- The routine
- 1 · Restate
- 2 · Skeleton
- 3 · Pattern
- 4 · Hand table → loop
- 5 · Dry run & assumptions
- Coding on paper
- In the exam room
1 · The routine: five moves
When you freeze on a programming question, you're usually searching for "the idea": the whole program at once. The routine replaces that search with five writing jobs. The first two never need an idea at all, and by the time you reach move 4 the idea usually shows up by itself.
- RestateWrite one line: input → output, using the question's own example. "5 numbers 2 5 6 4 9, value 10, position 2 → 2 5 10 6 4". If the question has no example, make up a tiny one and work it by hand. You can't write code for an answer you can't produce by hand.
- SkeletonWrite the parts every program has:
#include,int main(void) {, one declaration per thing in your move-1 line, aprintfprompt andscanffor every input, aprintffor every output,return 0; }. Leave a blank gap in the middle. This is where the "declarations and I/O" marks are. - PatternName the job in the middle, using the question's words: accumulate, find the max, count, search, shift, peel digits, try every combination, validate then process. Each name comes with a loop shape you already know (table in move 3).
- Hand table → loopDo the example by hand, one small step per row, writing down what changes. The rows that repeat are your loop body. Where the rows start is the loop's start, and where they stop is its condition.
- Dry run & assumptionsRun your code on the example on paper, a line at a time, and check you get the move-1 output. Then write "Assumption: …" for anything the question leaves open (bad input, a zero, the array size). The papers explicitly ask for this.
The sections below show each move on real questions. Each one stops where the routine hands over to the loop you'd write, so you can see how much of the answer the routine produces without an idea.
2 · Move 1 — restate: input → output
This move catches the most common reason for freezing: not being sure what the program is supposed to do. Long questions bury it in a story (vending machines, bank accounts, cricket). Strip the story and keep the data.
Write a program to insert a new element it to an array of integers at a given position (index), while doing so, all the elements from that position(index) must be moved to right by one position, and the original last element is lost as it moves beyond the boundary. Then print the resultant array. … Ex: Assume that the Original array where n=5, is {2 5 6 4 9}; the new element to be inserted is 10, at insert position (index)=2. After the execution of the program, the resulting array should be :{ 2 5 10 6 4}.
Move 1, written on the answer sheet:
/* in: n = 5, 2 5 6 4 9, value 10, position 2
out: 2 5 10 6 4 (9 falls off the end) */
Notice what that line already tells you: four inputs (n, the n numbers, the value, the position) and one output (the whole array). That's move 2's shopping list.
Develop a program that reads a sequence of characters (comprising of digits and lowercase alphabets) from the console terminated by an enter character. The program displays the sum of the digits. The program saves only the alphabets in a character array. The program displays the highest alphabet present in the array. (Hint: ASCI values of digits range from 48 to 57 and enter character is 10) · Usecase1: Input Sequence: ab12cd34 · Output: Sum of digits: 10 · Highest alphabet: d
/* in: a b 1 2 c d 3 4 [Enter] one character at a time
out: 1+2+3+4 = 10; letters a b c d, highest is d */
Writing "one character at a time" is the useful part: it tells you the input is read inside a loop, one char per scanf("%c", …), until the Enter key's character arrives.
Check yourself: write move 1 for the 2025 Sem 1 bank-account question. The sample input is {1,0,9,9} and the output is {1,1,0,0}.
in: n = 4, digits 1 0 9 9 → out: 1 1 0 0, because 1099 + 1 = 1100. Two things should jump out once it's written as a sum: the last digit is where you start, and a 9 turns into 0 and passes 1 to the digit on its left (a carry). That's the whole problem, found in one line.
3 · Move 2 — the skeleton the marking scheme pays for
Every program in this course has the same outer shell, and the shell is worth real marks. Here's what the published schemes say:
| Question | Marks for shell (declarations, input, output) | Marks for core logic |
|---|---|---|
| 2026 Q1 insert into array (16) | 3 program/syntax/variables + 5 declaration, scanf, printf = 8 | 8 |
| 2026 Q2(a) largest of three (10) | set-up and I/O = 2 | 8 |
| 2026 Q3 coin change (16) | prompts and scanf 2 + printing the count / "Not Possible" 2 = 4 | 7 loops + 5 dry run |
| 2026 Q4 cricket stats (16) | declarations 3 + reading loop 2 + final output block 3 = 8 | 8 (validation, initialising, the stats loop) |
| 2026 Q5 quadratic (16) | headers, declarations, scanf, syntax 6 + printf 2 = 8 | 8 (switch, root formulas) |
| 2024 Q11 characters (10) | declarations 1 + reading characters 1 + 1 = 3 | 7 |
The template is the same every time. Write it first, top to bottom, with an empty gap where the logic will go:
#include <stdio.h> /* add <math.h> if you'll need sqrt or pow */
int main(void) {
/* one declaration per thing on the move-1 line */
/* a prompt + scanf for every INPUT */
/* ---- gap: the core logic goes here (moves 3-4) ---- */
/* a printf for every OUTPUT */
return 0;
}
Here's the shell for the 2026 cricket question (Q4: ten scores in an array, each between 0 and 200; print total, average, highest, lowest, centuries and a consistency verdict). It is written straight from the question's list of outputs, before any thinking about how to compute them:
#include <stdio.h>
int main(void) {
int runs[10]; /* declarations */
int i, total = 0, highest, lowest, centuries = 0;
float average;
printf("Enter runs in 10 matches: "); /* input */
for (i = 0; i < 10; i++)
scanf("%d", &runs[i]);
/* ---- gap: validate, then compute ---- */
printf("Total Runs = %d\n", total); /* output */
printf("Average Runs = %.2f\n", average);
printf("Highest Score = %d\n", highest);
printf("Lowest Score = %d\n", lowest);
printf("Number of Centuries = %d\n", centuries);
return 0;
}
That's already most of the 8 shell marks, and it forced three decisions that belong to move 3: total and centuries start at 0 (they add up), highest and lowest have no starting value yet (they need the first score), and average is a float because the output has two decimals.
Check yourself: write the move-2 shell for the 2026 quadratic question (integers a, b, c in; two roots out, real or complex).
#include <stdio.h> and #include <math.h> (you'll need sqrt); int a, b, c; for the inputs; double r1, r2, re, im; for the outputs (roots aren't whole numbers); a prompt and scanf("%d %d %d", &a, &b, &c);; then the gap, a printf for each case, and return 0;. The scheme gives 6 + 2 of the 16 marks for exactly this.
4 · Move 3 — name the pattern
Almost every program on these papers is built from a few jobs you've met in the loops and arrays labs. The question's words tell you which job:
| The question says… | Pattern | Loop shape | Taught in |
|---|---|---|---|
| "total", "sum", "average" | Accumulate | sum = 0; before; sum += x; inside | Loops notes |
| "highest", "largest", "minimum" | Find the max/min | best = a[0]; before; if (a[i] > best) best = a[i]; inside | Arrays notes |
| "how many", "number of …" | Count | count = 0; before; if (test) count++; inside | Loops notes |
| "is present", "find", "not in B" | Search (with a flag) | flag = 0; then loop, if (match) { flag = 1; break; } | Arrays notes |
| "insert", "delete", "moved right by one" | Shift | Move elements one place, starting from the end they're moving towards | move 4 below |
| "digits of a number", "without arrays" | Digit peel | d = t % 10; (last digit), t = t / 10; (drop it), until t == 0 | Loops notes |
| "all possible combinations", "number of ways" | Try everything (nested loops) | One loop per unknown, test the condition in the innermost | Loops notes |
| "must be between", "display an error and terminate" | Validate, then process | Check each input as you read it; return 0; on a bad one | Operators & selection notes |
Most questions stack two or three. The cricket question is validate + accumulate + max + min + count, all in one loop over the same array. The character question is accumulate (digits) + store (letters) + max (highest letter). Naming them turns one frightening question into three small ones you've each done before.
Check yourself: name the patterns in "read a 5-digit number and output the smallest number you can make from its digits; you may not use arrays" (2025 Sem 1 Q6).
Digit peel ("digits", "without arrays") plus search: for each possible digit 0, 1, 2, … 9 in order, peel the number to see if that digit is in it; if it is, attach it to the answer. Trying the digits smallest-first is what makes the result the smallest. The practice page builds it in ten lines (the model answer took thirty).
5 · Move 4 — a hand table becomes the loop
This is the move that turns "I know it's a shift" into code. Do the example by hand, one small step per row, and write down exactly which variable or array cell changes in each step. Then look at the rows: the ones that repeat, with only an index changing, are the loop body.
Example: insert 10 at position 2
Array 2 5 6 4 9. The 9 must fall off, the 4 must move into the 9's cell, the 6 into the 4's cell, and then the 10 goes into cell 2. By hand, one step per row:
| Step | What happens | Array after |
|---|---|---|
| 1 | a[4] = a[3] (4 overwrites the 9) | 2 5 6 4 4 |
| 2 | a[3] = a[2] (6 moves right) | 2 5 6 6 4 |
| 3 | a[2] = 10 (the new value) | 2 5 10 6 4 |
Now read the table. Steps 1 and 2 have the same shape, a[i] = a[i-1], with i going 4, 3: from the last index n-1 down to just above the position. Step 3 happens once, afterwards. That is the code:
for (i = n - 1; i > pos; i--) /* rows 1-2: i = 4, then 3 */
a[i] = a[i - 1];
a[pos] = val; /* row 3, once */
Unpack: why right-to-left, not left-to-right?
Left-to-right would do a[3] = a[2] first, overwriting the 4 before it has moved, and then a[4] = a[3] copies the 6 again. Compiled, that version prints 2 5 10 6 6. Always start the shift at the end the values are moving towards, so nothing is overwritten before it has been copied.
Example: add 1 to 1 0 9 9
The same move on the bank-account question. By hand, as you'd add on paper:
| Step | Look at digit | What happens | Digits after |
|---|---|---|---|
| 1 | index 3 (a 9) | 9 + 1 = 10: write 0, carry 1 left | 1 0 9 0 |
| 2 | index 2 (a 9) | 9 + 1 = 10: write 0, carry 1 left | 1 0 0 0 |
| 3 | index 1 (a 0) | 0 + 1 = 1: write 1, carry stops | 1 1 0 0 |
The rows that repeat are "while the digit is 9: write 0 and move one left". The row that ends it is "not a 9: add 1 and stop". So the loop runs while the digit is 9, starting from the last index, and one +1 follows it:
i = n - 1;
while (i >= 0 && d[i] == 9) { /* the repeating rows */
d[i] = 0;
i--;
}
if (i >= 0)
d[i] = d[i] + 1; /* the last row, once */
Check yourself: for "all ways to change 110 using notes of 100, 20 and 10", what would the hand table's columns be, and how many loops does that give?
Columns: how many 100s, how many 20s, how many 10s, and the total. The rows go 0-0-11, 0-1-9, 0-2-7, … 1-0-1. Three columns that each take several values means three nested loops, one per column, and a test in the innermost: does the total equal 110? The count of rows that pass is the "number of ways" (7). Full build →
6 · Move 5 — dry run on paper, and write down your assumptions
With no compiler in the exam hall, the dry run is how you test. Take the question's own example and trace your code through it, writing a row every time a variable changes. If the last row matches your move-1 output, you're done. If not, the row where it first goes wrong shows you the bug. For the insert question with n = 5, pos = 2, val = 10:
| Line | i | Test | Array |
|---|---|---|---|
| for starts | 4 | 4 > 2 true | 2 5 6 4 4 |
| i-- | 3 | 3 > 2 true | 2 5 6 6 4 |
| i-- | 2 | 2 > 2 false, loop ends | 2 5 6 6 4 |
| a[pos] = val | — | — | 2 5 10 6 4 ✓ |
2026 Q3 gives 5 of its 16 marks for exactly this kind of written dry run (the printed tuples and the count), so on questions that ask for one, it's marks, not just checking.
Assumptions. Both recent papers say it in the instructions. 2025: "If you feel that something is missing in any question, please make your own assumption, and state it clearly in your answer." 2026: "If you think something is really missing, you can assume and proceed, but mention your assumption." Examples from these papers:
- Quadratic: "Assumption: a ≠ 0" (otherwise it isn't a quadratic and the formula divides by zero).
- Smallest number from the digits: "Assumption: the answer must stay a 5-digit number, so a 0 digit can't go first" (or the opposite, stated). The question never says which, and the model answer quietly picks one.
- Characters until Enter: "Assumption: at most 100 letters", which is the size you gave the array.
- Insert at a position: "Assumption: 0 ≤ position ≤ n − 1".
Check yourself: dry-run this line for n = 12 (from the 2026 multiple-choice section) and say what happens: while (n >= 0) { printf("%2d", n % 10); n = n / 10; }
Prints 2 (n becomes 1), prints 1 (n becomes 0), then 0 ≥ 0 is still true: prints 0, and n = 0/10 stays 0. So it prints 0 forever: an infinite loop (the key's answer). The dry-run table shows it in the third row: the same state repeats. A condition that can never become false is exactly what move 5 catches.
7 · Coding on paper: habits and the silent killers
Writing code by hand has its own failure mode: small slips that a compiler would catch. Three habits prevent most of them.
- Write every brace pair at once. When you write
{, write the matching}a few lines below straight away, then fill in between. Unbalanced braces make examiners guess what you meant. - Indent 4 spaces per level, even on paper. It shows which lines are inside which loop, for you and for the examiner.
- One statement per line, and a semicolon on every statement line, except lines that end in
{and thefor (…)/while (…)/if (…)line itself. A stray;afterfor (…)makes the loop do nothing (a 2025 predict-the-output question tested exactly this).
Then scan your finished answer for these. Each one compiles (at most with a warning) and then runs wrongly, which is why they cost marks even from students who know the logic:
| Silent killer | Wrong | Right | Seen on the papers |
|---|---|---|---|
Missing & in scanf | scanf("%d", n); | scanf("%d", &n); | every program reads input |
%f for a double in scanf | scanf("%f", &x); with double x | %lf (and %Lf for long double); in printf, %f is fine | 2024 fill-in Q6, 2025 Q1(b) |
| Integer division | average = total / 10; → 68.00 | total / 10.0 → 68.30 | 2026 Q4 average, and the 2026 Q5 model answer itself |
| Array bound off by one | for (i = 0; i <= n; i++) | i < n: indices run 0 to n − 1 | every array question |
= instead of == | if (flag = 1) (always true) | if (flag == 1) | every condition you write (clang warns; paper doesn't) |
switch without break | falls through into the next case | break; after each case | 2026 Q2(b): prints "PositiveZero" |
| Accumulator not started at 0 | int sum; then sum += d; | int sum = 0; | 2024 Q11, 2026 Q4 |
| Character vs digit | sum += c; adds 49 for '1' | sum += c - '0'; | 2024 Q11 (2 of its 10 marks) |
Unpack: why does c − '0' turn the character '7' into the number 7?
Characters are stored as numbers (ASCII): '0' is 48, '1' is 49, … '9' is 57, the same order as the digits. So '7' − '0' = 55 − 48 = 7. The 2024 question's hint ("ASCII values of digits range from 48 to 57") is pointing at exactly this.
8 · In the exam room
- Budget. The 2026 paper was 90 minutes, with up to 30 of them for the 10 multiple-choice questions. That leaves about 60 minutes for five 16-mark programs: roughly 12 minutes per program. Moves 1–2 take about 3 of those minutes and are the safest marks on the page.
- Stuck at move 4 for five minutes? Leave the shell (moves 1–2) on the page, write your hand table next to it, and move to the next question. Come back at the end. A complete shell with a partial loop scores. A blank page scores zero.
- Read the restrictions twice. 2026 questions forbade things: "only one array", "should not use &&", "at most three if-else", "no if conditions", "only for loops", "no user-defined functions or sorting". A correct program that breaks a restriction can lose the logic marks (2026 Q2(a) paid its 8 logic marks only for "correct logic that satisfies conditions in the q"). Underline each restriction before move 3.
- Finish with move 5. Trace the question's own example through your code. It's the only test you'll get.
A chat AI is useful here if you make it play examiner rather than solver. Two prompts that work:
"I'm a first-year student learning C (loops, 1-D arrays, if/switch; no pointers or functions yet). Give me one mid-sem-style 'write a program' question with a sample input and output. Don't show a solution. I'll send my move-1 input→output line and my skeleton first; tell me only whether my declarations and scanf/printf are complete."
"Here is my C program written on paper for [question]. Don't rewrite it. Dry-run it on the sample input, showing a table of the variables after each loop iteration, and tell me the first row where it goes wrong."
One caution: AI dry runs make arithmetic slips too. If its trace disagrees with yours, compile the code and let the machine decide.
Next: the practice page takes every program question from the three past papers through all five moves, with a skeleton marked against its marking scheme and a compiled solution for each. The questions exactly as set, with every other question on those papers, are on the past papers page.