Logical Reasoning I: Series, Coding, Relations, Directions and Calendars
The first half of logical reasoning is pattern recognition: spot the rule behind a series, decode a letter scheme, trace a family tree, follow directions, or count days. These questions are fast once you know the standard rules, and they reward a systematic habit: write the structure down (a table, an arrow diagram, coordinates) instead of holding it in your head. Every example is checked by a small program that implements the rule.
1. Number series
Find the rule linking terms. Try, in this order:
- Differences between consecutive terms (and differences of the differences).
- Ratios between consecutive terms.
- Squares, cubes, primes, factorial-like patterns.
- Two interleaved series (odd and even positions follow different rules).
- Alternating operations (+2, ×3, +2, ×3).
- Sum of the previous two terms (Fibonacci type).
| Series | Rule | Next |
|---|---|---|
| 2, 6, 12, 20, 30, ? | differences 4, 6, 8, 10 (or ) | 42 |
| 3, 6, 11, 18, 27, ? | differences 3, 5, 7, 9 (or ) | 38 |
| 1, 4, 9, 16, 25, ? | squares | 36 |
| 2, 3, 5, 7, 11, ? | primes | 13 |
| 5, 10, 20, 40, ? | ×2 | 80 |
| 1, 1, 2, 3, 5, 8, ? | sum of the previous two | 13 |
| 100, 95, 85, 70, 50, ? | subtract 5, 10, 15, 20, then 25 | 25 |
| 2, 4, 12, 48, 240, ? | multiply by 2, 3, 4, 5, then 6 | 1440 |
def next_by_differences(seq, depth=1):
"""Extrapolate assuming the differences (taken `depth` times) are an arithmetic progression."""
rows = [list(seq)]
for _ in range(depth):
rows.append([b - a for a, b in zip(rows[-1], rows[-1][1:])])
rows[-1].append(rows[-1][-1] + (rows[-1][-1] - rows[-1][-2]))
for i in range(depth - 1, -1, -1):
rows[i].append(rows[i][-1] + rows[i + 1][-1])
return rows[0][-1]
assert next_by_differences([2, 6, 12, 20, 30], depth=2) == 42
assert next_by_differences([3, 6, 11, 18, 27], depth=2) == 38
assert next_by_differences([100, 95, 85, 70, 50], depth=2) == 25
assert [k * k for k in range(1, 7)][-1] == 36
primes = [n for n in range(2, 20) if all(n % d for d in range(2, n))]
assert primes[:6] == [2, 3, 5, 7, 11, 13]
fib = [1, 1]
while len(fib) < 7:
fib.append(fib[-1] + fib[-2])
assert fib == [1, 1, 2, 3, 5, 8, 13]
term = 2
for factor in (2, 3, 4, 5, 6):
term *= factor
if factor == 5:
assert term == 240
assert term == 1440
Interleaved and alternating series
Example 1. 4, 10, 8, 20, 12, 30, 16, ? Odd positions: 4, 8, 12, 16 (+4). Even positions: 10, 20, 30 (+10), next 40. The missing term is the next even-position value after 16 (the 7th term is 16); the 8th term is 40.
Example 2. 2, 5, 11, 23, 47, ? Each term is twice the previous plus 1: next .
odd, even = [4, 8, 12, 16], [10, 20, 30, 40]
series = [v for pair in zip(odd, even) for v in pair]
assert series == [4, 10, 8, 20, 12, 30, 16, 40]
s = [2]
for _ in range(5):
s.append(2 * s[-1] + 1)
assert s == [2, 5, 11, 23, 47, 95]
Letter series
Convert letters to positions (A = 1, ..., Z = 26) and look for the same number rules.
Example 3. A, C, F, J, O, ? Positions 1, 3, 6, 10, 15: differences 2, 3, 4, 5, then 6, so the next position is 21, the letter U.
Example 4. AZ, BY, CX, ?: first letters go forward, second letters backward: DW.
import string
L = string.ascii_uppercase
pos = lambda c: L.index(c) + 1
chr_at = lambda n: L[(n - 1) % 26]
assert [pos(c) for c in "ACFJO"] == [1, 3, 6, 10, 15] and chr_at(15 + 6) == "U"
assert chr_at(4) + chr_at(27 - 4) == "DW"
2. Coding and decoding
A word or number is transformed by a rule. Work out the rule from the example, then apply it.
Types
- Shift cipher: each letter moves forward or backward by (CAT with +1 becomes DBU).
- Reverse alphabet (mirror): A↔Z, B↔Y, ... A letter at position becomes position .
- Reversal of the word or of letters in place.
- Substitution by symbols or numbers: deduce from common letters across the examples.
- Position-based rules (add the position number to each letter).
- Number coding: an operation on digits.
Example 5. If CAT is coded as DBU, what is DOG? Each letter is shifted by +1: EPH.
Example 6. If BAT is written as YZG in a certain code (mirror alphabet), how is DOG written? D↔W, O↔L, G↔T: WLT.
Example 7. In a code, "pen ink" is written "ka li", "ink paper" is "li ma", and "red pen" is "ka su". What is the code for "paper"? Common word "ink" is "li" in the first two, so "paper" is ma.
def shift(word, k):
return "".join(chr_at(pos(c) + k) for c in word)
def mirror(word):
return "".join(chr_at(27 - pos(c)) for c in word)
assert shift("CAT", 1) == "DBU" and shift("DOG", 1) == "EPH"
assert mirror("BAT") == "YZG" and mirror("DOG") == "WLT" and mirror(mirror("DOG")) == "DOG"
codes = {("pen", "ink"): {"ka", "li"}, ("ink", "paper"): {"li", "ma"}}
assert (codes[("ink", "paper")] - codes[("pen", "ink")]) == {"ma"}
Coding by letter values
Assign A = 1, B = 2, ..., Z = 26 and apply the stated operation to the word.
Example 8. What is the value of the word BAD if each letter has its position value? . If the rule is the sum of positions multiplied by the number of letters, the value of BAD is .
word_value = lambda w: sum(pos(c) for c in w)
assert word_value("BAD") == 7 and word_value("BAD") * len("BAD") == 21
3. Blood relations
Draw a family tree and translate each statement into a relation. Use symbols: for male, for female, for marriage, a vertical line for parent-child, a horizontal line for siblings.
Useful vocabulary: father's or mother's father is grandfather; father's brother is uncle; father's sister is aunt; mother's brother is maternal uncle; mother's sister is aunt (maternal); brother's or sister's child is nephew or niece; spouse's brother or sister is brother-in-law or sister-in-law; uncle's or aunt's child is cousin.
Example 9. Pointing to a man, a woman says, "His mother is the only daughter of my mother." How is the woman related to the man? The woman's mother has only one daughter, and that daughter is the man's mother. The woman is also a daughter of her mother (the only one), so the woman is the man's mother.
Example 10. A is B's sister; C is B's mother; D is C's father; E is D's mother. How is A related to D? A and B are siblings; C is their mother; D is C's father, so D is their maternal grandfather, and A is D's granddaughter. (E is D's mother, so E is A's great-grandmother.)
Example 11. If P is the brother of Q, Q is the sister of R, and R is the father of S, how is P related to S? P and Q are siblings, and Q and R are siblings, so all three are siblings. R is S's father, so P is S's uncle.
A small tree structure makes these checkable. Represent each person's gender and parents, then derive relations by code.
people = {
"A": {"sex": "F", "parents": ("C", None)},
"B": {"sex": "M", "parents": ("C", None)},
"C": {"sex": "F", "parents": ("D", "E_mother_of_D_not_needed")},
"D": {"sex": "M", "parents": ("E", None)},
"E": {"sex": "F", "parents": (None, None)},
}
def parent_of(child):
return people[child]["parents"][0]
def grandparent_of(person):
p = parent_of(person)
return parent_of(p) if p else None
assert parent_of("A") == "C" == parent_of("B") # A and B share the mother C: siblings
assert grandparent_of("A") == "D" and people["A"]["sex"] == "F" # A is D's granddaughter
assert parent_of("D") == "E" # E is D's mother
# example 11: siblings share a parent; a sibling of your parent is your uncle or aunt
family = {"P": "G", "Q": "G", "R": "G", "S": "R"} # child -> parent (G stands for the shared parent)
sibling = lambda a, b: a != b and family[a] == family[b]
assert sibling("P", "R") and family["S"] == "R" # P is a sibling of S's father, hence S's uncle
4. Direction sense
Track position on a coordinate grid: North = +y, East = +x. Start at the origin and add each move. Distance from the start is ; the final direction is read from the signs.
Example 12. A man walks 5 km north, then 3 km east, then 2 km south, then 7 km west. How far is he from the start, and in which direction? Position: . Distance km. He is to the north-west of the start (4 km west, 3 km north).
Example 13. Facing north, a person turns right, then left, then left, then right. Which direction does he face now? Right of north is east; left of east is north; left of north is west; right of west is north. North.
Example 14. The sun rises behind a boy. After walking 10 m forward, he turns left and walks 5 m. In which direction is he from the start? (In the morning the sun is in the east, and the boy faces west; turning left from west means going south.) He is south-west of the start.
MOVES = {"N": (0, 1), "S": (0, -1), "E": (1, 0), "W": (-1, 0)}
def walk(steps):
x = y = 0
for d, k in steps:
dx, dy = MOVES[d]
x, y = x + dx * k, y + dy * k
return x, y
x, y = walk([("N", 5), ("E", 3), ("S", 2), ("W", 7)])
assert (x, y) == (-4, 3) and (x * x + y * y) ** 0.5 == 5
order = ["N", "E", "S", "W"]
def turn(direction, side):
return order[(order.index(direction) + (1 if side == "R" else -1)) % 4]
d = "N"
for side in "RLLR":
d = turn(d, side)
assert d == "N"
assert walk([("W", 10), ("S", 5)]) == (-10, -5) # 10 m west then 5 m south: south-west of the start
Shadows
A shadow points away from the sun. In the morning (sun in the east) shadows fall to the west; in the evening they fall to the east. At noon shadows are short and point roughly north in the northern hemisphere at most latitudes in India outside the tropics' overhead sun.
5. Ranking and position
Position from the left plus position from the right equals total + 1.
- Total .
- Persons between two people with positions : .
- Rank from the other end .
Example 15. In a row of 40 people, A is 12th from the left and B is 15th from the right. How many people stand between them? B's position from the left . Between .
Example 16. In a class, Meera is 7th from the top and 28th from the bottom. How many students are in the class? .
total, a_left, b_right = 40, 12, 15
b_left = total - b_right + 1
assert b_left == 26 and b_left - a_left - 1 == 13
assert 7 + 28 - 1 == 34
6. Calendar problems
- An ordinary year has 365 days = 52 weeks + 1 odd day; a leap year has 366 = 52 weeks + 2 odd days.
- A leap year is divisible by 4, except century years, which must be divisible by 400 (1900 was not a leap year, 2000 was).
- 100 years have 5 odd days, 200 years have 3, 300 years have 1, 400 years have 0.
- The day of the week advances by the number of odd days.
- The same calendar repeats after 28 years in most cases (not across a skipped century leap year), and a date moves one weekday forward each ordinary year and two forward after a leap day.
Example 17. If 1 January 2024 is a Monday, what day is 26 January 2024? The difference is 25 days weeks days, so Monday = Friday.
Example 18. How many days from 12 March 2023 to 5 June 2023 (not counting the first day)? March has 19 more days (13th to 31st), April 30, May 31, plus 5 in June: .
Example 19. What day of the week was 15 August 1947? Count odd days up to and including that date. The 1,900 years before 1901 contain odd days and odd day, a total of 1. The 46 years 1901 to 1946 contain 11 leap years, so odd days, which is . From 1 January to 15 August 1947 there are days, and . Total odd days . With 0 = Sunday, 1 = Monday, ..., 5 is Friday.
import datetime
is_leap = lambda y: (y % 4 == 0 and y % 100 != 0) or y % 400 == 0
assert datetime.date(2024, 1, 1).strftime("%A") == "Monday"
assert datetime.date(2024, 1, 26).strftime("%A") == "Friday" and (26 - 1) % 7 == 4
assert (datetime.date(2023, 6, 5) - datetime.date(2023, 3, 12)).days == 19 + 30 + 31 + 5 == 85
assert datetime.date(1947, 8, 15).strftime("%A") == "Friday"
assert (1 + 1 + 227 % 7) % 7 == 5 and sum(1 for y in range(1901, 1947) if is_leap(y)) == 11
assert [is_leap(y) for y in (1900, 2000, 2024, 2100)] == [False, True, True, False]
assert (sum(366 if is_leap(y) else 365 for y in range(1601, 1701))) % 7 == 5 # 100 years: 5 odd days
assert (sum(366 if is_leap(y) else 365 for y in range(1601, 2001))) % 7 == 0 # 400 years: 0 odd days
7. Odd one out and analogies
Odd one out: find the property shared by all but one (category, size, number property). Analogy: find the relation in the first pair and apply it.
- Square : 4 :: Triangle : ? The relation is the number of sides, so 3.
- Doctor : Hospital :: Teacher : ? Workplace, so School.
- Odd one out among 27, 64, 125, 144, 216? 144 is the only non-cube (the others are ): 144.
- Odd one out among 2, 3, 5, 9, 11? 9 is not prime.
is_cube = lambda n: round(n ** (1 / 3)) ** 3 == n
assert [n for n in (27, 64, 125, 144, 216) if not is_cube(n)] == [144]
assert [n for n in (2, 3, 5, 9, 11) if any(n % d == 0 for d in range(2, n))] == [9]
8. Common traps
- Assuming a pattern from too few terms; verify the rule against every given term.
- Off-by-one in position counts ("between" excludes both ends).
- Gender assumptions in blood relation questions (a name does not tell you gender; use only the text).
- Mirroring versus shifting in letter codes.
- Mixing left and right in direction questions; draw it.
- Forgetting the leap day in calendar questions and that 1900 and 2100 are not leap years.
- Using the direction of the shadow incorrectly (away from the sun).
9. Practice set with answers
- Find the next term: 7, 10, 16, 28, 52, ?
- In a certain code, TABLE is written UBCMF. How is DESK written?
- A man walks 6 km east, 8 km north, then 6 km west. How far is he from the start, and in which direction?
- Pointing to a girl, Anil says, "She is the daughter of my mother's only son." How is the girl related to Anil?
- In a row, Rohit is 18th from the left and Sanjay is 14th from the right; there are 9 people between them. How many people are in the row?
- If 5 March 2025 is a Wednesday, what day is 5 March 2026?
- Which is the odd one out: 16, 25, 36, 48, 49?
- Find the missing letter pair in: AC, FH, KM, PR, ?
seq = [7, 10, 16, 28, 52]
assert [b - a for a, b in zip(seq, seq[1:])] == [3, 6, 12, 24] and seq[-1] + 48 == 100
assert shift("TABLE", 1) == "UBCMF" and shift("DESK", 1) == "EFTL"
assert walk([("E", 6), ("N", 8), ("W", 6)]) == (0, 8)
sanjay_left = 18 + 9 + 1 # Sanjay stands 9 places beyond Rohit
assert sanjay_left == 28 and sanjay_left + 14 - 1 == 41
assert datetime.date(2025, 3, 5).strftime("%A") == "Wednesday" and datetime.date(2026, 3, 5).strftime("%A") == "Thursday"
assert [n for n in (16, 25, 36, 48, 49) if round(n ** 0.5) ** 2 != n] == [48]
assert [chr_at(pos(a) + 5) + chr_at(pos(b) + 5) for a, b in ("AC", "FH", "KM", "PR")][-1] == "UW"
Answers: 1) 100 (the differences double: 3, 6, 12, 24, 48); 2) EFTL; 3) 8 km due north; 4) the girl is Anil's daughter (his mother's only son is Anil himself); 5) 41 people; 6) Thursday (2025 is not a leap year, so the weekday advances by one); 7) 48 (the others are perfect squares); 8) UW (each letter moves forward by 5).