Created
December 17, 2024 23:04
-
-
Save dlants/09ecbd41feb0c5d2c84cd8c0cfb3c883 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Types to make the code more readable and type-safe | |
type StudentResponse = number[][] | |
type AnswerKey = number[][] | |
type CardPair = [number, number] | |
type PairCount = { pair: CardPair; count: number } | |
/** | |
* Finds incorrectly grouped card pairs across all student responses, | |
* sorted by frequency (most frequent first) | |
*/ | |
function findIncorrectPairsInClass( | |
classResponses: StudentResponse[], | |
answerKey: AnswerKey | |
): CardPair[] { | |
// Create a set of valid pairs from the answer key | |
const validPairs = new Set<string>( | |
extractAllPairs(answerKey).map(pair => pairToString(pair)) | |
) | |
// Count frequency of each incorrect pair | |
const pairCounts = new Map<string, PairCount>() | |
classResponses.forEach(response => { | |
// Get all pairs from this student's response | |
const studentPairs = extractAllPairs(response) | |
// Check each pair against valid pairs | |
studentPairs.forEach(pair => { | |
const pairStr = pairToString(pair) | |
if (!validPairs.has(pairStr)) { | |
if (!pairCounts.has(pairStr)) { | |
pairCounts.set(pairStr, { pair, count: 1 }) | |
} else { | |
const current = pairCounts.get(pairStr)! | |
pairCounts.set(pairStr, { ...current, count: current.count + 1 }) | |
} | |
} | |
}) | |
}) | |
// Sort pairs by frequency and convert to output format | |
return Array.from(pairCounts.values()) | |
.sort((a, b) => b.count - a.count || a.pair[0] - b.pair[0]) | |
.map(pc => pc.pair) | |
} | |
/** | |
* Extracts all possible pairs of numbers from groups of numbers | |
*/ | |
function extractAllPairs(groups: number[][]): CardPair[] { | |
const pairs: CardPair[] = [] | |
groups.forEach(group => { | |
// For each group, generate all possible pairs within that group | |
for (let i = 0; i < group.length; i++) { | |
for (let j = i + 1; j < group.length; j++) { | |
// Always put smaller number first for consistent comparison | |
pairs.push([ | |
Math.min(group[i], group[j]), | |
Math.max(group[i], group[j]) | |
]) | |
} | |
} | |
}) | |
return pairs | |
} | |
/** | |
* Converts a pair to a string for consistent lookup | |
*/ | |
function pairToString(pair: CardPair): string { | |
return `${pair[0]},${pair[1]}` | |
} | |
// Tests using Jest | |
describe('findIncorrectPairsInClass', () => { | |
test('handles basic case with multiple students', () => { | |
const result = findIncorrectPairsInClass( | |
[ | |
[[1, 2], [3]], // student 1 | |
[[2], [3, 1]], // student 2 | |
[[2, 3, 1]] // student 3 | |
], | |
[[1, 2], [3]] | |
) | |
expect(result).toEqual([[1, 3], [2, 3]]) | |
}) | |
test('handles case with equal frequency pairs', () => { | |
const result = findIncorrectPairsInClass( | |
[ | |
[[1, 4], [3], [2]], // student 1 | |
[[2, 1, 4, 3]], // student 2 | |
], | |
[[1, 2, 3], [4]] | |
) | |
expect(result).toEqual([[1, 4], [2, 4], [3, 4]]) | |
}) | |
test('handles empty class responses', () => { | |
const result = findIncorrectPairsInClass( | |
[], | |
[[1, 2], [3]] | |
) | |
expect(result).toEqual([]) | |
}) | |
test('handles single-item groups', () => { | |
const result = findIncorrectPairsInClass( | |
[[[1], [2], [3]]], | |
[[1, 2], [3]] | |
) | |
expect(result).toEqual([]) | |
}) | |
test('handles multiple incorrect groupings of same pair', () => { | |
const result = findIncorrectPairsInClass( | |
[ | |
[[1, 3]], | |
[[1, 3]], | |
[[2, 3]] | |
], | |
[[1, 2], [3]] | |
) | |
expect(result).toEqual([[1, 3], [2, 3]]) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment