ssctopper/generators/quant_generator.py

722 lines
33 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Quantitative Aptitude Question Generator for SSC CGL.
Generates ~30,000 template-based math questions across all topics.
"""
import random
import math
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from generators.base import make_question, get_qtid, nearby_wrong, nearby_wrong_float, get_db, insert_questions_batch
SUBJECT = "Quantitative Aptitude"
def gen_number_system(conn, count=800):
questions = []
# Unit digit questions
qtid = get_qtid(conn, SUBJECT, "Arithmetic", "Number System", "Unit digit")
if qtid:
for _ in range(count // 4):
base = random.randint(2, 99)
exp = random.randint(10, 200)
unit = pow(base, exp, 10)
q = make_question(qtid,
f"What is the unit digit of {base}^{exp}?",
str(unit), nearby_wrong(unit, 4),
f"Unit digit of {base}^{exp} = {unit}", random.choice([1,1,2]))
questions.append(q)
# Divisibility
qtid = get_qtid(conn, SUBJECT, "Arithmetic", "Number System", "Divisibility test")
if qtid:
divs = [2, 3, 4, 5, 6, 7, 8, 9, 11]
for _ in range(count // 4):
d = random.choice(divs)
num = random.randint(100, 9999) * d
q = make_question(qtid,
f"Which of the following numbers is divisible by {d}?",
str(num), [str(num + random.randint(1, d-1)) for _ in range(3)],
f"{num} ÷ {d} = {num//d}", 1)
questions.append(q)
# Remainder
qtid = get_qtid(conn, SUBJECT, "Arithmetic", "Number System", "Remainder problems")
if qtid:
for _ in range(count // 4):
divisor = random.randint(3, 20)
quotient = random.randint(10, 200)
remainder = random.randint(0, divisor - 1)
num = divisor * quotient + remainder
q = make_question(qtid,
f"What is the remainder when {num} is divided by {divisor}?",
str(remainder), nearby_wrong(remainder, max(3, divisor)),
f"{num} = {divisor} × {quotient} + {remainder}", 1)
questions.append(q)
# Find the value
qtid = get_qtid(conn, SUBJECT, "Arithmetic", "Number System", "Find the value")
if qtid:
for _ in range(count // 4):
a, b = random.randint(10, 99), random.randint(10, 99)
ops = [(f"{a} × {b}", a*b), (f"{a}² - {b}²", a*a - b*b),
(f"{a}² + {b}²", a*a + b*b)]
expr, ans = random.choice(ops)
q = make_question(qtid, f"Find the value of {expr}.",
str(ans), nearby_wrong(ans),
f"{expr} = {ans}", random.choice([1,2]))
questions.append(q)
return questions
def gen_hcf_lcm(conn, count=500):
questions = []
qtid_hcf = get_qtid(conn, SUBJECT, "Arithmetic", "HCF and LCM", "Find HCF")
qtid_lcm = get_qtid(conn, SUBJECT, "Arithmetic", "HCF and LCM", "Find LCM")
qtid_word = get_qtid(conn, SUBJECT, "Arithmetic", "HCF and LCM", "Word problems on HCF/LCM")
for _ in range(count // 3):
a, b = random.randint(10, 200), random.randint(10, 200)
h = math.gcd(a, b)
l = (a * b) // h
if qtid_hcf:
questions.append(make_question(qtid_hcf,
f"Find the HCF of {a} and {b}.", str(h), nearby_wrong(h),
f"HCF({a}, {b}) = {h}", 1))
if qtid_lcm:
questions.append(make_question(qtid_lcm,
f"Find the LCM of {a} and {b}.", str(l), nearby_wrong(l),
f"LCM({a}, {b}) = {l}", 1))
if qtid_word:
for _ in range(count // 3):
h = random.randint(5, 30)
m1, m2 = random.randint(2, 6), random.randint(2, 6)
a, b = h * m1, h * m2
questions.append(make_question(qtid_word,
f"Two ropes of lengths {a} cm and {b} cm are to be cut into pieces of equal length. What is the maximum length of each piece?",
str(h) + " cm", [str(h+i) + " cm" for i in [1, 2, -1]],
f"HCF({a}, {b}) = {h} cm", 1))
return questions
def gen_simplification(conn, count=600):
questions = []
qtid = get_qtid(conn, SUBJECT, "Arithmetic", "Simplification", "Simplify expression")
if not qtid:
return questions
for _ in range(count):
a, b, c = random.randint(2, 50), random.randint(2, 50), random.randint(1, 30)
templates = [
(f"{a} + {b} × {c}", a + b * c),
(f"{a} × {b} - {c}", a * b - c),
(f"({a} + {b}) × {c}", (a + b) * c),
(f"{a}² - {b} × {c}", a*a - b * c),
(f"{a} + {b}² - {c}", a + b*b - c),
]
expr, ans = random.choice(templates)
questions.append(make_question(qtid, f"Simplify: {expr}",
str(ans), nearby_wrong(ans), f"{expr} = {ans}", random.choice([1,1,2])))
return questions
def gen_percentage(conn, count=2000):
questions = []
# Basic percentage
qtid = get_qtid(conn, SUBJECT, "Percentage", "Basic Percentage", "Find X% of Y")
if qtid:
for _ in range(count // 4):
pct = random.choice([5, 10, 12, 15, 16, 20, 25, 30, 33, 40, 50, 60, 75])
val = random.randint(50, 5000)
ans = val * pct / 100
if ans == int(ans):
ans = int(ans)
questions.append(make_question(qtid,
f"What is {pct}% of {val}?", str(ans), nearby_wrong(ans),
f"{pct}% of {val} = {val} × {pct}/100 = {ans}", 1))
qtid = get_qtid(conn, SUBJECT, "Percentage", "Basic Percentage", "What percent is X of Y")
if qtid:
for _ in range(count // 4):
total = random.randint(50, 1000)
part = random.randint(1, total)
pct = round(part * 100 / total, 2)
questions.append(make_question(qtid,
f"What percentage is {part} of {total}?", str(pct) + "%",
[str(round(pct + random.uniform(-10, 10), 2)) + "%" for _ in range(3)],
f"{part}/{total} × 100 = {pct}%", 1))
qtid = get_qtid(conn, SUBJECT, "Percentage", "Basic Percentage", "Percentage change")
if qtid:
for _ in range(count // 4):
old = random.randint(100, 5000)
change = random.randint(5, 50)
direction = random.choice(["increased", "decreased"])
new_val = old + old * change // 100 if direction == "increased" else old - old * change // 100
questions.append(make_question(qtid,
f"If a value {direction} from {old} to {new_val}, what is the percentage change?",
str(change) + "%", [str(change + i) + "%" for i in [2, -3, 5]],
f"Change = {abs(new_val-old)}/{old} × 100 = {change}%", 1))
# Successive percentage
qtid = get_qtid(conn, SUBJECT, "Percentage", "Successive Percentage", "Net percentage change")
if qtid:
for _ in range(count // 4):
p1, p2 = random.randint(5, 40), random.randint(5, 40)
net = round(p1 + p2 + p1 * p2 / 100, 2)
questions.append(make_question(qtid,
f"If a price increases by {p1}% and then by {p2}%, what is the net percentage increase?",
str(net) + "%", nearby_wrong_float(net),
f"Net = {p1} + {p2} + ({p1}×{p2})/100 = {net}%", 2))
return questions
def gen_profit_loss(conn, count=2000):
questions = []
qtid = get_qtid(conn, SUBJECT, "Profit and Loss", "Basic Profit and Loss", "Find profit/loss percentage")
if qtid:
for _ in range(count // 3):
cp = random.randint(100, 5000)
margin = random.randint(5, 50)
is_profit = random.choice([True, False])
sp = cp + cp * margin // 100 if is_profit else cp - cp * margin // 100
word = "profit" if is_profit else "loss"
questions.append(make_question(qtid,
f"An article bought for ₹{cp} is sold for ₹{sp}. Find the {word} percentage.",
str(margin) + "%", [str(margin + i) + "%" for i in [2, -3, 5]],
f"{word.title()} = {abs(sp-cp)}/{cp} × 100 = {margin}%", 1))
qtid = get_qtid(conn, SUBJECT, "Profit and Loss", "Discount and Marked Price", "Find selling price after discount")
if qtid:
for _ in range(count // 3):
mp = random.randint(200, 10000)
d = random.choice([5, 10, 15, 20, 25, 30, 40, 50])
sp = mp - mp * d // 100
questions.append(make_question(qtid,
f"The marked price of an article is ₹{mp}. If a discount of {d}% is given, find the selling price.",
f"{sp}", [f"{sp + i*10}" for i in [1, -2, 3]],
f"SP = {mp} - {d}% of {mp} = ₹{sp}", 1))
qtid = get_qtid(conn, SUBJECT, "Profit and Loss", "Discount and Marked Price", "Find single equivalent discount")
if qtid:
for _ in range(count // 3):
d1, d2 = random.choice([10,15,20,25,30]), random.choice([5,10,15,20])
eq = round(d1 + d2 - d1 * d2 / 100, 2)
questions.append(make_question(qtid,
f"Find the single equivalent discount for successive discounts of {d1}% and {d2}%.",
str(eq) + "%", nearby_wrong_float(eq),
f"Equivalent = {d1} + {d2} - ({d1}×{d2})/100 = {eq}%", 2))
return questions
def gen_ratio(conn, count=1800):
questions = []
qtid = get_qtid(conn, SUBJECT, "Ratio and Proportion", "Basic Ratio", "Divide in given ratio")
if qtid:
for _ in range(count // 4):
a, b = random.randint(1, 10), random.randint(1, 10)
total = (a + b) * random.randint(10, 100)
part_a, part_b = total * a // (a + b), total * b // (a + b)
questions.append(make_question(qtid,
f"Divide ₹{total} in the ratio {a}:{b}. Find the larger share.",
f"{max(part_a, part_b)}", [f"{max(part_a,part_b) + i*10}" for i in [1,-2,3]],
f"Larger share = {total} × {max(a,b)}/{a+b} = ₹{max(part_a,part_b)}", 1))
qtid = get_qtid(conn, SUBJECT, "Ratio and Proportion", "Mixture and Alligation", "Mean price of mixture")
if qtid:
for _ in range(count // 4):
p1, p2 = random.randint(20, 60), random.randint(60, 120)
q1, q2 = random.randint(1, 10), random.randint(1, 10)
mean = round((p1*q1 + p2*q2) / (q1+q2), 2)
questions.append(make_question(qtid,
f"If {q1} kg of rice at ₹{p1}/kg is mixed with {q2} kg of rice at ₹{p2}/kg, find the price of the mixture per kg.",
f"{mean}", [f"{round(mean+i,2)}" for i in [2,-3,5]],
f"Mean = ({p1}×{q1} + {p2}×{q2})/{q1+q2} = ₹{mean}", 2))
qtid = get_qtid(conn, SUBJECT, "Ratio and Proportion", "Partnership", "Divide profit among partners")
if qtid:
for _ in range(count // 4):
inv_a = random.randint(1000, 10000)
inv_b = random.randint(1000, 10000)
profit = random.randint(5000, 50000)
share_a = round(profit * inv_a / (inv_a + inv_b))
questions.append(make_question(qtid,
f"A invests ₹{inv_a} and B invests ₹{inv_b}. Total profit is ₹{profit}. Find A's share.",
f"{share_a}", [f"{share_a + i*100}" for i in [1,-2,3]],
f"A's share = {profit} × {inv_a}/({inv_a}+{inv_b}) = ₹{share_a}", 2))
qtid = get_qtid(conn, SUBJECT, "Ratio and Proportion", "Proportion", "Find fourth proportional")
if qtid:
for _ in range(count // 4):
a, b, c = random.randint(2, 20), random.randint(2, 20), random.randint(2, 20)
d = b * c // a if a != 0 else 1
if a * d == b * c:
questions.append(make_question(qtid,
f"Find the fourth proportional to {a}, {b}, and {c}.",
str(d), nearby_wrong(d),
f"a:b = c:d → d = b×c/a = {b}×{c}/{a} = {d}", 1))
return questions
def gen_average(conn, count=1200):
questions = []
qtid = get_qtid(conn, SUBJECT, "Average", "Simple Average", "Find average")
if qtid:
for _ in range(count // 3):
n = random.randint(3, 8)
nums = [random.randint(10, 100) for _ in range(n)]
avg = round(sum(nums) / n, 2)
nums_str = ", ".join(map(str, nums))
questions.append(make_question(qtid,
f"Find the average of {nums_str}.",
str(avg), nearby_wrong_float(avg),
f"Average = {sum(nums)}/{n} = {avg}", 1))
qtid = get_qtid(conn, SUBJECT, "Average", "Simple Average", "Average after adding/removing")
if qtid:
for _ in range(count // 3):
n = random.randint(5, 15)
avg = random.randint(20, 80)
new_val = random.randint(avg + 5, avg + 50)
new_avg = round((avg * n + new_val) / (n + 1), 2)
questions.append(make_question(qtid,
f"The average of {n} numbers is {avg}. When a new number {new_val} is added, what is the new average?",
str(new_avg), nearby_wrong_float(new_avg),
f"New avg = ({avg}×{n} + {new_val})/{n+1} = {new_avg}", 2))
qtid = get_qtid(conn, SUBJECT, "Average", "Age Problems", "Average age of family")
if qtid:
for _ in range(count // 3):
n = random.randint(3, 6)
avg_age = random.randint(20, 40)
baby_age = random.randint(1, 5)
new_avg = round((avg_age * n + baby_age) / (n + 1), 2)
questions.append(make_question(qtid,
f"The average age of {n} members of a family is {avg_age} years. A baby of {baby_age} year(s) is born. Find the new average age.",
str(new_avg) + " years", [str(round(new_avg+i,2)) + " years" for i in [1,-2,3]],
f"New avg = ({avg_age}×{n} + {baby_age})/{n+1} = {new_avg} years", 1))
return questions
def gen_time_work(conn, count=1500):
questions = []
qtid = get_qtid(conn, SUBJECT, "Time and Work", "Basic Time and Work", "Find combined time")
if qtid:
for _ in range(count // 3):
a, b = random.randint(5, 30), random.randint(5, 30)
combined = round(a * b / (a + b), 2)
questions.append(make_question(qtid,
f"A can do a work in {a} days and B can do it in {b} days. In how many days can they do it together?",
str(combined) + " days", [str(round(combined+i,2)) + " days" for i in [1,-2,3]],
f"Together = {a}×{b}/({a}+{b}) = {combined} days", 2))
qtid = get_qtid(conn, SUBJECT, "Time and Work", "Pipes and Cisterns", "Time to fill tank")
if qtid:
for _ in range(count // 3):
a, b = random.randint(5, 30), random.randint(5, 30)
combined = round(a * b / (a + b), 2)
questions.append(make_question(qtid,
f"Two pipes can fill a tank in {a} hours and {b} hours respectively. How long to fill the tank if both are opened?",
str(combined) + " hours", [str(round(combined+i,2)) + " hours" for i in [1,-2,3]],
f"Together = {a}×{b}/({a}+{b}) = {combined} hours", 2))
qtid = get_qtid(conn, SUBJECT, "Time and Work", "Work and Wages", "Divide wages")
if qtid:
for _ in range(count // 3):
da, db = random.randint(5, 20), random.randint(5, 20)
wage = random.randint(1000, 10000)
eff_a, eff_b = 1/da, 1/db
share_a = round(wage * eff_a / (eff_a + eff_b))
questions.append(make_question(qtid,
f"A can do a work in {da} days and B in {db} days. For a total wage of ₹{wage}, find A's share.",
f"{share_a}", [f"{share_a + i*50}" for i in [1,-2,3]],
f"A's share = ₹{wage} × (1/{da}) / (1/{da} + 1/{db}) = ₹{share_a}", 2))
return questions
def gen_speed_distance(conn, count=2000):
questions = []
qtid = get_qtid(conn, SUBJECT, "Time, Speed and Distance", "Basic Speed and Distance", "Average speed")
if qtid:
for _ in range(count // 4):
s1, s2 = random.randint(20, 80), random.randint(20, 80)
avg = round(2 * s1 * s2 / (s1 + s2), 2)
questions.append(make_question(qtid,
f"A person goes from A to B at {s1} km/h and returns at {s2} km/h. Find the average speed.",
str(avg) + " km/h", [str(round(avg+i,2)) + " km/h" for i in [2,-3,5]],
f"Avg speed = 2×{s1}×{s2}/({s1}+{s2}) = {avg} km/h", 2))
qtid = get_qtid(conn, SUBJECT, "Time, Speed and Distance", "Trains", "Train passing pole")
if qtid:
for _ in range(count // 4):
length = random.randint(100, 500)
speed_kmh = random.randint(36, 144)
speed_ms = round(speed_kmh * 5 / 18, 2)
time = round(length / speed_ms, 2)
questions.append(make_question(qtid,
f"A train {length}m long passes a pole in {time} seconds. Find its speed in km/h.",
str(speed_kmh) + " km/h", [str(speed_kmh + i) + " km/h" for i in [4,-6,9]],
f"Speed = {length}/{time} m/s = {speed_kmh} km/h", 2))
qtid = get_qtid(conn, SUBJECT, "Time, Speed and Distance", "Boats and Streams", "Find speed in still water")
if qtid:
for _ in range(count // 4):
boat = random.randint(10, 30)
stream = random.randint(2, 8)
ds = boat + stream
us = boat - stream
questions.append(make_question(qtid,
f"A boat goes {ds} km/h downstream and {us} km/h upstream. Find speed in still water.",
str(boat) + " km/h", [str(boat + i) + " km/h" for i in [1, -2, 3]],
f"Speed = ({ds}+{us})/2 = {boat} km/h", 1))
qtid = get_qtid(conn, SUBJECT, "Time, Speed and Distance", "Basic Speed and Distance", "Find distance")
if qtid:
for _ in range(count // 4):
speed = random.randint(20, 100)
time = random.randint(1, 10)
dist = speed * time
questions.append(make_question(qtid,
f"A car travels at {speed} km/h for {time} hours. Find the distance covered.",
str(dist) + " km", nearby_wrong(dist),
f"Distance = {speed} × {time} = {dist} km", 1))
return questions
def gen_interest(conn, count=1500):
questions = []
qtid = get_qtid(conn, SUBJECT, "Interest", "Simple Interest", "Find SI")
if qtid:
for _ in range(count // 3):
p = random.choice([1000, 2000, 5000, 8000, 10000, 15000, 20000])
r = random.choice([4, 5, 6, 8, 10, 12, 15])
t = random.randint(1, 5)
si = p * r * t // 100
questions.append(make_question(qtid,
f"Find the simple interest on ₹{p} at {r}% per annum for {t} years.",
f"{si}", [f"{si + i*50}" for i in [1,-2,3]],
f"SI = {p}×{r}×{t}/100 = ₹{si}", 1))
qtid = get_qtid(conn, SUBJECT, "Interest", "Compound Interest", "Find CI")
if qtid:
for _ in range(count // 3):
p = random.choice([1000, 2000, 5000, 10000])
r = random.choice([5, 10, 15, 20])
t = random.choice([1, 2, 3])
amt = round(p * (1 + r/100)**t, 2)
ci = round(amt - p, 2)
questions.append(make_question(qtid,
f"Find the compound interest on ₹{p} at {r}% for {t} year(s).",
f"{ci}", [f"{round(ci+i*20,2)}" for i in [1,-2,3]],
f"CI = {p}(1+{r}/100)^{t} - {p} = ₹{ci}", 2))
qtid = get_qtid(conn, SUBJECT, "Interest", "Compound Interest", "Difference between CI and SI")
if qtid:
for _ in range(count // 3):
p = random.choice([1000, 2000, 5000, 10000])
r = random.choice([5, 10, 15, 20])
si = p * r * 2 // 100
ci = round(p * (1 + r/100)**2 - p, 2)
diff = round(ci - si, 2)
questions.append(make_question(qtid,
f"Find the difference between CI and SI on ₹{p} at {r}% for 2 years.",
f"{diff}", [f"{round(diff+i*5,2)}" for i in [1,-2,3]],
f"Diff = P×(r/100)² = {p}×({r}/100)² = ₹{diff}", 2))
return questions
def gen_algebra(conn, count=2000):
questions = []
qtid = get_qtid(conn, SUBJECT, "Algebra", "Linear Equations", "Solve for x")
if qtid:
for _ in range(count // 4):
a = random.randint(2, 15)
x = random.randint(1, 30)
b = random.randint(1, 50)
c = a * x + b
questions.append(make_question(qtid,
f"Solve: {a}x + {b} = {c}",
f"x = {x}", [f"x = {x+i}" for i in [1,-2,3]],
f"{a}x = {c} - {b} = {c-b}, x = {x}", 1))
qtid = get_qtid(conn, SUBJECT, "Algebra", "Algebraic Identities", "Find value of expression")
if qtid:
for _ in range(count // 4):
a, b = random.randint(2, 20), random.randint(1, 15)
val = a*a + b*b + 2*a*b # (a+b)²
questions.append(make_question(qtid,
f"If a = {a} and b = {b}, find a² + b² + 2ab.",
str(val), nearby_wrong(val),
f"a² + b² + 2ab = (a+b)² = ({a}+{b})² = {val}", 1))
qtid = get_qtid(conn, SUBJECT, "Algebra", "Surds and Indices", "Find value")
if qtid:
for _ in range(count // 4):
base = random.randint(2, 10)
exp = random.randint(2, 5)
val = base ** exp
questions.append(make_question(qtid,
f"Find the value of {base}^{exp}.",
str(val), nearby_wrong(val),
f"{base}^{exp} = {val}", 1))
qtid = get_qtid(conn, SUBJECT, "Algebra", "Quadratic Equations", "Sum and product of roots")
if qtid:
for _ in range(count // 4):
r1, r2 = random.randint(-10, 10), random.randint(-10, 10)
a = 1
b = -(r1 + r2)
c = r1 * r2
s = r1 + r2
questions.append(make_question(qtid,
f"Find the sum of roots of x² + ({b})x + ({c}) = 0.",
str(s), nearby_wrong(s),
f"Sum = -b/a = {s}", 1))
return questions
def gen_geometry(conn, count=2000):
questions = []
qtid = get_qtid(conn, SUBJECT, "Geometry", "Triangles", "Find angle in triangle")
if qtid:
for _ in range(count // 4):
a = random.randint(20, 80)
b = random.randint(20, 160 - a)
c = 180 - a - b
questions.append(make_question(qtid,
f"In a triangle, two angles are {a}° and {b}°. Find the third angle.",
f"{c}°", [f"{c+i}°" for i in [5,-10,15]],
f"Third angle = 180 - {a} - {b} = {c}°", 1))
qtid = get_qtid(conn, SUBJECT, "Geometry", "Circles", "Tangent properties")
if qtid:
for _ in range(count // 4):
r = random.randint(3, 20)
d = random.randint(r + 5, r + 30)
tangent = round(math.sqrt(d*d - r*r), 2)
questions.append(make_question(qtid,
f"The radius of a circle is {r} cm and a point is {d} cm from the center. Find the length of the tangent.",
str(tangent) + " cm", [str(round(tangent+i,2)) + " cm" for i in [1,-2,3]],
f"Tangent = √({d}²-{r}²) = {tangent} cm", 2))
qtid = get_qtid(conn, SUBJECT, "Geometry", "Coordinate Geometry", "Find distance between points")
if qtid:
for _ in range(count // 4):
x1, y1 = random.randint(-10, 10), random.randint(-10, 10)
x2, y2 = random.randint(-10, 10), random.randint(-10, 10)
dist = round(math.sqrt((x2-x1)**2 + (y2-y1)**2), 2)
questions.append(make_question(qtid,
f"Find the distance between ({x1}, {y1}) and ({x2}, {y2}).",
str(dist), nearby_wrong_float(dist),
f"Distance = √[({x2}-{x1})² + ({y2}-{y1})²] = {dist}", 2))
qtid = get_qtid(conn, SUBJECT, "Geometry", "Lines and Angles", "Find angle value")
if qtid:
for _ in range(count // 4):
angle = random.randint(10, 170)
supp = 180 - angle
questions.append(make_question(qtid,
f"Find the supplement of {angle}°.",
f"{supp}°", [f"{supp+i}°" for i in [5,-10,15]],
f"Supplement = 180 - {angle} = {supp}°", 1))
return questions
def gen_mensuration(conn, count=2000):
questions = []
qtid = get_qtid(conn, SUBJECT, "Mensuration", "2D Figures", "Find area")
if qtid:
for _ in range(count // 4):
l, w = random.randint(5, 50), random.randint(5, 50)
area = l * w
questions.append(make_question(qtid,
f"Find the area of a rectangle with length {l} cm and width {w} cm.",
f"{area} cm²", [f"{area+i*5} cm²" for i in [1,-2,3]],
f"Area = {l} × {w} = {area} cm²", 1))
for _ in range(count // 4):
r = random.randint(3, 25)
area = round(math.pi * r * r, 2)
questions.append(make_question(qtid,
f"Find the area of a circle with radius {r} cm. (Use π = 3.14)",
str(round(3.14 * r * r, 2)) + " cm²",
[str(round(3.14 * r * r + i * 5, 2)) + " cm²" for i in [1, -2, 3]],
f"Area = πr² = 3.14 × {r}² = {round(3.14*r*r,2)} cm²", 1))
qtid = get_qtid(conn, SUBJECT, "Mensuration", "3D Figures", "Find volume")
if qtid:
for _ in range(count // 4):
l, w, h = random.randint(3, 20), random.randint(3, 20), random.randint(3, 20)
vol = l * w * h
questions.append(make_question(qtid,
f"Find the volume of a cuboid with dimensions {l}×{w}×{h} cm.",
f"{vol} cm³", [f"{vol+i*10} cm³" for i in [1,-2,3]],
f"Volume = {l}×{w}×{h} = {vol} cm³", 1))
qtid = get_qtid(conn, SUBJECT, "Mensuration", "3D Figures", "Find surface area")
if qtid:
for _ in range(count // 4):
a = random.randint(3, 20)
sa = 6 * a * a
questions.append(make_question(qtid,
f"Find the total surface area of a cube with side {a} cm.",
f"{sa} cm²", [f"{sa+i*6} cm²" for i in [1,-2,3]],
f"TSA = 6a² = 6×{a}² = {sa} cm²", 1))
return questions
def gen_trigonometry(conn, count=1500):
questions = []
trig_vals = {0: {'sin': 0, 'cos': 1, 'tan': 0},
30: {'sin': 0.5, 'cos': 0.866, 'tan': 0.577},
45: {'sin': 0.707, 'cos': 0.707, 'tan': 1},
60: {'sin': 0.866, 'cos': 0.5, 'tan': 1.732},
90: {'sin': 1, 'cos': 0, 'tan': 'undefined'}}
qtid = get_qtid(conn, SUBJECT, "Trigonometry", "Trigonometric Ratios", "Find value of expression")
if qtid:
for _ in range(count // 3):
ang = random.choice([0, 30, 45, 60])
func = random.choice(['sin', 'cos', 'tan'])
val = trig_vals[ang][func]
if isinstance(val, (int, float)):
questions.append(make_question(qtid,
f"Find the value of {func}({ang}°).",
str(val), nearby_wrong_float(val if val != 0 else 0.5),
f"{func}({ang}°) = {val}", 1))
qtid = get_qtid(conn, SUBJECT, "Trigonometry", "Trigonometric Identities", "Find value given condition")
if qtid:
for _ in range(count // 3):
ang = random.choice([30, 45, 60])
val = trig_vals[ang]['sin']**2 + trig_vals[ang]['cos']**2
questions.append(make_question(qtid,
f"Find the value of sin²({ang}°) + cos²({ang}°).",
"1", ["0", "2", "0.5"],
f"sin²θ + cos²θ = 1 (identity)", 1))
qtid = get_qtid(conn, SUBJECT, "Trigonometry", "Heights and Distances", "Find height of tower")
if qtid:
for _ in range(count // 3):
dist = random.randint(20, 100)
ang = random.choice([30, 45, 60])
height = round(dist * trig_vals[ang]['tan'], 2) if ang != 90 else dist
questions.append(make_question(qtid,
f"From a point {dist}m from the base of a tower, the angle of elevation is {ang}°. Find the height.",
str(height) + " m", [str(round(height+i,2)) + " m" for i in [2,-5,8]],
f"h = {dist} × tan({ang}°) = {height} m", 2))
return questions
def gen_di(conn, count=1500):
questions = []
qtid = get_qtid(conn, SUBJECT, "Data Interpretation", "Table", "Calculate from table")
if qtid:
for _ in range(count // 2):
vals = [random.randint(100, 1000) for _ in range(5)]
total = sum(vals)
avg = round(total / 5, 2)
years = ["2019", "2020", "2021", "2022", "2023"]
table = ", ".join(f"{y}: {v}" for y, v in zip(years, vals))
questions.append(make_question(qtid,
f"Production (in units) - {table}. Find the total production.",
str(total), nearby_wrong(total),
f"Total = {'+'.join(map(str, vals))} = {total}", 1))
qtid = get_qtid(conn, SUBJECT, "Data Interpretation", "Table", "Percentage calculation")
if qtid:
for _ in range(count // 2):
vals = [random.randint(100, 1000) for _ in range(5)]
idx = random.randint(0, 4)
total = sum(vals)
pct = round(vals[idx] * 100 / total, 2)
years = ["2019", "2020", "2021", "2022", "2023"]
table = ", ".join(f"{y}: {v}" for y, v in zip(years, vals))
questions.append(make_question(qtid,
f"Sales - {table}. What percentage of total sales occurred in {years[idx]}?",
str(pct) + "%", [str(round(pct+i,2)) + "%" for i in [2,-3,5]],
f"{vals[idx]}/{total} × 100 = {pct}%", 2))
return questions
def gen_statistics(conn, count=800):
questions = []
qtid = get_qtid(conn, SUBJECT, "Statistics", "Mean, Median and Mode", "Find mean")
if qtid:
for _ in range(count // 3):
n = random.randint(5, 10)
nums = sorted([random.randint(1, 100) for _ in range(n)])
mean = round(sum(nums) / n, 2)
questions.append(make_question(qtid,
f"Find the mean of: {', '.join(map(str, nums))}",
str(mean), nearby_wrong_float(mean),
f"Mean = {sum(nums)}/{n} = {mean}", 1))
qtid = get_qtid(conn, SUBJECT, "Statistics", "Mean, Median and Mode", "Find median")
if qtid:
for _ in range(count // 3):
n = random.choice([5, 7, 9])
nums = sorted([random.randint(1, 100) for _ in range(n)])
median = nums[n // 2]
questions.append(make_question(qtid,
f"Find the median of: {', '.join(map(str, nums))}",
str(median), nearby_wrong(median),
f"Sorted: {nums}, Median = {median}", 1))
qtid = get_qtid(conn, SUBJECT, "Statistics", "Mean, Median and Mode", "Find mode")
if qtid:
for _ in range(count // 3):
mode_val = random.randint(1, 50)
nums = [mode_val] * 3 + [random.randint(1, 100) for _ in range(4)]
random.shuffle(nums)
questions.append(make_question(qtid,
f"Find the mode of: {', '.join(map(str, nums))}",
str(mode_val), nearby_wrong(mode_val),
f"Mode = {mode_val} (appears most)", 1))
return questions
def generate_all(conn):
"""Generate all Quantitative Aptitude questions."""
generators = [
("Number System", gen_number_system, 800),
("HCF/LCM", gen_hcf_lcm, 500),
("Simplification", gen_simplification, 600),
("Percentage", gen_percentage, 2500),
("Profit & Loss", gen_profit_loss, 2500),
("Ratio & Proportion", gen_ratio, 2200),
("Average", gen_average, 1500),
("Time & Work", gen_time_work, 1800),
("Speed & Distance", gen_speed_distance, 2500),
("Interest", gen_interest, 2000),
("Algebra", gen_algebra, 2500),
("Geometry", gen_geometry, 2500),
("Mensuration", gen_mensuration, 2500),
("Trigonometry", gen_trigonometry, 2000),
("Data Interpretation", gen_di, 2000),
("Statistics", gen_statistics, 1200),
]
total = 0
all_questions = []
for name, gen_func, count in generators:
questions = gen_func(conn, count)
all_questions.extend(questions)
print(f" {name}: {len(questions)} questions")
total += len(questions)
# Insert in batches
batch_size = 5000
for i in range(0, len(all_questions), batch_size):
insert_questions_batch(conn, all_questions[i:i+batch_size])
print(f" TOTAL Quantitative Aptitude: {total}")
return total
if __name__ == '__main__':
conn = get_db()
print("Generating Quantitative Aptitude questions...")
generate_all(conn)
conn.close()