FA-97411 / Knitting and sewing pattern grading / Open access
Yarn yardage estimator: area ratio · case 01
A whole sweater is estimated at a fraction of a gram.
ROOT CAUSE
The swatch-to-garment area ratio is inverted.
VERIFIED REPAIR
Scale swatch grams by garment area over swatch area.
Unsuccessful approach: Dividing by width plus height uses the swatch perimeter instead of its area.
Case contract
grams = garment_area / swatch_area * swatch_g; meters = grams * skein_m/skein_g; add margin_pct as a multiplier (meters*(1+margin/100)). skeins = ceiling(meters/skein_m); leftover = skeins*skein_m - meters. Return [meters, skeins, leftover] with meters and leftover half-up integers. Non-positive swatch area or skein weight -> "error: swatch".
Why this case matters
Designers and knitters estimate how many skeins to buy from a weighed swatch.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(swatch_g, swatch_w_cm, swatch_h_cm, garment_area_cm2, skein_g, skein_m, margin_pct):
sw_area = Fraction(str(swatch_w_cm)) * Fraction(str(swatch_h_cm))
if sw_area <= 0 or skein_g <= 0:
return 'error: swatch'
grams = sw_area / Fraction(str(garment_area_cm2)) * Fraction(str(swatch_g))
meters = grams * Fraction(skein_m, skein_g)
meters = meters * (1 + Fraction(margin_pct, 100))
skeins = math.ceil(meters / skein_m)
leftover = skeins * skein_m - meters
return [math.floor(meters + Fraction(1, 2)), skeins, math.floor(leftover + Fraction(1, 2))]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['regression: area ratio', [8, 12, 10, 2400, 100, 125, 15], [230, 2, 20]],
['repair check: area ratio', [10, 12, 15, 2000, 50, 400, 10], [978, 3, 222]],
['generated control 1', [12, 15, 10, 9000, 50, 100, 20], [1728, 18, 72]],
['generated control 2', [20, 12, 15, 2400, 100, 125, 10], [367, 3, 8]],
['generated control 3', [8, 12, 15, 2400, 50, 400, 0], [853, 3, 347]]],
[['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['regression: area ratio', [15, 10, 15, 6000, 50, 100, 10], [1320, 14, 80]],
['repair check: area ratio', [20, 15, 12, 1500, 100, 200, 15], [383, 2, 17]],
['generated control 1', [12, 15, 10, 1500, 50, 200, 20], [576, 3, 24]],
['generated control 2', [10, 10, 15, 1500, 100, 400, 0], [400, 1, 0]],
['generated control 3', [10, 12, 15, 6000, 50, 100, 20], [800, 8, 0]]],
[['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['regression: area ratio', [10, 15, 12, 2000, 50, 400, 15], [1022, 3, 178]],
['repair check: area ratio', [8, 12, 15, 2000, 50, 125, 10], [244, 2, 6]],
['generated control 1', [8, 15, 15, 2400, 50, 100, 15], [196, 2, 4]],
['generated control 2', [15, 10, 10, 2000, 50, 200, 20], [1440, 8, 160]],
['generated control 3', [10, 15, 15, 4800, 100, 400, 10], [939, 3, 261]]],
[['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['regression: area ratio', [20, 15, 12, 2000, 50, 400, 0], [1778, 5, 222]],
['repair check: area ratio', [10, 12, 15, 1500, 50, 100, 10], [183, 2, 17]],
['generated control 1', [15, 10, 12, 2000, 50, 125, 20], [750, 6, 0]],
['generated control 2', [10, 10, 10, 4800, 100, 400, 10], [2112, 6, 288]],
['generated control 3', [15, 10, 12, 2400, 50, 100, 20], [720, 8, 80]]],
[['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['regression: area ratio', [20, 10, 15, 6000, 50, 125, 15], [2300, 19, 75]],
['repair check: area ratio', [15, 15, 12, 3000, 100, 100, 0], [250, 3, 50]],
['generated control 1', [20, 10, 15, 9000, 50, 150, 10], [3960, 27, 90]],
['generated control 2', [12, 10, 15, 3000, 100, 100, 20], [288, 3, 12]],
['generated control 3', [20, 12, 10, 6000, 50, 200, 0], [4000, 20, 0]]]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| exact two skeins | [1, 1, 199] | [400, 2, 0] | Failed |
| with margin | [1, 1, 124] | [1320, 11, 55] | Failed |
| zero swatch | error: swatch | error: swatch | Passed |
| regression: area ratio | [1, 1, 124] | [230, 2, 20] | Failed |
| repair check: area ratio | [8, 1, 392] | [978, 3, 222] | Failed |
| generated control 1 | [0, 1, 100] | [1728, 18, 72] | Failed |
| generated control 2 | [2, 1, 123] | [367, 3, 8] | Failed |
| generated control 3 | [5, 1, 395] | [853, 3, 347] | Failed |
SHA-256 / 743f630e52e6dfa12d164552d240622a664d64e9ad3288bf28bb64b9fb4ea0f6
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(swatch_g, swatch_w_cm, swatch_h_cm, garment_area_cm2, skein_g, skein_m, margin_pct):
sw_area = Fraction(str(swatch_w_cm)) * Fraction(str(swatch_h_cm))
if sw_area <= 0 or skein_g <= 0:
return 'error: swatch'
grams = Fraction(str(garment_area_cm2)) / (Fraction(str(swatch_w_cm)) + Fraction(str(swatch_h_cm))) * Fraction(str(swatch_g))
meters = grams * Fraction(skein_m, skein_g)
meters = meters * (1 + Fraction(margin_pct, 100))
skeins = math.ceil(meters / skein_m)
leftover = skeins * skein_m - meters
return [math.floor(meters + Fraction(1, 2)), skeins, math.floor(leftover + Fraction(1, 2))]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['regression: area ratio', [8, 12, 10, 2400, 100, 125, 15], [230, 2, 20]],
['repair check: area ratio', [10, 12, 15, 2000, 50, 400, 10], [978, 3, 222]],
['generated control 1', [12, 15, 10, 9000, 50, 100, 20], [1728, 18, 72]],
['generated control 2', [20, 12, 15, 2400, 100, 125, 10], [367, 3, 8]],
['generated control 3', [8, 12, 15, 2400, 50, 400, 0], [853, 3, 347]]],
[['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['regression: area ratio', [15, 10, 15, 6000, 50, 100, 10], [1320, 14, 80]],
['repair check: area ratio', [20, 15, 12, 1500, 100, 200, 15], [383, 2, 17]],
['generated control 1', [12, 15, 10, 1500, 50, 200, 20], [576, 3, 24]],
['generated control 2', [10, 10, 15, 1500, 100, 400, 0], [400, 1, 0]],
['generated control 3', [10, 12, 15, 6000, 50, 100, 20], [800, 8, 0]]],
[['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['regression: area ratio', [10, 15, 12, 2000, 50, 400, 15], [1022, 3, 178]],
['repair check: area ratio', [8, 12, 15, 2000, 50, 125, 10], [244, 2, 6]],
['generated control 1', [8, 15, 15, 2400, 50, 100, 15], [196, 2, 4]],
['generated control 2', [15, 10, 10, 2000, 50, 200, 20], [1440, 8, 160]],
['generated control 3', [10, 15, 15, 4800, 100, 400, 10], [939, 3, 261]]],
[['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['regression: area ratio', [20, 15, 12, 2000, 50, 400, 0], [1778, 5, 222]],
['repair check: area ratio', [10, 12, 15, 1500, 50, 100, 10], [183, 2, 17]],
['generated control 1', [15, 10, 12, 2000, 50, 125, 20], [750, 6, 0]],
['generated control 2', [10, 10, 10, 4800, 100, 400, 10], [2112, 6, 288]],
['generated control 3', [15, 10, 12, 2400, 50, 100, 20], [720, 8, 80]]],
[['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['regression: area ratio', [20, 10, 15, 6000, 50, 125, 15], [2300, 19, 75]],
['repair check: area ratio', [15, 15, 12, 3000, 100, 100, 0], [250, 3, 50]],
['generated control 1', [20, 10, 15, 9000, 50, 150, 10], [3960, 27, 90]],
['generated control 2', [12, 10, 15, 3000, 100, 100, 20], [288, 3, 12]],
['generated control 3', [20, 12, 10, 6000, 50, 200, 0], [4000, 20, 0]]]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| exact two skeins | [2000, 10, 0] | [400, 2, 0] | Failed |
| with margin | [7200, 58, 50] | [1320, 11, 55] | Failed |
| zero swatch | error: swatch | error: swatch | Passed |
| regression: area ratio | [1255, 11, 120] | [230, 2, 20] | Failed |
| repair check: area ratio | [6519, 17, 281] | [978, 3, 222] | Failed |
| generated control 1 | [10368, 104, 32] | [1728, 18, 72] | Failed |
| generated control 2 | [2444, 20, 56] | [367, 3, 8] | Failed |
| generated control 3 | [5689, 15, 311] | [853, 3, 347] | Failed |
SHA-256 / 34f242d48c1114bd9add1e0fcd757f1f8b973f2648c7e3010a43eabe0f300d06
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(swatch_g, swatch_w_cm, swatch_h_cm, garment_area_cm2, skein_g, skein_m, margin_pct):
sw_area = Fraction(str(swatch_w_cm)) * Fraction(str(swatch_h_cm))
if sw_area <= 0 or skein_g <= 0:
return 'error: swatch'
grams = Fraction(str(garment_area_cm2)) / sw_area * Fraction(str(swatch_g))
meters = grams * Fraction(skein_m, skein_g)
meters = meters * (1 + Fraction(margin_pct, 100))
skeins = math.ceil(meters / skein_m)
leftover = skeins * skein_m - meters
return [math.floor(meters + Fraction(1, 2)), skeins, math.floor(leftover + Fraction(1, 2))]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['regression: area ratio', [8, 12, 10, 2400, 100, 125, 15], [230, 2, 20]],
['repair check: area ratio', [10, 12, 15, 2000, 50, 400, 10], [978, 3, 222]],
['generated control 1', [12, 15, 10, 9000, 50, 100, 20], [1728, 18, 72]],
['generated control 2', [20, 12, 15, 2400, 100, 125, 10], [367, 3, 8]],
['generated control 3', [8, 12, 15, 2400, 50, 400, 0], [853, 3, 347]]],
[['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['regression: area ratio', [15, 10, 15, 6000, 50, 100, 10], [1320, 14, 80]],
['repair check: area ratio', [20, 15, 12, 1500, 100, 200, 15], [383, 2, 17]],
['generated control 1', [12, 15, 10, 1500, 50, 200, 20], [576, 3, 24]],
['generated control 2', [10, 10, 15, 1500, 100, 400, 0], [400, 1, 0]],
['generated control 3', [10, 12, 15, 6000, 50, 100, 20], [800, 8, 0]]],
[['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['regression: area ratio', [10, 15, 12, 2000, 50, 400, 15], [1022, 3, 178]],
['repair check: area ratio', [8, 12, 15, 2000, 50, 125, 10], [244, 2, 6]],
['generated control 1', [8, 15, 15, 2400, 50, 100, 15], [196, 2, 4]],
['generated control 2', [15, 10, 10, 2000, 50, 200, 20], [1440, 8, 160]],
['generated control 3', [10, 15, 15, 4800, 100, 400, 10], [939, 3, 261]]],
[['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['regression: area ratio', [20, 15, 12, 2000, 50, 400, 0], [1778, 5, 222]],
['repair check: area ratio', [10, 12, 15, 1500, 50, 100, 10], [183, 2, 17]],
['generated control 1', [15, 10, 12, 2000, 50, 125, 20], [750, 6, 0]],
['generated control 2', [10, 10, 10, 4800, 100, 400, 10], [2112, 6, 288]],
['generated control 3', [15, 10, 12, 2400, 50, 100, 20], [720, 8, 80]]],
[['with margin', [12, 10, 12, 4800, 50, 125, 10], [1320, 11, 55]],
['zero swatch', [10, 0, 10, 2000, 100, 200, 0], 'error: swatch'],
['exact two skeins', [10, 10, 10, 2000, 100, 200, 0], [400, 2, 0]],
['regression: area ratio', [20, 10, 15, 6000, 50, 125, 15], [2300, 19, 75]],
['repair check: area ratio', [15, 15, 12, 3000, 100, 100, 0], [250, 3, 50]],
['generated control 1', [20, 10, 15, 9000, 50, 150, 10], [3960, 27, 90]],
['generated control 2', [12, 10, 15, 3000, 100, 100, 20], [288, 3, 12]],
['generated control 3', [20, 12, 10, 6000, 50, 200, 0], [4000, 20, 0]]]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| exact two skeins | [400, 2, 0] | [400, 2, 0] | Passed |
| with margin | [1320, 11, 55] | [1320, 11, 55] | Passed |
| zero swatch | error: swatch | error: swatch | Passed |
| regression: area ratio | [230, 2, 20] | [230, 2, 20] | Passed |
| repair check: area ratio | [978, 3, 222] | [978, 3, 222] | Passed |
| generated control 1 | [1728, 18, 72] | [1728, 18, 72] | Passed |
| generated control 2 | [367, 3, 8] | [367, 3, 8] | Passed |
| generated control 3 | [853, 3, 347] | [853, 3, 347] | Passed |
SHA-256 / 8248169d301e2efd1d78cd470c781344e003a82ea8c57144a5b049f43663266f
Verification & scope
A deterministic toy contract stated in full here; it is a bounded teaching model, not an authoritative reference or standards implementation. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:52:31.917979+00:00.
Case digest / 95e38d910491c5a758582f97a7eca2966519d2fd2f983d26699849680639a10d