Define the local evaluation task
A synthetic repeated-answer ledger supplies pass and attempt counts per case. Attempt-weighted scoring pools all attempts; case-weighted scoring averages each case’s own fraction equally. Use exact reduced fractions as decimal numerator/denominator strings. There are 1–100 cases; each needs 1–10000 attempts and passes between zero and that count. No favourable attempts are discarded.
- Validate each finite count pair
- Pool attempts for one fraction
- Average case fractions for the other
Zero attempts or inconsistent counts invalidate scoring inputs.
Use the filled cases
| Case | Supplied input | Expected structured output | Decision and reason |
|---|---|---|---|
| Cases have different repeat counts | {"cases":[{"pass":9,"attempts":10},{"pass":0,"attempts":1}]} | {"attemptWeighted":["9","11"],"caseWeighted":["9","20"]} | Pooling gives 9/11; equal case weight gives (9/10+0)/2=9/20. |
| Cases have equal repeat counts | {"cases":[{"pass":1,"attempts":2},{"pass":2,"attempts":2}]} | {"attemptWeighted":["3","4"],"caseWeighted":["3","4"]} | Equal attempt counts make these two weighting rules agree here. |
| Impossible pass count | {"cases":[{"pass":3,"attempts":2}]} | {"error":"counts"} | The ledger is inconsistent, so no score is calculated. |
Work the more-passes-than-attempts case. Which output is required, and why?
Show the worked answer
{"error":"counts"} — The ledger is inconsistent, so no score is calculated.
Run the self-contained evaluator
import assert from 'node:assert/strict';
function evaluate(x){
const gcd=(a,b)=>b?gcd(b,a%b):a,reduce=(n,d)=>{const g=gcd(n,d);return [n/g,d/g];},text=([n,d])=>[n.toString(),d.toString()];
if(x.cases.length<1||x.cases.length>100||x.cases.some(c=>!Number.isInteger(c.pass)||!Number.isInteger(c.attempts)||c.attempts<1||c.attempts>10000||c.pass<0||c.pass>c.attempts))return {error:'counts'};
let n=0n,d=1n,passes=0n,attempts=0n;for(const c of x.cases){const a=BigInt(c.attempts),p=BigInt(c.pass);n=n*a+p*d;d*=a;[n,d]=reduce(n,d);passes+=p;attempts+=a;}
return {attemptWeighted:text(reduce(passes,attempts)),caseWeighted:text(reduce(n,d*BigInt(x.cases.length)))};
}
const cases = [
{
"id": "unequal-repeats",
"input": {
"cases": [
{
"pass": 9,
"attempts": 10
},
{
"pass": 0,
"attempts": 1
}
]
},
"expected": {
"attemptWeighted": [
"9",
"11"
],
"caseWeighted": [
"9",
"20"
]
}
},
{
"id": "equal-repeats",
"input": {
"cases": [
{
"pass": 1,
"attempts": 2
},
{
"pass": 2,
"attempts": 2
}
]
},
"expected": {
"attemptWeighted": [
"3",
"4"
],
"caseWeighted": [
"3",
"4"
]
}
},
{
"id": "more-passes-than-attempts",
"input": {
"cases": [
{
"pass": 3,
"attempts": 2
}
]
},
"expected": {
"error": "counts"
}
}
];
for (const c of cases) assert.deepEqual(evaluate(c.input), c.expected, c.id);
console.log(JSON.stringify({checked:cases.length,caseIds:cases.map(c=>c.id)}));
State which weighting grain the acceptance report uses. Repeating one easy case may change pooled scores while leaving case-weighted results unchanged; neither rule estimates real workload prevalence.