feat(trainer): C — расширение «Десятичные», «Неравенства», «Системы» (+8)

Десятичные (7→10): dec-divide-pow10 (деление на 10/100/1000, L1),
dec-to-percent (десятичная→%, L2), dec-percent-to (%→десятичная, L2).
Неравенства (7→10): ineq-frac ((ax+b)/c ≤ d, L3), ineq-div (x/a > b, L2),
ineq-greatest-int (наибольшее целое двойного неравенства, L2).
Системы (6→8): sys-word-price (покупка цена/количество, L2),
sys-word-age (возраст, сумма/разность, L2).

Все с пошаговыми решениями. Смоук 6609 ассертов, 0 ошибок (self-check по видам:
relation/pair/значение, приём канонич. ответа, отклонение неверного, LaTeX-рендер).
Итого 230 генераторов. Завершает волну C (+18: дроби 4 + геометрия 6 + алгебра 8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-29 22:19:19 +03:00
parent ee94ca2346
commit b1ffba633c
+126
View File
@@ -1373,6 +1373,49 @@
]
},
/* (ax + b)/c ≤ d — неравенство с дробью */
{
id: 'ineq-frac', topic: 'inequalities', order: 8, subject: 'algebra', grade: 8, kind: 'inequality',
title: '(ax + b)/c ≤ d',
pick: { a: [2, 5], b: [1, 9], c: [2, 4], root: [-6, 8] },
derive: { d: '(a*root + b)/c', cd: 'a*root + b', ad: 'a*root' }, require: 'mod(a*root + b, c) == 0',
lhs: '({a}*x + {b})/{c}', rhs: '{d}', dispOp: '<=', relOp: '<=', bound: 'root',
answerVar: 'x',
solution: [
{ note: 'Умножаем обе части на {c} (положительное) — знак неравенства сохраняется.', tex: '{a}x + {b} <= {cd}' },
{ note: 'Переносим свободный член {b} вправо.', tex: '{a}x <= {ad}' },
{ note: 'Делим обе части на {a} (положительное).', tex: 'x <= {root}' }
]
},
/* x/a > b — неравенство с делением */
{
id: 'ineq-div', topic: 'inequalities', order: 9, subject: 'algebra', grade: 8, kind: 'inequality',
title: 'x/a > b',
pick: { a: [2, 6], b: [-6, 8] },
derive: { root: 'a*b' },
lhs: 'x/{a}', rhs: '{b}', dispOp: '>', relOp: '>', bound: 'root',
answerVar: 'x',
solution: [
{ note: 'Умножаем обе части на {a} (положительное) — знак неравенства сохраняется.', tex: 'x > {a}*{b}' },
{ note: 'Считаем.', tex: 'x > {root}' }
]
},
/* наибольшее целое решение двойного неравенства */
{
id: 'ineq-greatest-int', topic: 'inequalities', order: 10, subject: 'algebra', grade: 8, kind: 'compute',
title: 'Наибольшее целое решение',
pick: { lo: [-5, 4], span: [3, 9] },
derive: { hi: 'lo + span', val: 'lo + span - 1' },
lhs: 'x', rhs: '{hi} - 1', display: 'Найдите наибольшее целое число x, для которого {lo} < x < {hi}.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Подходят целые от {lo}+1 до {hi}−1. Наибольшее из них — {hi} − 1.', tex: 'x = {hi} - 1' },
{ note: 'Считаем.', tex: 'x = {ans}' }
]
},
/* ── Системы ── */
/* x + y = S, x y = D — сумма и разность */
@@ -1431,6 +1474,44 @@
]
},
/* текстовая задача (покупка) — система цена/количество */
{
id: 'sys-word-price', topic: 'systems', order: 7, subject: 'algebra', grade: 7, kind: 'system',
title: 'Текстовая задача (покупка)',
pick: { sx: [2, 9], sy: [2, 9], p: [3, 6], q: [2, 5] }, constraint: 'p > q',
derive: { N: 'sx + sy', T: 'p*sx + q*sy', TmqN: '(p - q)*sx' },
eqs: [{ lhs: 'x + y', rhs: '{N}' }, { lhs: '{p}*x + {q}*y', rhs: '{T}' }],
display: 'Купили всего {N} шариков: красные по {p} руб. и синие по {q} руб., заплатив {T} руб. Сколько было красных (x) и синих (y)?',
answers: { x: 'sx', y: 'sy' }, answerVars: ['x', 'y'], integerAnswer: true,
solution: [
{ note: 'Всего шариков {N}.', tex: 'x + y = {N}' },
{ note: 'Стоимость всех шариков — {T} руб.', tex: '{p}*x + {q}*y = {T}' },
{ note: 'Из первого уравнения выразим y = {N} − x и подставим во второе.', tex: 'y = {N} - x' },
{ note: 'После подстановки и упрощения остаётся одно уравнение с x.', tex: '({p} - {q})*x = {TmqN}' },
{ note: 'Находим x, затем y = {N} x.', tex: 'x = {sx}' },
{ note: 'Ответ: красных {sx}, синих {sy}.', tex: '' }
]
},
/* текстовая задача (возраст) — система сумма/разность */
{
id: 'sys-word-age', topic: 'systems', order: 8, subject: 'algebra', grade: 7, kind: 'system',
title: 'Текстовая задача (возраст)',
pick: { sx: [8, 20], sy: [30, 55] }, constraint: 'sy > sx',
derive: { N: 'sx + sy', D: 'sy - sx', twoY: '2*sy' },
eqs: [{ lhs: 'x + y', rhs: '{N}' }, { lhs: 'y - x', rhs: '{D}' }],
display: 'Сыну и отцу вместе {N} лет. Отец старше сына на {D} лет. Сколько лет сыну (x) и отцу (y)?',
answers: { x: 'sx', y: 'sy' }, answerVars: ['x', 'y'], integerAnswer: true,
solution: [
{ note: 'Возраст сына x, возраст отца y. Вместе им {N} лет.', tex: 'x + y = {N}' },
{ note: 'Отец старше сына на {D} лет.', tex: 'y - x = {D}' },
{ note: 'Сложим уравнения — получим удвоенный возраст отца.', tex: '2*y = {twoY}' },
{ note: 'Находим возраст отца y.', tex: 'y = {sy}' },
{ note: 'Тогда сыну:', tex: 'x = {N} - {sy}' },
{ note: 'Ответ: сыну {sx}, отцу {sy}.', tex: '' }
]
},
/* Система 3×3 (вводный тизер) */
{
id: 'sys-3x3', topic: 'systems', order: 6, subject: 'algebra', grade: 9, kind: 'system',
@@ -2580,6 +2661,48 @@
]
},
/* деление на 10, 100, 1000 */
{
id: 'dec-divide-pow10', topic: 'decimals', order: 8, subject: 'algebra', grade: 5, kind: 'compute',
title: 'Деление на 10, 100, 1000',
pick: { a: [11, 99], k: [1, 3] },
derive: { pw: '10^k', val: 'a / 10^k' },
lhs: 'x', rhs: '{a}/{pw}', display: 'Вычислите {a} : {pw}.',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Деление на {pw} сдвигает запятую влево на {k} разряд(ов).', tex: 'x = {a}/{pw}' },
{ note: 'Получаем десятичную дробь.', tex: 'x = {ans}' }
]
},
/* десятичную дробь — в проценты */
{
id: 'dec-to-percent', topic: 'decimals', order: 9, subject: 'algebra', grade: 5, kind: 'compute',
title: 'Десятичную в проценты',
pick: { a: [1, 9], b: [0, 9] },
derive: { d: '(10*a + b)/100', val: '10*a + b' },
lhs: 'x', rhs: '10*{a} + {b}', display: 'Запишите десятичную дробь {d} в процентах. Введите число процентов.',
answerVar: 'x', answer: 'val', integerAnswer: true,
solution: [
{ note: 'Чтобы перевести десятичную дробь в проценты, умножают её на 100.', tex: 'x = {d} * 100' },
{ note: 'Умножение на 100 сдвигает запятую на 2 разряда вправо.', tex: 'x = {ans}' }
]
},
/* проценты — в десятичную дробь */
{
id: 'dec-percent-to', topic: 'decimals', order: 10, subject: 'algebra', grade: 5, kind: 'compute',
title: 'Проценты в десятичную',
pick: { p: [5, 95] },
derive: { val: 'p/100' },
lhs: 'x', rhs: '{p}/100', display: 'Запишите {p}% в виде десятичной дроби.',
answerVar: 'x', answer: 'val',
solution: [
{ note: 'Процент — это сотая доля, поэтому число процентов делят на 100.', tex: 'x = {p}/100' },
{ note: 'Деление на 100 сдвигает запятую на 2 разряда влево.', tex: 'x = {ans}' }
]
},
/* ── Отрицательные ── */
/* деление отрицательных */
@@ -3579,7 +3702,10 @@
'lin-both-frac': 2, 'lin-x-denom': 3, 'lin-k-over-x': 2, 'lin-abs': 3,
'lin-frac-eq-frac': 3, 'lin-nested-paren': 3, 'lin-literal': 3,
'ineq-both-sides': 2, 'ineq-both-flip': 3, 'ineq-paren': 2, 'ineq-count-int': 2,
'ineq-frac': 3, 'ineq-div': 2, 'ineq-greatest-int': 2,
'sys-sum-diff': 1, 'sys-subst': 2, 'sys-word': 2, 'sys-3x3': 3,
'sys-word-price': 2, 'sys-word-age': 2,
'dec-divide-pow10': 1, 'dec-to-percent': 2, 'dec-percent-to': 2,
// V4.1 — Пропорции/Проценты/Текстовые
'prop-direct-word': 1, 'prop-inverse-word': 2, 'prop-scale-map': 2, 'prop-compound': 3, 'prop-share-ratio': 2,
'pct-increase': 2, 'pct-decrease': 2, 'pct-change': 3, 'pct-simple-interest': 2, 'pct-compound-2y': 3, 'pct-restore-before': 3,