from common import *
from fractions import Fraction as F
from math import gcd, comb, factorial, sqrt, isqrt
B = Bank("mathematics", seed=11)
def fr(x): x=F(x); return str(x.numerator) if x.denominator==1 else f"{x.numerator}/{x.denominator}"
def lcm(a,b): return a*b//gcd(a,b)
R = lambda r,a,b: r.randint(a,b)

def t_arith(r):
    a,b,c=R(r,12,99),R(r,3,19),R(r,10,200); v=a*b+c
    return B.add(f"Evaluate {a} × {b} + {c}.", v, near(r,v,[a*(b+c),a+b*c,a*b-c]), "Number and Numeration","Easy")
def t_pct(r):
    p=r.choice([5,10,15,20,25,30,35,40,45,50,60,75]); n=R(r,2,60)*20; v=F(p*n,100)
    return B.add(f"Find {p}% of {n}.", fr(v), [fr(v+d) for d in (p,-p//2 or 1,10,-10,5)],"Number and Numeration","Easy")
def t_lcmhcf(r):
    a,b=R(r,4,40),R(r,4,40)
    if a==b: return False
    if r.random()<.5: v=lcm(a,b); return B.add(f"Find the LCM of {a} and {b}.", v, [a*b if a*b!=v else a+b, v+a, v-b if v-b>0 else v+b, gcd(a,b)+v] ,"Number and Numeration")
    v=gcd(a,b); return B.add(f"Find the HCF of {a} and {b}.", v, [v+1,v*2,lcm(a,b),v+2,a-b if a>b else b-a],"Number and Numeration")
def t_ratio(r):
    a,b=R(r,1,9),R(r,1,9)
    if a==b: return False
    k=R(r,3,30); tot=(a+b)*k; v=a*k
    return B.add(f"Share ₦{tot*100:,} in the ratio {a}:{b}. Find the first share (the {a} part).", f"₦{v*100:,}", [f"₦{x*100:,}" for x in (b*k,(a+b)*k//2,v+k,v-k if v>k else v+2*k)],"Number and Numeration")
def t_si(r):
    P=R(r,5,100)*1000; rt=R(r,2,15); T=R(r,1,8); v=P*rt*T//100
    return B.add(f"Calculate the simple interest on ₦{P:,} for {T} year(s) at {rt}% per annum.", f"₦{v:,}", [f"₦{x:,}" for x in (P*rt//100, v+P//100*T, v*2, v+P//10)],"Number and Numeration")
def t_ci(r):
    P=R(r,1,10)*10000; rt=r.choice([10,20,5]); T=2; v=P*(100+rt)**2//10000
    if P*(100+rt)**2%10000: return False
    return B.add(f"Find the compound amount on ₦{P:,} invested for 2 years at {rt}% per annum compounded annually.", f"₦{v:,}", [f"₦{x:,}" for x in (P+P*rt*2//100,v+P*rt//100,v-P*rt//100,P*(100+2*rt)//100+P//10)],"Number and Numeration","Hard")
def t_avg(r):
    n=R(r,4,8); xs=[R(r,2,40) for _ in range(n)]; s=sum(xs)
    if s%n: return False
    v=s//n; return B.add(f"Find the mean of {', '.join(map(str,xs))}.", v, near(r,v,[sorted(xs)[n//2],max(xs)-min(xs)]),"Statistics","Easy")
def t_median(r):
    n=r.choice([5,7,9]); xs=r.sample(range(1,60),n); v=sorted(xs)[n//2]
    return B.add(f"Find the median of {', '.join(map(str,xs))}.", v, [sorted(xs)[n//2-1],sorted(xs)[n//2+1],sum(xs)//n,max(xs)],"Statistics")
def t_mode(r):
    xs=r.sample(range(1,30),5); m=r.choice(xs); lst=xs+[m,m]; r.shuffle(lst)
    return B.add(f"Find the mode of {', '.join(map(str,lst))}.", m, [x for x in xs if x!=m],"Statistics","Easy")
def t_linear(r):
    x=R(r,-9,15); a=R(r,2,9); b=R(r,-20,20); c=a*x+b
    if x==0: return False
    return B.add(f"Solve for x: {a}x {'+' if b>=0 else '−'} {abs(b)} = {c}.", x, near(r,x,[(c+b)//a if a else 0, (c-b)//a+1]),"Algebra","Easy") if b!=0 else False
def t_simul(r):
    x,y=R(r,-6,9),R(r,-6,9); a,b,c,d=R(r,1,5),R(r,1,5),R(r,1,5),R(r,1,5)
    if a*d-b*c==0 or x==y: return False
    return B.add(f"If {a}x + {b}y = {a*x+b*y} and {c}x + {d}y = {c*x+d*y}, find x + y.", x+y, near(r,x+y,[x-y,x*y,y]),"Algebra","Hard")
def t_quad(r):
    p,q=R(r,-9,9),R(r,-9,9)
    if p==q or p==0 or q==0: return False
    b,c=-(p+q),p*q
    f=lambda n:("+ " if n>=0 else "− ")+str(abs(n))
    return B.add(f"Find the roots of x² {f(b)}x {f(c)} = 0.", f"x = {min(p,q)} or x = {max(p,q)}", [f"x = {-min(p,q)} or x = {-max(p,q)}", f"x = {min(p,q)} or x = {-max(p,q)}", f"x = {-min(p,q)} or x = {max(p,q)}", f"x = {p+q} or x = {p*q}"],"Algebra")
def t_sumprod_roots(r):
    p,q=R(r,-8,9),R(r,-8,9)
    if p==q: return False
    f=lambda n:("+ " if n>=0 else "− ")+str(abs(n))
    return B.add(f"What is the sum of the roots of x² {f(-(p+q))}x {f(p*q)} = 0?", p+q, [-(p+q),p*q,-p*q,p+q+1],"Algebra")
def t_indices(r):
    b=r.choice([2,3,5]); m,n=R(r,2,9),R(r,2,9)
    if r.random()<.5: v=b**(m+n); return B.add(f"Simplify {b}^{m} × {b}^{n} as a single power of {b}.", f"{b}^{m+n}", [f"{b}^{m*n}",f"{b*b}^{m+n}",f"{b}^{abs(m-n)}",f"{b}^{m+n+1}"],"Algebra","Easy")
    if m==n: return False
    return B.add(f"Simplify {b}^{max(m,n)} ÷ {b}^{min(m,n)}.", f"{b}^{abs(m-n)}", [f"{b}^{m+n}",f"{b}^{m*n}",f"{b}^{max(m,n)//min(m,n)}",f"{b}^{abs(m-n)+1}"],"Algebra","Easy")
def t_log(r):
    b=r.choice([2,3,4,5,10]); n=R(r,2,5)
    return B.add(f"Evaluate log base {b} of {b**n}.", n, near(r,n,[b,b*n]),"Algebra","Easy")
def t_circle(r):
    rad=R(r,1,10)*7; 
    if r.random()<.5: v=F(22,7)*rad*rad; return B.add(f"Find the area of a circle of radius {rad} cm. (Take π = 22/7)", f"{fr(v)} cm²", [f"{fr(v*2)} cm²",f"{fr(F(44,7)*rad)} cm²",f"{fr(v/2)} cm²",f"{fr(F(22,7)*rad)} cm²"],"Mensuration")
    v=F(44,7)*rad; return B.add(f"Calculate the circumference of a circle of radius {rad} cm. (Take π = 22/7)", f"{fr(v)} cm", [f"{fr(v*rad/2)} cm",f"{fr(v/2)} cm",f"{fr(v*2)} cm",f"{fr(v+rad)} cm"],"Mensuration")
def t_cyl(r):
    rad=R(r,1,6)*7; h=R(r,2,15); v=F(22,7)*rad*rad*h
    return B.add(f"Find the volume of a cylinder of radius {rad} cm and height {h} cm. (π = 22/7)", f"{fr(v)} cm³", [f"{fr(v/h)} cm³",f"{fr(v*2)} cm³",f"{fr(v/3)} cm³",f"{fr(F(44,7)*rad*h)} cm³"],"Mensuration","Medium")
def t_pyth(r):
    a,b,c=r.choice([(3,4,5),(5,12,13),(8,15,17),(7,24,25),(20,21,29),(9,40,41)]); k=R(r,1,6)
    if r.random()<.5: return B.add(f"A right-angled triangle has legs {a*k} cm and {b*k} cm. Find its hypotenuse.", f"{c*k} cm", [f"{(a+b)*k} cm",f"{c*k+k} cm",f"{c*k-1} cm",f"{b*k+a} cm"],"Geometry","Easy")
    return B.add(f"The hypotenuse of a right-angled triangle is {c*k} cm and one leg is {a*k} cm. Find the other leg.", f"{b*k} cm", [f"{b*k+1} cm",f"{c*k-a*k} cm",f"{b*k-1} cm",f"{(c+a)*k} cm"],"Geometry")
def t_polygon(r):
    n=R(r,5,16); v=(n-2)*180
    if r.random()<.5: return B.add(f"Find the sum of the interior angles of a polygon with {n} sides.", f"{v}°", [f"{(n-1)*180}°",f"{n*180}°",f"{(n-2)*90}°",f"{360}°"],"Geometry")
    if 360%n: return False
    return B.add(f"Each exterior angle of a regular polygon is {360//n}°. How many sides has the polygon?", n, near(r,n,[n*2,360//n]),"Geometry")
def t_ap(r):
    a,d,n=R(r,-5,20),R(r,2,9),R(r,6,25); v=a+(n-1)*d
    return B.add(f"Find the {n}th term of the arithmetic progression {a}, {a+d}, {a+2*d}, ...", v, [v+d,v-d,a+n*d+d,a*n+d], "Sequence and Series")
def t_apsum(r):
    a,d,n=R(r,1,10),R(r,1,8),R(r,5,20); v=n*(2*a+(n-1)*d)//2
    return B.add(f"Find the sum of the first {n} terms of the AP with first term {a} and common difference {d}.", v, [v+n,v-a*n if v>a*n else v+a*n, n*(a+(n-1)*d), v+d*n],"Sequence and Series","Medium")
def t_gp(r):
    a,rr,n=R(r,1,5),R(r,2,4),R(r,4,7); v=a*rr**(n-1)
    return B.add(f"Find the {n}th term of the geometric progression {a}, {a*rr}, {a*rr*rr}, ...", v, [v*rr,v//rr,a*rr*n,a+(n-1)*rr],"Sequence and Series")
def t_grad(r):
    x1,y1,x2,y2=R(r,-6,6),R(r,-6,6),R(r,-6,6),R(r,-6,6)
    if x1==x2: return False
    m=F(y2-y1,x2-x1)
    return B.add(f"Find the gradient of the line joining ({x1}, {y1}) and ({x2}, {y2}).", fr(m), [fr(-m) if m!=0 else "1", fr(F(x2-x1,y2-y1)) if y2!=y1 else "2", fr(m+1), fr(m-1)],"Coordinate Geometry")
def t_mid(r):
    x1,y1,x2,y2=R(r,-8,8),R(r,-8,8),R(r,-8,8),R(r,-8,8)
    if (x1+x2)%2 or (y1+y2)%2: return False
    return B.add(f"Find the midpoint of the line segment joining ({x1}, {y1}) and ({x2}, {y2}).", f"({(x1+x2)//2}, {(y1+y2)//2})", [f"({x1+x2}, {y1+y2})",f"({(x2-x1)//2 if (x2-x1)%2==0 else 0}, {(y2-y1)//2 if (y2-y1)%2==0 else 0})",f"({(x1+x2)//2+1}, {(y1+y2)//2})",f"({(x1+x2)//2}, {(y1+y2)//2-1})"],"Coordinate Geometry")
def t_dist(r):
    a,b,c=r.choice([(3,4,5),(5,12,13),(6,8,10),(8,15,17)]); x1,y1=R(r,-5,5),R(r,-5,5)
    return B.add(f"Find the distance between ({x1}, {y1}) and ({x1+a}, {y1+b}).", c, [a+b,c+1,c-1,a*b],"Coordinate Geometry")
def t_sets(r):
    a,b,i=R(r,10,40),R(r,10,40),R(r,2,9); u=a+b-i
    return B.add(f"If n(A) = {a}, n(B) = {b} and n(A ∩ B) = {i}, find n(A ∪ B).", u, [a+b,u+i,u-i,a-i+b+i+1],"Sets","Easy")
def t_base(r):
    n=R(r,5,60); 
    if r.random()<.5: return B.add(f"Convert {bin(n)[2:]} (base 2) to base 10.", n, near(r,n,[n+1,n*2]),"Number Bases")
    return B.add(f"Convert {n} (base 10) to base 2.", bin(n)[2:], [bin(n+1)[2:],bin(n-1)[2:] if n>1 else "11",bin(n+2)[2:],bin(n^1)[2:] if bin(n^1)[2:]!=bin(n)[2:] else "101"],"Number Bases")
def t_baseadd(r):
    a,b=R(r,3,25),R(r,3,25); return B.add(f"Add {bin(a)[2:]} and {bin(b)[2:]} in base two.", bin(a+b)[2:], [bin(a+b+1)[2:],bin(a+b-1)[2:],bin(a*b)[2:],bin(a+b+2)[2:]],"Number Bases","Medium")
def t_speed(r):
    s=R(r,20,120); t=R(r,2,9)
    return B.add(f"A car travels at {s} km/h for {t} hours. How far does it travel?", f"{s*t} km", [f"{s+t} km",f"{s*t+s} km",f"{s*t-t} km",f"{s*(t+1)} km"],"Everyday Statistics","Easy")
def t_profit(r):
    cp=R(r,2,20)*100; p=r.choice([10,20,25,30,40,50]); sp=cp*(100+p)//100
    return B.add(f"A trader bought an article for ₦{cp:,} and sold it for ₦{sp:,}. Find the percentage profit.", f"{p}%", [f"{p+5}%",f"{p-5}%",f"{p*2}%",f"{p+10}%"],"Number and Numeration")
def t_prob(r):
    red,blue=R(r,2,9),R(r,2,9); g=gcd(red,red+blue)
    return B.add(f"A bag contains {red} red and {blue} blue balls. What is the probability of picking a red ball at random?", fr(F(red,red+blue)), [fr(F(blue,red+blue)),fr(F(red,blue)),fr(F(1,red+blue)),fr(F(red+1,red+blue+1))],"Probability")
def t_dice(r):
    k=R(r,1,5); return B.add(f"A fair die is thrown once. What is the probability of getting a number greater than {k}?", fr(F(6-k,6)), [fr(F(k,6)),fr(F(6-k,5)),fr(F(7-k,6)),fr(F(1,6))],"Probability","Easy")
def t_var(r):
    k=R(r,2,9); x1,x2=R(r,2,6),R(r,7,12)
    return B.add(f"y varies directly as x. If y = {k*x1} when x = {x1}, find y when x = {x2}.", k*x2, [k*x2+k,(k*x1)+x2,k*x2-k,x2*x1],"Variation")
def t_invvar(r):
    k=R(r,6,36)*2; x1=r.choice([2,3,4,6]); 
    if k%x1: return False
    x2=r.choice([d for d in (1,2,3,4,6,8,12) if k%d==0 and d!=x1] or [0])
    if not x2: return False
    return B.add(f"y varies inversely as x. If y = {k//x1} when x = {x1}, find y when x = {x2}.", k//x2, [k*x2//x1 if (k*x2)%x1==0 else k//x2+3, k//x2+1, k//x2-1 if k//x2>1 else k//x2+4, x1*x2],"Variation","Medium")
def t_subject(r):
    a,b=R(r,2,9),R(r,2,9); 
    if a==b: return False
    return B.add(f"Make x the subject of the formula y = {a}x + {b}.", f"x = (y − {b})/{a}", [f"x = (y + {b})/{a}", f"x = {a}(y − {b})", f"x = y − {b}/{a}", f"x = ({a} − y)/{b}"],"Algebra")
def t_factor(r):
    p,q=R(r,1,9),R(r,1,9)
    if p==q: return False
    return B.add(f"Factorise x² + {p+q}x + {p*q}.", f"(x + {p})(x + {q})", [f"(x − {p})(x − {q})", f"(x + {p*q})(x + 1)", f"(x + {p})(x − {q})", f"(x + {p+1})(x + {q-1})" if q>1 else f"(x + {p+2})(x + {q})"],"Algebra")
def t_diffsq(r):
    a=R(r,2,12); return B.add(f"Factorise completely: x² − {a*a}.", f"(x + {a})(x − {a})", [f"(x − {a})²",f"(x + {a})²",f"(x − {a*a})(x + 1)",f"(x + {a*a})(x − 1)"],"Algebra","Easy")
def t_ineq(r):
    a,b=R(r,2,6),R(r,1,20); c=a*R(r,3,10)+b; v=(c-b)//a
    return B.add(f"Solve the inequality {a}x + {b} < {c}.", f"x < {v}", [f"x > {v}",f"x < {v+1}",f"x ≤ {v}",f"x > {v-1}"],"Algebra")
def t_trig(r):
    t=r.choice([("sin 30°","1/2"),("cos 60°","1/2"),("tan 45°","1"),("cos 30°","√3/2"),("sin 60°","√3/2"),("sin 45°","1/√2"),("tan 60°","√3"),("tan 30°","1/√3"),("cos 45°","1/√2"),("sin 90°","1"),("cos 0°","1"),("cos 90°","0")])
    pool=["1/2","1","√3/2","1/√2","√3","1/√3","0","2"]; 
    return B.add(f"What is the value of {t[0]}?", t[1], [p for p in pool if p!=t[1]][:6] and r.sample([p for p in pool if p!=t[1]],3),"Trigonometry","Easy")
def t_trigsolve(r):
    ang=r.choice([30,45,60]); h=R(r,2,20)*10
    if ang==45: return B.add(f"A ladder leans against a wall making an angle of 45° with the ground. If the top reaches {h} m up the wall, how far is the foot of the ladder from the wall?", f"{h} m", [f"{h*2} m",f"{h//2} m",f"{h+5} m",f"{h-5} m"],"Trigonometry")
    return False
def t_surd(r):
    a=R(r,2,12); k=R(r,2,6); n=a*a*k
    if k in (4,9) or int(sqrt(k))**2==k: return False
    return B.add(f"Simplify √{n}.", f"{a}√{k}", [f"{k}√{a}", f"{a*k}√{a}" if a>1 else f"{k}√{k}", f"{a}√{k+1}", f"{a+k}"],"Surds","Medium")
def t_stdform(r):
    m=R(r,12,98)/10; e=R(r,2,7); n=round(m*10**e)
    return B.add(f"Express {n:,} in standard form.".replace(",",""), f"{m} × 10^{e}", [f"{m} × 10^{e+1}",f"{m} × 10^{e-1}",f"{m*10:g} × 10^{e}",f"{m} × 10^−{e}"],"Number and Numeration")
def t_sigfig(r):
    n=R(r,10000,99999)/1000; v=round(n,1)
    return B.add(f"Express {n} correct to 1 decimal place.", v, [round(n,2),round(n)+0.0,v+0.1,v-0.1],"Number and Numeration","Easy")
def t_angle(r):
    a,b=R(r,20,80),R(r,20,80)
    return B.add(f"Two angles of a triangle are {a}° and {b}°. Find the third angle.", f"{180-a-b}°", [f"{360-a-b}°",f"{90-a}°",f"{180-a}°",f"{a+b}°"],"Geometry","Easy")
def t_trap(r):
    a,b,h=R(r,3,15),R(r,3,15),R(r,2,12)
    if (a+b)*h%2 or a==b: return False
    v=(a+b)*h//2; return B.add(f"Find the area of a trapezium with parallel sides {a} cm and {b} cm and height {h} cm.", f"{v} cm²", [f"{a*b*h//2 if a*b*h%2==0 else v+3} cm²",f"{(a+b)*h} cm²",f"{v+h} cm²",f"{a*h} cm²"],"Mensuration")
def t_fracadd(r):
    a,b,c,d=R(r,1,5),R(r,2,9),R(r,1,5),R(r,2,9)
    if a>=b or c>=d: return False
    v=F(a,b)+F(c,d); return B.add(f"Evaluate {a}/{b} + {c}/{d}.", fr(v), [f"{a+c}/{b+d}",fr(F(a*c,b*d)),fr(v+F(1,b*d)),fr(abs(F(a,b)-F(c,d)))],"Number and Numeration")
def t_fracmult(r):
    a,b,c,d=R(r,1,9),R(r,2,9),R(r,1,9),R(r,2,9); v=F(a,b)*F(c,d)
    return B.add(f"Evaluate ({a}/{b}) × ({c}/{d}).", fr(v), [fr(F(a,b)+F(c,d)),fr(F(a*d,b*c)),fr(v*2),f"{a*c}/{b+d}"],"Number and Numeration")
def t_evalexpr(r):
    a,b,x,y=R(r,2,9),R(r,2,9),R(r,-5,6),R(r,-5,6); v=a*x*x+b*y
    return B.add(f"If x = {x} and y = {y}, evaluate {a}x² + {b}y.", v, [a*x*x-b*y,(a*x)**2+b*y,a*x+b*y,v+a],"Algebra")
def t_perc_change(r):
    o=R(r,2,20)*50; p=r.choice([10,20,25,40,50]); n=o*(100-p)//100
    return B.add(f"The price of an item was reduced from ₦{o:,} to ₦{n:,}. Find the percentage reduction.", f"{p}%", [f"{p+10}%",f"{p-5}%",f"{p*2}%",f"{100-p}%"],"Number and Numeration")
def t_sector(r):
    ang=r.choice([45,60,90,120,180]); rad=R(r,1,5)*7; v=F(ang,360)*F(22,7)*rad*rad
    return B.add(f"Find the area of a sector of angle {ang}° in a circle of radius {rad} cm. (π = 22/7)", f"{fr(v)} cm²", [f"{fr(F(ang,360)*F(44,7)*rad)} cm²",f"{fr(v*2)} cm²",f"{fr(F(22,7)*rad*rad)} cm²",f"{fr(v/2)} cm²"],"Mensuration","Hard")
def t_bearing(r):
    b=r.choice([30,45,60,75,110,130,150,200,240,300]); 
    return B.add(f"The bearing of B from A is {b:03d}°. Find the bearing of A from B.", f"{(b+180)%360:03d}°", [f"{b:03d}°",f"{(360-b)%360:03d}°",f"{abs(180-b):03d}°" if b!=180 else "090°",f"{(b+90)%360:03d}°"],"Geometry","Medium")
def t_cuboid(r):
    l,w,h=R(r,2,12),R(r,2,12),R(r,2,12)
    return B.add(f"Find the total surface area of a cuboid {l} cm by {w} cm by {h} cm.", f"{2*(l*w+w*h+l*h)} cm²", [f"{l*w*h} cm²",f"{l*w+w*h+l*h} cm²",f"{4*(l+w+h)} cm²",f"{2*(l*w+w*h+l*h)+l} cm²"],"Mensuration")
def t_remfac(r):
    a,b,c=R(r,1,5),R(r,-6,6),R(r,-9,9); k=R(r,-3,3); v=a*k*k+b*k+c
    return B.add(f"Find the remainder when {a}x² {'+' if b>=0 else '−'} {abs(b)}x {'+' if c>=0 else '−'} {abs(c)} is divided by (x − {k})." if k>=0 else f"Find the remainder when {a}x² {'+' if b>=0 else '−'} {abs(b)}x {'+' if c>=0 else '−'} {abs(c)} is divided by (x + {-k}).", v, near(r,v,[a*k*k-b*k+c,c,a+b+c]),"Algebra","Hard")
def t_hist(r):
    xs=[R(r,1,9) for _ in range(5)]; vals=[1,2,3,4,5]; tot=sum(xs); mean=F(sum(f*v for f,v in zip(xs,vals)),tot)
    return B.add(f"A frequency table shows scores 1, 2, 3, 4, 5 with frequencies {', '.join(map(str,xs))} respectively. Find the mean score.", fr(mean) if mean.denominator==1 else f"{float(mean):.2f}", [f"{float(mean)+d:.2f}" for d in (.5,-.5,1,-1,.25)],"Statistics","Hard")

temps=[t_arith,t_pct,t_lcmhcf,t_ratio,t_si,t_ci,t_avg,t_median,t_mode,t_linear,t_simul,t_quad,t_sumprod_roots,t_indices,t_log,t_circle,t_cyl,t_pyth,t_polygon,t_ap,t_apsum,t_gp,t_grad,t_mid,t_dist,t_sets,t_base,t_baseadd,t_speed,t_profit,t_prob,t_dice,t_var,t_invvar,t_subject,t_factor,t_diffsq,t_ineq,t_trig,t_surd,t_stdform,t_sigfig,t_angle,t_trap,t_fracadd,t_fracmult,t_evalexpr,t_perc_change,t_sector,t_bearing,t_cuboid,t_remfac,t_hist]
if __name__=="__main__":
    target=3000; per=target//len(temps)+8
    for t in temps: B.fill(t, per)
    # top up from random templates until 3000
    k=0
    while len(B.qs)<target and k<200000:
        k+=1; t=B.rng.choice(temps); t(B.rng)
    B.qs=B.qs[:target]
    print("mathematics", B.save())
