FAILURE MAP
← Case archive

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.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

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 fixtureActualExpectedOutcome
exact two skeins[1, 1, 199][400, 2, 0]Failed
with margin[1, 1, 124][1320, 11, 55]Failed
zero swatcherror: swatcherror: swatchPassed
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 fixtureActualExpectedOutcome
exact two skeins[2000, 10, 0][400, 2, 0]Failed
with margin[7200, 58, 50][1320, 11, 55]Failed
zero swatcherror: swatcherror: swatchPassed
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 fixtureActualExpectedOutcome
exact two skeins[400, 2, 0][400, 2, 0]Passed
with margin[1320, 11, 55][1320, 11, 55]Passed
zero swatcherror: swatcherror: swatchPassed
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