///|
/// Infer a rising-shed liftplan by grouping identical warp columns.
/// This minimizes shafts for the exact supplied drawdown, not treadles or a different repeat.
pub fn from_drawdown(cells : Array[Array[Bool]]) -> Result[Draft, String] {
let h = cells.length()
if h < 1 || h > 2048 {
return Err("weave.size")
}
let w = cells[0].length()
if w < 1 || w > 2048 || w * h > 262144 {
return Err("weave.size")
}
if cells.any(fn(row) { row.length() != w }) {
return Err("weave.ragged")
}
let signatures : Array[Array[Bool]] = []
let threading : Array[Int] = []
for x = 0; x < w; x = x + 1 {
let column = cells.map(fn(row) { row[x] })
let mut found = -1
for i, s in signatures {
if s == column {
found = i
break
}
}
if found < 0 {
if signatures.length() == 64 {
return Err("weave.shafts")
}
found = signatures.length()
signatures.push(column)
}
threading.push(found + 1)
}
draft(
signatures.length(),
threading,
Array::makei(h, fn(y) {
let lift : Array[Int] = []
for i, s in signatures {
if s[y] {
lift.push(i + 1)
}
}
lift
}),
)
}