diff --git a/src/content/questions/comp2804/2022-winter-final/1/generator.test.ts b/src/content/questions/comp2804/2022-winter-final/1/generator.test.ts new file mode 100644 index 00000000..551a4085 --- /dev/null +++ b/src/content/questions/comp2804/2022-winter-final/1/generator.test.ts @@ -0,0 +1,106 @@ +import { describe, expect } from "@jest/globals"; +import Generator from "./generator"; + +describe("comp2804/2022-winter-final/1", () => { + describe("generateValues", () => { + it("will return two values", () => { + const generator = new Generator(); + + const values = generator.generateValues(); + + expect(values).toHaveLength(2); + }); + + it("will return a string length between 50 and 100", () => { + const generator = new Generator(); + + const [stringLength, _] = generator.generateValues(); + + expect(stringLength).toBeGreaterThanOrEqual(50); + expect(stringLength).toBeLessThanOrEqual(100); + }); + + it("will return a positions value between 5 and 20", () => { + const generator = new Generator(); + + const [_, positions] = generator.generateValues(); + + expect(positions).toBeGreaterThanOrEqual(5); + expect(positions).toBeLessThanOrEqual(20); + }); + }); + + describe("createOptions", () => { + it("will return five options", () => { + const generator = new Generator(); + + const options = generator.createOptions(50, 5); + + expect(options).toHaveLength(5); + }); + + it("will have exactly one correct option", () => { + const generator = new Generator(); + + const options = generator.createOptions(50, 5); + const correctOptions = options.filter((option) => option.correct); + + expect(correctOptions).toHaveLength(1); + }); + }); + + describe("createCorrectOption", () => { + it("will return the correct option", () => { + const generator = new Generator(); + + const option = generator.createCorrectOption(50, 10); + + expect(option.label).toBe("$\\binom{50}{10}\\cdot 4^{40}$"); + expect(option.correct).toBe(true); + }); + }); + + describe("createIncorrectOption1", () => { + it("will return an option with the combination being multiplied with 5 ^ value instead of 4 ^ value", () => { + const generator = new Generator(); + + const option = generator.createIncorrectOption1(50, 10); + + expect(option.label).toBe("$\\binom{50}{10}\\cdot 5^{40}$"); + expect(option.correct).toBe(false); + }); + }); + + describe("createIncorrectOption2", () => { + it("will return an option with the combination using the number of letters instead of positions and being multiplied with 5 ^ value instead of 4 ^ value", () => { + const generator = new Generator(); + + const option = generator.createIncorrectOption2(50, 10); + + expect(option.label).toBe("$\\binom{50}{5}\\cdot 5^{40}$"); + expect(option.correct).toBe(false); + }); + }); + + describe("createIncorrectOption3", () => { + it("will return an option with the combination using the number of letters instead of positions", () => { + const generator = new Generator(); + + const option = generator.createIncorrectOption3(50, 10); + + expect(option.label).toBe("$\\binom{50}{5}\\cdot 4^{40}$"); + expect(option.correct).toBe(false); + }); + }); + + describe("createIncorrectOption4", () => { + it("will return an option which does not use combinations", () => { + const generator = new Generator(); + + const option = generator.createIncorrectOption4(50, 10); + + expect(option.label).toBe("$5^{10}\\cdot 4^{40}$"); + expect(option.correct).toBe(false); + }); + }); +}); diff --git a/src/content/questions/comp2804/2022-winter-final/1/generator.ts b/src/content/questions/comp2804/2022-winter-final/1/generator.ts new file mode 100644 index 00000000..141c14f4 --- /dev/null +++ b/src/content/questions/comp2804/2022-winter-final/1/generator.ts @@ -0,0 +1,106 @@ +import { MultipleChoiceQuestionGenerator } from "@common/MultipleChoiceQuestionGenerator"; +import type { + MultipleChoiceQuestion, + MultipleChoiceQuestionOption, +} from "@common/MultipleChoiceQuestionGenerator"; + +class Generator extends MultipleChoiceQuestionGenerator { + generateQuestion(): MultipleChoiceQuestion { + const [stringLength, positions] = this.generateValues(); + const dynamicQuestionBody = `Consider strings of length $${stringLength}$, in which each character is one of the characters $a,b,c,d,e$. How many such strings have exactly $${positions}$ letters $e$?`; + return { + body: dynamicQuestionBody, + options: this.createOptions(stringLength, positions), + }; + } + + generateValues(): [number, number] { + const stringLength = Math.floor(Math.random() * 51) + 50; //generate a value between 50 and 100 + const positions = Math.floor(Math.random() * 16) + 5; //generate a value between 5 and 20 + + return [stringLength, positions]; + } + + createOptions( + stringLength: number, + positions: number, + ): MultipleChoiceQuestionOption[] { + const correctOption = this.createCorrectOption(stringLength, positions); + const incorrectOption1 = this.createIncorrectOption1( + stringLength, + positions, + ); + const incorrectOption2 = this.createIncorrectOption2( + stringLength, + positions, + ); + const incorrectOption3 = this.createIncorrectOption3( + stringLength, + positions, + ); + const incorrectOption4 = this.createIncorrectOption4( + stringLength, + positions, + ); + + return this.shuffleOptions([ + correctOption, + incorrectOption1, + incorrectOption2, + incorrectOption3, + incorrectOption4, + ]); + } + + createCorrectOption( + stringLength: number, + positions: number, + ): MultipleChoiceQuestionOption { + return { + label: `$\\binom{${stringLength}}{${positions}}\\cdot 4^{${stringLength - positions}}$`, + correct: true, + }; + } + + createIncorrectOption1( + stringLength: number, + positions: number, + ): MultipleChoiceQuestionOption { + return { + label: `$\\binom{${stringLength}}{${positions}}\\cdot 5^{${stringLength - positions}}$`, + correct: false, + }; + } //mutliples with 5 ^ value instead of 4 + + createIncorrectOption2( + stringLength: number, + positions: number, + ): MultipleChoiceQuestionOption { + return { + label: `$\\binom{${stringLength}}{5}\\cdot 5^{${stringLength - positions}}$`, + correct: false, + }; + } //uses number of letters instead of positions and multiples with 5 ^ value instead of 4 + + createIncorrectOption3( + stringLength: number, + positions: number, + ): MultipleChoiceQuestionOption { + return { + label: `$\\binom{${stringLength}}{5}\\cdot 4^{${stringLength - positions}}$`, + correct: false, + }; + } //uses number of letters instead of positions + + createIncorrectOption4( + stringLength: number, + positions: number, + ): MultipleChoiceQuestionOption { + return { + label: `$5^{${positions}}\\cdot 4^{${stringLength - positions}}$`, + correct: false, + }; + } //does not use combinations +} + +export default Generator; diff --git a/src/content/questions/comp2804/2022-winter-final/1/index.md b/src/content/questions/comp2804/2022-winter-final/1/index.md index f89af3a4..a1b134e5 100644 --- a/src/content/questions/comp2804/2022-winter-final/1/index.md +++ b/src/content/questions/comp2804/2022-winter-final/1/index.md @@ -5,6 +5,7 @@ type: multiple-choice author: Michiel Smid question: comp2804/2022-winter-final/1/question.ts solution: comp2804/2022-winter-final/1/solution.md +generator: comp2804/2022-winter-final/1/generator.ts tags: - comp2804 - comp2804-final