Function Transformations Worksheet Generator
Generate a fresh 20-problem practice set: shifts, reflections, stretches, vertex tracking, and combined transformations.
Skill: function-transformations
Each click of Generate builds a brand-new set of 20 problems. Toggle the answer key any time; printing includes the key only when it is visible.
Function Transformations Practice Worksheet
Answer Key
For the teacher or for self-checking after you finish.
'use strict'; /* ===================================================================== Function transformations worksheet generator — pure logic (no DOM). ===================================================================== */ function mulberry32(a){ return function(){ a |= 0; a = (a + 0x6D2B79F5) | 0; var t = Math.imul(a ^ (a >>> 15), 1 | a); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } var _rand = Math.random; function setSeed(s){ _rand = mulberry32(s >>> 0); } function ri(lo, hi){ return lo + Math.floor(_rand() * (hi - lo + 1)); } function pick(arr){ return arr[Math.floor(_rand() * arr.length)]; } function shuffle(a){ for (var i = a.length - 1; i > 0; i--){ var j = Math.floor(_rand() * (i + 1)); var t = a[i]; a[i] = a[j]; a[j] = t; } return a; } function fmtH(h){ return h > 0 ? '(x \u2212 ' + h + ')' : h < 0 ? '(x + ' + Math.abs(h) + ')' : '(x)'; } function fmtK(k){ return k > 0 ? ' + ' + k : k < 0 ? ' \u2212 ' + Math.abs(k) : ''; } function fmtA(a){ return a === 1 ? '' : a === -1 ? '\u2212' : String(a).replace('-', '\u2212'); } function ansDir(v){ return { k: 'dir', v: v }; } function ansPt(x, y){ return { k: 'pt', x: x, y: y }; } function ansNum(v){ return { k: 'num', v: v }; } function ansYN(v){ return { k: 'yn', v: v }; } function ansShift(dir, n){ return { k: 'shift', dir: dir, n: n }; } function keyHTML(a){ if (a.k === 'dir') return '' + a.v + ''; if (a.k === 'yn') return '' + (a.v ? 'Yes' : 'No') + ''; if (a.k === 'num') return '' + a.v + ''; if (a.k === 'shift') return '' + a.dir + ' ' + a.n + ''; return '(' + a.x + ', ' + a.y + ')'; }
function gShiftUp(){ var k = ri(1, 6); return { stemHTML: 'Describe y = x\u00B2 + ' + k + ' from y = x\u00B2. Which way does it shift?', answer: ansDir('up') }; } function gShiftDown(){ var k = ri(1, 6); return { stemHTML: 'Describe y = x\u00B2 \u2212 ' + k + ' from y = x\u00B2. Which way does it shift?', answer: ansDir('down') }; } function gShiftRight(){ var h = ri(1, 6); return { stemHTML: 'Describe y = (x \u2212 ' + h + ')\u00B2 from y = x\u00B2. Direction and distance?', answer: ansShift('right', h) }; } function gShiftLeft(){ var h = ri(1, 6); return { stemHTML: 'Describe y = (x + ' + h + ')\u00B2 from y = x\u00B2. Direction and distance?', answer: ansShift('left', h) }; } function gReflect(){ var parent = pick(['x\u00B2', '|x|']); return { stemHTML: 'From y = ' + parent + ', is y = \u2212' + parent + ' reflected over the x-axis? (yes / no)', answer: ansYN(true) }; } function gStretch(){ var a = pick([2, 3, 4]); return { stemHTML: 'From y = x\u00B2, describe y = ' + a + 'x\u00B2. Vertical stretch by what factor?', answer: ansNum(a) }; } function gCompress(){ var den = pick([2, 3, 4]); return { stemHTML: 'From y = x\u00B2, describe y = (1/' + den + ')x\u00B2. Vertical compression by what factor? (decimal or fraction)', answer: ansNum(1 / den) }; } function gVertex(){ var h = ri(-5, 5), k = ri(-5, 5); if (h === 0) h = 2; if (k === 0) k = -3; return { stemHTML: 'From y = x\u00B2, the graph of y = ' + fmtH(h) + '\u00B2' + fmtK(k) + ' has vertex at which point?', answer: ansPt(h, k) }; } function gVertexCombo(){ var a = pick([-2, -3, 2, 3]); var h = ri(1, 4), k = ri(-4, 4); if (k === 0) k = 1; return { stemHTML: 'From y = x\u00B2, the graph of y = ' + fmtA(a) + fmtH(h) + '\u00B2' + fmtK(k) + ' has vertex at which point?', answer: ansPt(h, k) }; } function gShiftAbs(){ var h = ri(1, 5), left = pick([true, false]); return { stemHTML: 'From y = |x|, describe y = |x ' + (left ? '+' : '\u2212') + ' ' + h + '|. Direction and distance?', answer: ansShift(left ? 'left' : 'right', h) }; } function gOpens(){ var a = pick([-3, -2, -1, 1, 2, 3]); var k = ri(-3, 3); return { stemHTML: 'For y = ' + fmtA(a) + 'x\u00B2' + fmtK(k) + ', does the parabola open upward or downward?', answer: ansDir(a > 0 ? 'up' : 'down') }; } function gCombo(){ var h = ri(1, 4), k = ri(-3, 3); if (k === 0) k = 1; var a = pick([-2, -3]); return { stemHTML: 'From y = x\u00B2 to y = ' + fmtA(a) + fmtH(h) + '\u00B2' + fmtK(k) + ': give the vertex.', answer: ansPt(h, k) }; }
var PLAN = { easy: [gShiftUp, gShiftUp, gShiftDown, gShiftDown, gShiftRight, gShiftRight, gShiftLeft, gShiftLeft, gReflect, gReflect, gOpens, gOpens, gVertex, gVertex, gShiftUp, gShiftDown, gShiftRight, gShiftLeft, gReflect, gOpens], medium: [gShiftUp, gShiftDown, gShiftRight, gShiftLeft, gReflect, gStretch, gCompress, gVertex, gVertex, gVertexCombo, gShiftAbs, gOpens, gCombo, gStretch, gReflect, gShiftLeft, gShiftRight, gVertex, gCompress, gShiftAbs], hard: [gVertexCombo, gVertexCombo, gCombo, gCombo, gStretch, gCompress, gShiftAbs, gShiftAbs, gVertex, gVertex, gReflect, gOpens, gCombo, gVertexCombo, gStretch, gCompress, gShiftRight, gShiftLeft, gCombo, gVertexCombo] };
function generateSet(seed, difficulty){ if (!PLAN[difficulty]) throw new Error('generateSet: bad difficulty ' + difficulty); setSeed(seed >>> 0); var plan = shuffle(PLAN[difficulty].slice()); var problems = plan.map(function (gen){ return gen(); }); if (problems.length !== 20) throw new Error('generateSet: expected 20 problems'); return problems; }
/* ---- DOM wiring ---- */ var current = { problems: [], difficulty: 'medium', keyVisible: false, genCount: 0 }; var el = {}; function renderProblems(){ el.problems.innerHTML = current.problems.map(function (p, i){ return '
'; }).join(''); el.probCount.textContent = current.problems.length + ' problems \u00B7 ' + current.difficulty.charAt(0).toUpperCase() + current.difficulty.slice(1); } function renderKey(){ el.keyGrid.innerHTML = current.problems.map(function (p, i){ return '
'; }).join(''); } function newSet(seed){ current.seed = (seed === undefined) ? ((Date.now() + (current.genCount * 7919)) >>> 0) : (seed >>> 0); current.genCount++; current.problems = generateSet(current.seed, current.difficulty); renderProblems(); if (current.keyVisible) renderKey(); } function setKeyVisible(v){ current.keyVisible = v; el.keySection.hidden = !v; el.btnKey.setAttribute('aria-pressed', v ? 'true' : 'false'); el.btnKey.textContent = v ? 'Hide Answer Key' : 'Show Answer Key'; if (v) renderKey(); } function init(){ el.diffSel = document.getElementById('diffSel'); el.btnGen = document.getElementById('btnGen'); el.btnKey = document.getElementById('btnKey'); el.btnPrint = document.getElementById('btnPrint'); el.problems = document.getElementById('problems'); el.probCount = document.getElementById('probCount'); el.keySection = document.getElementById('keySection'); el.keyGrid = document.getElementById('keyGrid'); current.difficulty = el.diffSel.value; el.diffSel.addEventListener('change', function(){ current.difficulty = el.diffSel.value; newSet(); }); el.btnGen.addEventListener('click', function(){ newSet(); }); el.btnKey.addEventListener('click', function(){ setKeyVisible(!current.keyVisible); }); el.btnPrint.addEventListener('click', function(){ window.print(); }); newSet(); } if (document.readyState === 'loading'){ document.addEventListener('DOMContentLoaded', init); } else { init(); }
window.__WS = { generateSet: generateSet, keyHTML: keyHTML, getState: function(){ return current; }, newSet: newSet, setKeyVisible: setKeyVisible };