Nonoblock: Difference between revisions
Content added Content deleted
(Add ref.) |
(+ D entry) |
||
Line 52: | Line 52: | ||
;Reference: |
;Reference: |
||
* The blog post [http://paddy3118.blogspot.co.uk/2014/03/nonogram-puzzle-solver-part-1.html Nonogram puzzle solver (part 1)] Inspired this task and donated its Python solution. |
* The blog post [http://paddy3118.blogspot.co.uk/2014/03/nonogram-puzzle-solver-part-1.html Nonogram puzzle solver (part 1)] Inspired this task and donated its Python solution. |
||
=={{header|D}}== |
|||
{{trans|python}} |
|||
<lang d>import std.stdio, std.array, std.algorithm, std.exception, std.conv; |
|||
struct Solution { uint pos, len; } |
|||
struct NonoBlocks { |
|||
const uint[] blocks; |
|||
const uint cells; |
|||
int opApply(int delegate(ref const Solution[]) dg) { |
|||
int result; |
|||
if (blocks.empty || blocks[0] == 0) { |
|||
const vec = [Solution(0, 0)]; |
|||
result = dg(vec); |
|||
if (result) return result; |
|||
} else { |
|||
enforce(sum(cast(uint[])blocks) + blocks.length - 1 <= cells,//** |
|||
"Those blocks cannot fit in those cells."); |
|||
immutable firstBl = blocks[0]; |
|||
const restBl = blocks[1 .. $]; |
|||
// The other blocks need space. |
|||
immutable minS = restBl.map!(b => b + 1).sum; |
|||
// Slide the start position from left to max RH |
|||
// index allowing for other blocks. |
|||
foreach (immutable bPos; 0 .. cells - minS - firstBl + 1) { |
|||
if (restBl.empty) { |
|||
// No other blocks to the right so just yield |
|||
// this one. |
|||
const vec = [Solution(bPos, firstBl)]; |
|||
result = dg(vec); |
|||
if (result) return result; |
|||
} else { |
|||
// More blocks to the right so create a sub-problem |
|||
// of placing the restBl blocks in the cells one |
|||
// space to the right of the RHS of this block. |
|||
immutable offset = bPos + firstBl + 1; |
|||
immutable newCells = cells - offset; |
|||
// Recursive call to nonoBlocks yields multiple |
|||
// sub-positions. |
|||
foreach (const subPos; NonoBlocks(restBl, newCells)) { |
|||
// Remove the offset from sub block positions. |
|||
const rest = subPos.map!(sol => Solution(offset + sol.pos, |
|||
sol.len)).array; |
|||
// Yield this block plus sub blocks positions. |
|||
const vec = [Solution(bPos, firstBl)] ~ rest; |
|||
result = dg(vec); |
|||
if (result) return result; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
} |
|||
/// Pretty prints each run of blocks with a |
|||
/// different letter for each block of filled cells. |
|||
string show(in Solution[] vec, in uint nCells) pure { |
|||
auto result = ['_'].replicate(nCells); |
|||
foreach (immutable i, immutable sol; vec) |
|||
foreach (immutable j; sol.pos .. sol.pos + sol.len) |
|||
result[j] = (result[j] == '_') ? to!char('A' + i) : '?'; |
|||
return '[' ~ result ~ ']'; |
|||
} |
|||
void main() { |
|||
static struct Problem { uint[] blocks; uint nCells; } |
|||
immutable Problem[] problems = [{[2, 1], 5}, |
|||
{[], 5}, |
|||
{[8], 10}, |
|||
{[2, 3, 2, 3], 15}, |
|||
{[4, 3], 10}, |
|||
{[2, 1], 5}, |
|||
{[3, 1], 10}, |
|||
{[2, 3], 5}]; |
|||
foreach (immutable prob; problems) { |
|||
writefln("Configuration (%d cells and %s blocks):", |
|||
prob.nCells, prob.blocks); |
|||
show([], prob.nCells).writeln; |
|||
"Possibilities:".writeln; |
|||
foreach (const sol; NonoBlocks(prob.tupleof)) |
|||
show(sol, prob.nCells).writeln; |
|||
writeln; |
|||
} |
|||
}</lang> |
|||
{{out}} |
|||
<pre>Configuration (5 cells and [2, 1] blocks): |
|||
[_____] |
|||
Possibilities: |
|||
[AA_B_] |
|||
[AA__B] |
|||
[_AA_B] |
|||
Configuration (5 cells and [] blocks): |
|||
[_____] |
|||
Possibilities: |
|||
[_____] |
|||
Configuration (10 cells and [8] blocks): |
|||
[__________] |
|||
Possibilities: |
|||
[AAAAAAAA__] |
|||
[_AAAAAAAA_] |
|||
[__AAAAAAAA] |
|||
Configuration (15 cells and [2, 3, 2, 3] blocks): |
|||
[_______________] |
|||
Possibilities: |
|||
[AA_BBB_CC_DDD__] |
|||
[AA_BBB_CC__DDD_] |
|||
[AA_BBB_CC___DDD] |
|||
[AA_BBB__CC_DDD_] |
|||
[AA_BBB__CC__DDD] |
|||
[AA_BBB___CC_DDD] |
|||
[AA__BBB_CC_DDD_] |
|||
[AA__BBB_CC__DDD] |
|||
[AA__BBB__CC_DDD] |
|||
[AA___BBB_CC_DDD] |
|||
[_AA_BBB_CC_DDD_] |
|||
[_AA_BBB_CC__DDD] |
|||
[_AA_BBB__CC_DDD] |
|||
[_AA__BBB_CC_DDD] |
|||
[__AA_BBB_CC_DDD] |
|||
Configuration (10 cells and [4, 3] blocks): |
|||
[__________] |
|||
Possibilities: |
|||
[AAAA_BBB__] |
|||
[AAAA__BBB_] |
|||
[AAAA___BBB] |
|||
[_AAAA_BBB_] |
|||
[_AAAA__BBB] |
|||
[__AAAA_BBB] |
|||
Configuration (5 cells and [2, 1] blocks): |
|||
[_____] |
|||
Possibilities: |
|||
[AA_B_] |
|||
[AA__B] |
|||
[_AA_B] |
|||
Configuration (10 cells and [3, 1] blocks): |
|||
[__________] |
|||
Possibilities: |
|||
[AAA_B_____] |
|||
[AAA__B____] |
|||
[AAA___B___] |
|||
[AAA____B__] |
|||
[AAA_____B_] |
|||
[AAA______B] |
|||
[_AAA_B____] |
|||
[_AAA__B___] |
|||
[_AAA___B__] |
|||
[_AAA____B_] |
|||
[_AAA_____B] |
|||
[__AAA_B___] |
|||
[__AAA__B__] |
|||
[__AAA___B_] |
|||
[__AAA____B] |
|||
[___AAA_B__] |
|||
[___AAA__B_] |
|||
[___AAA___B] |
|||
[____AAA_B_] |
|||
[____AAA__B] |
|||
[_____AAA_B] |
|||
Configuration (5 cells and [2, 3] blocks): |
|||
[_____] |
|||
Possibilities: |
|||
Possibilities: |
|||
object.Exception@nonoblock.d(17): Those blocks cannot fit in those cells. |
|||
---------------- |
|||
0x0040AC17 in pure @safe void std.exception.bailOut(immutable(char)[], uint, const(char[])) |
|||
...</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |