Task: Nonoblock



C#: using System;
using System.Linq;
using System.Text;

public static class Nonoblock
{
    public static void Main() {
        Positions(5, 2,1);
        Positions(5);
        Positions(10, 8);
        Positions(15, 2,3,2,3);
        Positions(5, 2,3);
    }

    public static void Positions(int cells, params int[] blocks) {
        if (cells < 0 || blocks == null || blocks.Any(b => b < 1)) throw new ArgumentOutOfRangeException();
        Console.WriteLine($"{cells} cells with [{string.Join(", ", blocks)}]");
        if (blocks.Sum() + blocks.Length - 1 > cells) {
            Console.WriteLine("No solution");
            return;
        }
        var spaces = new int[blocks.Length + 1];
        int total = -1;
        for (int i = 0; i < blocks.Length; i++) {
            total += blocks[i] + 1;
            spaces[i+1] = total;
        }
        spaces[spaces.Length - 1] = cells - 1;
        var sb = new StringBuilder(string.Join(".", blocks.Select(b => new string('#', b))).PadRight(cells, '.'));
        Iterate(sb, spaces, spaces.Length - 1, 0);
        Console.WriteLine();
    }

    private static void Iterate(StringBuilder output, int[] spaces, int index, int offset) {
        Console.WriteLine(output.ToString());
        if (index <= 0) return;
        int count = 0;
        while (output[spaces[index] - offset] != '#') {
            count++;
            output.Remove(spaces[index], 1);
            output.Insert(spaces[index-1], '.');
            spaces[index-1]++;
            Iterate(output, spaces, index - 1, 1);
        }
        if (offset == 0) return;
        spaces[index-1] -= count;
        output.Remove(spaces[index-1], count);
        output.Insert(spaces[index] - count, ".", count);
    }

}





Python: def nonoblocks(blocks, cells):
    if not blocks or blocks[0] == 0:
        yield [(0, 0)]
    else:
        assert sum(blocks) + len(blocks)-1 <= cells, \
            'Those blocks will not fit in those cells'
        blength, brest = blocks[0], blocks[1:]      
        minspace4rest = sum(1+b for b in brest)     
        
        for bpos in range(0, cells - minspace4rest - blength + 1):
            if not brest:
                
                yield [(bpos, blength)]
            else:
                
                
                
                offset = bpos + blength +1
                nonoargs = (brest, cells - offset)  
                
                for subpos in nonoblocks(*nonoargs):
                    
                    rest = [(offset + bp, bl) for bp, bl in subpos]
                    
                    vec = [(bpos, blength)] + rest
                    yield vec

def pblock(vec, cells):
    'Prettyprints each run of blocks with a different letter A.. for each block of filled cells'
    vector = ['_'] * cells
    for ch, (bp, bl) in enumerate(vec, ord('A')):
        for i in range(bp, bp + bl):
            vector[i] = chr(ch) if vector[i] == '_' else'?'
    return '|' + '|'.join(vector) + '|'


if __name__ == '__main__':
    for blocks, cells in (
            ([2, 1], 5),
            ([], 5),
            ([8], 10),
            ([2, 3, 2, 3], 15),
           
           
           
            ([2, 3], 5),
            ):
        print('\nConfiguration:\n    %s 
        print('  Possibilities:')
        for i, vector in enumerate(nonoblocks(blocks, cells)):
            print('   ', pblock(vector, cells))
        print('  A total of %i Possible configurations.' % (i+1))