RosettaCodeData/Task/Nonoblock/Zkl/nonoblock-1.zkl
2023-07-01 13:44:08 -04:00

33 lines
1.5 KiB
Text

fcn nonoblocks(blocks,cells){
if(not blocks or blocks[0]==0) vm.yield( T(T(0,0)) );
else{
if(not ( blocks.sum(0) + blocks.len() -1<=cells ))
throw(Exception.AssertionError("Those blocks will not fit in those cells"));
blength,brest:=blocks[0], blocks[1,*]; # Deal with the first block of length
minspace4rest:=brest.reduce('+(1),0); # The other blocks need space
# Slide the start position from left to max RH index allowing for other blocks.
foreach bpos in (cells - minspace4rest - blength +1){
if(not brest) # No other blocks to the right so just yield this one.
vm.yield(T(T(bpos,blength)));
else{
# More blocks to the right so create a *sub-problem* of placing
# the brest blocks in the cells one space to the right of the RHS of
# this block.
offset:=bpos + blength +1;
# recursive call to nonoblocks yields multiple sub-positions
foreach subpos in (Utils.Generator(nonoblocks,brest,cells - offset)){
# Remove the offset from sub block positions
rest:=subpos.pump(List,'wrap([(bp,bl)]){ T(offset + bp, bl) });
# Yield this block plus sub blocks positions
vm.yield(T( T(bpos,blength) ).extend(rest) );
}
}
}
}
}
# Pretty print each run of blocks with a different letter for each block of filled cells
fcn pblock(vec,cells){
vector,ch:=cells.pump(List(),"_".copy), ["A".."Z"];
vec.apply2('wrap([(a,b)]){ a.walker(b).pump(Void,vector.set.fp1(ch.next())) });
String("|",vector.concat("|"),"|");
}