Nonogram solver: Difference between revisions

Content deleted Content added
Hkdtam (talk | contribs)
Peak (talk | contribs)
→‎{{header|jq}}: remove unused defs
 
(8 intermediate revisions by 6 users not shown)
Line 49:
'''Extra credit''': generate nonograms with unique solutions, of desired height and width.
<br><br>
This task is the problem n.98 of the "[https://sites.google.com/site/prologsite/prolog-problems 99 Prolog Problems]" [https://web.archive.org/web/20230406102539/https://sites.google.com/site/prologsite/prolog-problems (archived)] by Werner Hett (also thanks to Paul Singleton for the idea and the examples).
<br><br>
; Related tasks
Line 64:
{{trans|Python 3}}
 
<langsyntaxhighlight lang="11l">F gen_row(w, s)
‘Create all patterns of a row or col that match given runs.’
F gen_seg([[Int]] o, Int sp) -> [[Int]]
Line 172:
 
print(‘Extra example where there is no solution:’)
solve("B A A\nA A A")</langsyntaxhighlight>
 
{{out}}
Line 195:
 
=={{header|C sharp}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using static System.Linq.Enumerable;
Line 311:
}
 
}</langsyntaxhighlight>
{{out}}
<pre style="height:30ex;overflow:scroll">
Line 384:
=={{header|C++}}==
===The Solver===
<langsyntaxhighlight lang="cpp">
// A class to solve Nonogram (Hadje) Puzzles
// Nigel Galloway - January 23rd., 2017
Line 444:
return n.str();
}};
</syntaxhighlight>
</lang>
 
===The Task===
<langsyntaxhighlight lang="cpp">
// For the purpose of this task I provide a little code to read from a file in the required format
// Note though that Nonograms may contain blank lines and values greater than 24
Line 478:
std::cout << "\n" << myN.toStr() << std::endl;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 564:
===Bonus GCHQ Xmas Puzzle===
[[https://www.gchq.gov.uk/news-article/christmas-card-cryptographic-twist-charity GCHQ Xmas Puzzle]] is a Nonogram. They say "We pre-shaded a few cells to help people get started. Without this, the puzzle would have been slightly ambiguous, though the error correction used in QR codes means that the URL would have been recovered anyway. As a small Easter egg, the pre-shaded cells spell out “GCHQ” in Morse code."
<langsyntaxhighlight lang="cpp">
int main(){
const std::vector<std::vector<int>> Ngchq={{ 7,3,1, 1,7},
Line 643:
std::cout << "\n" << myN.toStr() << std::endl;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 674:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defpackage :ac3
(:use :cl)
(:export :var
Line 848:
(nonogram (parse-nonogram (read-until-line s)
(read-until-line s)))))
(end-of-file ())))</langsyntaxhighlight>
{{out}}
<pre>CL-USER> (time (nonogram::solve-from-file "c:/Users/cro/Dropbox/Projects/rosetta-code/nonogram_problems.txt"))
Line 939:
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.range, std.file, std.algorithm, std.string;
 
/// Create all patterns of a row or col that match given runs.
Line 1,074:
"Extra example where there is no solution:".writeln;
"B A A\nA A A".solve;
}</langsyntaxhighlight>
{{out}}
<pre>Horizontal runs: [[3], [2, 1], [3, 2], [2, 2], [6], [1, 5], [6], [1], [2]]
Line 1,193:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
(*
I define a discriminated union to provide Nonogram Solver functionality.
Line 1,229:
if ((fst el) = (fst l)) && ((snd el) = (snd l)) then (n,i,g,e,(Array.forall (fun n -> n = 1) (fst l))) else fn na ia ga ea el
fn na nb x (N.fl x) ((Array.map (fun n -> List.length n) na), (Array.map (fun n -> List.length n) ga))
</syntaxhighlight>
</lang>
For the purposes of this task I provide a little code to read the input from a file
<langsyntaxhighlight lang="fsharp">
let fe (n : array<string>) i = n |> Array.collect (fun n -> [|N.fn [for g in n -> ((int)g-64)] i|])
let fl (n : array<string>) (i : array<string>) = (fe n i.Length), (fe i n.Length)
Line 1,239:
Some(fl (file.ReadLine().Split ' ') (file.ReadLine().Split ' '))
with | _ -> printfn "Error reading file" ; None
</syntaxhighlight>
</lang>
This may be used:
<langsyntaxhighlight lang="fsharp">
let n,i,g,e,l = N.presolve rFile.Value
if l then i |> Array.iter (fun n -> n |> Array.iter (fun n -> printf "%s" (N.toStr n));printfn "") else printfn "No unique solution"
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,330:
=={{header|Go}}==
{{trans|Java}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,513:
newPuzzle(puzzleData)
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,584:
. . . . . . . . . . . . . . . . . # # # # # # # #
. . . . . . . . . . . . . . . . . . # # # # # # #
</pre>
 
 
=={{header|Haskell}}==
{{works with|GHC|8.10.7}}
{{libheader|csp}}
<syntaxhighlight lang="haskell">import Control.Applicative ((<|>))
import Control.Monad
import Control.Monad.CSP
import Data.List (transpose)
import System.Environment (getArgs)
import Text.ParserCombinators.ReadP (ReadP)
import qualified Text.ParserCombinators.ReadP as P
import Text.Printf (printf)
 
main :: IO ()
main = do
file <- parseArgs
printf "reading problem file from %s\n" file
ps <- parseProblems file
forM_ ps $ \p -> do
print p
putStrLn ""
printSolution $ solve p
putStrLn ""
 
-------------------------------------------------------------------------------
-- parsing
-------------------------------------------------------------------------------
 
parseArgs :: IO FilePath
parseArgs = do
args <- getArgs
case args of
[file] -> return file
_ -> ioError $ userError "expected exactly one command line argument, the name of the problem file"
 
data Problem = Problem
{ rows :: [[Int]]
, cols :: [[Int]]
} deriving (Show, Read, Eq, Ord)
 
entryP :: ReadP Int
entryP = do
n <- fromEnum <$> P.get
if n < 65 || n > 90
then P.pfail
else return $ n - 64
 
blankP, eolP :: ReadP Char
blankP = P.char ' '
eolP = P.char '\n'
 
entriesP :: ReadP [Int]
entriesP = ([] <$ blankP) <|> P.many1 entryP
 
lineP :: ReadP [[Int]]
lineP = P.sepBy1 entriesP blankP <* eolP
 
problemP :: ReadP Problem
problemP = Problem <$> lineP <*> lineP
 
problemsP :: ReadP [Problem]
problemsP = P.sepBy1 problemP (P.many blankP <* eolP) <* P.eof
 
parseProblems :: FilePath -> IO [Problem]
parseProblems file = do
s <- readFile file
case P.readP_to_S problemsP s of
[(ps, "")] -> return ps
_ -> ioError $ userError $ "error parsing file " <> file
 
-------------------------------------------------------------------------------
-- CSP
-------------------------------------------------------------------------------
 
solve :: Problem -> [[Bool]]
solve = oneCSPSolution . problemCSP
 
problemCSP :: Problem -> CSP r [[DV r Bool]]
problemCSP p = do
let rowCount = length $ rows p
colCount = length $ cols p
cells <- replicateM rowCount
$ replicateM colCount
$ mkDV [False, True]
 
forM_ (zip cells $ rows p) $ uncurry rowOrColCSP
forM_ (zip (transpose cells) $ cols p) $ uncurry rowOrColCSP
 
return cells
 
rowOrColCSP :: [DV r Bool] -> [Int] -> CSP r ()
rowOrColCSP ws [] = forM_ ws $ constraint1 not
rowOrColCSP ws xs = do
let vs = zip [0 ..] ws
n = length ws
 
blocks <- forM xs $ \x ->
mkDV [(i, i + x - 1) | i <- [0 .. n - x]] -- the blocks, given by first and last index
 
-- blocks must be separate and not overlapping
f blocks
 
-- cells in blocks are set
forM_ blocks $ \x ->
forM_ vs $ \(i, y) ->
constraint2 (\(x1, x2) b -> i < x1 || i > x2 || b) x y
 
-- cells before the first block are not set
forM_ vs $ \(i, y) ->
constraint2 (\(y', _) b -> i >= y' || not b) (head blocks) y
 
-- cells after the last block are not set
forM_ vs $ \(i, y) ->
constraint2 (\(_, y') b -> i <= y' || not b) (last blocks) y
 
-- cells between blocks are not set
forM_ (zip blocks $ tail blocks) $ \(x, y) ->
forM_ vs $ \(i, z) ->
constraint3 (\(_, x') (y', _) b -> i <= x' || i >= y' || not b) x y z
where
f :: [DV r (Int, Int)] -> CSP r ()
f (u : v : bs) = do
constraint2 (\(_, u') (v', _) -> v' >= u' + 2) u v
f $ v : bs
f _ = return ()
 
-------------------------------------------------------------------------------
-- printing
-------------------------------------------------------------------------------
 
printSolution :: [[Bool]] -> IO ()
printSolution bss =
forM_ bss $ \bs -> do
forM_ bs $ \b ->
putChar $ if b then '#' else '.'
putChar '\n'</syntaxhighlight>
 
{{out}}
<pre>
time cabal run nonogram-solver -- nonogram-problems.txt
 
reading problem file from nonogram-problems.txt
Problem {rows = [[3],[2,1],[3,2],[2,2],[6],[1,5],[6],[1],[2]], cols = [[1,2],[3,1],[1,5],[7,1],[5],[3],[4],[3]]}
 
.###....
##.#....
.###..##
..##..##
..######
#.#####.
######..
....#...
...##...
 
Problem {rows = [[6],[3,1,3],[1,3,1,3],[3,14],[1,1,1],[1,1,2,2],[5,2,2],[5,1,1],[5,3,3,3],[8,3,3,3]], cols = [[4],[4],[1,5],[3,4],[1,5],[1],[4,1],[2,2,2],[3,3],[1,1,2],[2,1,1],[1,1,2],[4,1],[1,1,2],[1,1,1],[2,1,2],[1,1,1],[3,4],[2,2,1],[4,1]]}
 
..........######....
........###.#..###..
...#..###...#....###
..###.##############
...#..#............#
..#.#.##..........##
#####..##........##.
#####...#........#..
#####..###.###.###..
########.###.###.###
 
Problem {rows = [[3,1],[2,4,1],[1,3,3],[2,4],[3,3,1,3],[3,2,2,1,3],[2,2,2,2,2],[2,1,1,2,1,1],[1,2,1,4],[1,1,2,2],[2,2,8],[2,2,2,4],[1,2,2,1,1,1],[3,3,5,1],[1,1,3,1,1,2],[2,3,1,3,3],[1,3,2,8],[4,3,8],[1,4,2,5],[1,4,2,2],[4,2,5],[5,3,5],[4,1,1],[4,2],[3,3]], cols = [[2,3],[3,1,3],[3,2,1,2],[2,4,4],[3,4,2,4,5],[2,5,2,4,6],[1,4,3,4,6,1],[4,3,3,6,2],[4,2,3,6,3],[1,2,4,2,1],[2,2,6],[1,1,6],[2,1,4,2],[4,2,6],[1,1,1,1,4],[2,4,7],[3,5,6],[3,2,4,2],[2,2,2],[6,3]]}
 
....###.#...........
....##.####.#.......
....#.###.###.......
..##.####...........
.###.###.#....###...
###..##.##...#.###..
##..##.##....##.##..
....##.#.#..##.#.#..
....#.##.#...####...
....#.#.##.....##...
.....##.##..########
....##.##...##..####
....#.##.##.#...#..#
###..###.#####.....#
#.#.###.#....#....##
##..###.#....###.###
.#.###.##.########..
.####.###.########..
...#.####.##.#####..
...#.####.##...##...
....####..##...#####
...#####.###...#####
...####.#..........#
..####.##...........
..###.###...........
 
Problem {rows = [[5],[2,3,2],[2,5,1],[2,8],[2,5,11],[1,1,2,1,6],[1,2,1,3],[2,1,1],[2,6,2],[15,4],[10,8],[2,1,4,3,6],[17],[17],[18],[1,14],[1,1,14],[5,9],[8],[7]], cols = [[5],[3,2],[2,1,2],[1,1,1],[1,1,1],[1,3],[2,2],[1,3,3],[1,3,3,1],[1,7,2],[1,9,1],[1,10],[1,10],[1,3,5],[1,8],[2,1,6],[3,1,7],[4,1,7],[6,1,8],[6,10],[7,10],[1,4,11],[1,2,11],[2,12],[3,13]]}
 
....................#####
..##..............###..##
.##..............#####..#
##.............########..
##....#####.###########..
#.#..##....#....######...
#..##.....#.......###....
##........#.............#
.##.....######.........##
..###############....####
.....##########..########
....##.#.####.###..######
........#################
........#################
.......##################
.......#...##############
.......#.#.##############
........#####...#########
.................########
..................#######
 
 
real 0m0,244s
user 0m0,208s
sys 0m0,031s
</pre>
 
=={{header|Java}}==
{{works with|Java|8}}
<langsyntaxhighlight lang="java">import java.util.*;
import static java.util.Arrays.*;
import static java.util.stream.Collectors.toList;
Line 1,729 ⟶ 1,953:
return countRemoved;
}
}</langsyntaxhighlight>
<pre>. # # # . . . .
# # . # . . . .
Line 1,797 ⟶ 2,021:
. . . . . . . . . . . . . . . . . # # # # # # # #
. . . . . . . . . . . . . . . . . . # # # # # # #</pre>
 
=={{header|jq}}==
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq''' (*)
 
The following solution relies on jq's support for backtracking.
It begins by determining the cells in the nonogram matrix that can be
directly determined by the row and column constraints; this is
followed by an iterative winnowing step (during which informative
messages showing the reduction achieved are produced); finally, one or
more solutions are found by maintaining arrays of possible solutions
for each row and column.
 
Specifically, .rows[$i] keeps track of possible solutions for the i-th
row of the nonogram, and .cols[$j] likewise keeps track of the
possible solutions for the j-th column of the nonogram.
 
(*) jq's definition of transform/0 must be used. It is
included here to avoid confusion.
 
''Acknowledgement: genSequence/2 is translated from the [[#Wren|Wren]] solution.''
<syntaxhighlight lang="jq">
### For the sake of gojq
# This def of transpose can be omitted if using the C implementation of jq.
# Rows are padded with nulls so the result is always rectangular.
def transpose: [range(0; map(length)|max // 0) as $i | [.[][$i]]];
 
###############################################################################
### Generic functions
 
def array($n): [range(0;$n) as $i | .];
 
def inform(msg):
. as $in
| ("\(msg)\n" | stderr)
| $in;
 
def sum(stream): reduce stream as $x (0; . + $x);
 
def count(stream): sum(stream|1);
 
# null-based elementwise "or" for arrays
def or_array($b):
. as $a
| reduce range(0;length) as $i ([];
. + [if $a[$i] == null then $b[$i] else $a[$i] end]);
 
# null-based elementwise "or" for matrices
def or_matrix($b):
. as $a
| reduce range(0;length) as $i ([];
. + [$a[$i] | or_array($b[$i])] );
 
# Pretty-print the input, which must be an array but is normally a matrix.
# Notice that null nows and null values are handled specially.
def pp:
.[]
| if . == null then ""
else
reduce .[] as $x ("";
. + if $x == 0 then " ."
elif $x == null then " "
else " 1"
end )
end;
 
 
### Nonogram Solver
 
## Building blocks:
 
# $a and $b are normally arrays with $a | length <= $b | length
# Output: an array of the same length as $a, such that
# the element at $i is ( a[$i] == $b[$i] ? a[$i] : null )
def common($a; $b):
[ range(0;$a|length) as $i
| $a[$i]
| if . == $b[$i] then . else null end ];
 
# If `stream` is a stream of arrays, the output will be the reduction
# of the stream based on common/2, except that the output is null if
# the arrays have no elements in common.
# The implementation is intended to serve as the complete specification.
# Notice in particular the "short-circuit" semantics, and
# that an occurrence of null or [] in the stream will produce `null`
def common(stream):
def count: sum( .common[] | if . == null then 0 else 1 end );
first(
foreach (stream, null) as $x ({common: null, emit: 0};
if $x == null then .emit = .common
elif .common == null then .common = $x
else .common |= common(.; $x)
| if count == 0 then .emit=null end
end)
| select(.emit != 0).emit);
 
# $common should be null or an array. If $common is null, any input
# is agreeable. Otherwise, if the input is an array, then the output
# is true or false as the input is in point-wise agreement with
# $common in the sense that an occurrence of `null` in $common imposes
# no constraint on the corresponding item in the input.
# The implementation is intended to serve as the complete specification.
def agreeable($common):
if $common == null then true
else . as $in
| all( range(0; $common|length);
. as $i
| if $common[$i] == null then true
else $common[$i] == $in[$i]
end)
end;
 
# Convert an alphabetic specification of a sequence of runs
# to an array of integer arrays, e.g. "AB A" => [[1,2], [1]]
# Use _ for 0
def alphabet2runs:
split(" ")
| map( [explode[] | if . == 95 then 0 else . - 64 end]);
 
# A recursive helper function for runs2rows/2.
# Output: a stream of the rows with the required runs.
# Each row begins with a 0 for ensuring separation between the runs.
def genSequence($ones; $numZeros):
if $ones|length == 0 then (0|array($numZeros))
else range(1; $numZeros - ($ones|length) + 2) as $x
| genSequence($ones[1:]; $numZeros - $x) as $tail
| (0|array($x)) + $ones[0] + $tail
end;
 
# $rows should be an array of integers specifying the run lengths in a row of length $len.
# Output: a stream of arrays of length $len with the specified runs
def runs2rows($runs; $len):
($runs|map(select(. != 0))) as $runs # ignore 0s
| if ($runs|length) == 1 and $runs[0] == $len then 1|array($len)
else sum($runs[]) as $sum
| if $len - $sum <= 0
then empty
else
(reduce ($runs|map(select(. != 0)))[] as $run ([]; . + [1|array($run)] )) as $data
| genSequence($data; $len - $sum + 1)[1:]
end
end;
 
# Check the acceptability of . based on $common
def acceptable($common):
. as $in
| $common == null
or all( range(0;length); . as $i | $common[$i] | IN(null, $in[$i])) ;
 
# The rows that are acceptable w.r.t. $common
def runs2rows($runs; $len; $common):
runs2rows($runs; $len)
| select(acceptable($common));
 
# Setup {rows, cols, common} based on $rowruns and $colruns
def setup($rowruns; $colruns):
($rowruns | length) as $nrows
| ($colruns | length) as $ncols
 
| ($rowruns | map(common(runs2rows(.; $ncols)) ) ) as $commonRows
 
| ($colruns | map(common(runs2rows(.; $nrows)) ) ) as $commonCols
| ($commonCols | transpose | or_matrix($commonRows)) as $common
| ($common | transpose) as $ct
| { rows: [range(0; $nrows) as $i | [runs2rows($rowruns[$i]; $ncols; $common[$i]) ]],
cols: [range(0; $ncols) as $i | [runs2rows($colruns[$i]; $nrows; $ct[$i]) ]],
common: $common,
matrix: [],
};
 
# Winnow .rows and .cols based on point-wise commonality
def winnow:
.reduction = 0
| (.rows|length) as $nrows
| (.cols|length) as $ncols
# Winnow each row that has not already been fixed
| reduce range(0; $nrows) as $i (.;
if (.rows[$i] | length) != 1
then common(.rows[$i][]) as $common
| (.rows[$i] | length) as $before
| .rows[$i] |= map(select(agreeable($common)))
| .reduction += ((.rows[$i]|length) - $before)
end )
# Winnow each col that has not already been fixed
| reduce range(0; $ncols) as $i (.;
if (.cols[$i] | length) != 1
then common(.cols[$i][]) as $common
| (.cols[$i] | length) as $before
| .cols[$i] |= map(select(agreeable($common)))
| .reduction += ((.cols[$i]|length) - $before )
end)
| inform("reduction by \(.reduction)")
| if .reduction != 0 then winnow end ;
 
 
# Input: {rows, cols}
# If setting .matrix[$i] to $row is feasible,
# then winnow .cols accordingly and finally set .matrix[$i] to $row
def set($i; $row):
(.cols | length) as $ncols
| .cols as $cols
| if all(range(0; $ncols);
. as $j
| any( range(0; $cols[$j]|length);
$cols[$j][.][$i] == $row[$j] ) )
then foreach range(0; $ncols) as $j (.;
.cols[$j][] |= select( .[$i] == $row[$j] ) )
else empty
end
| .matrix[$i] = $row;
# Input: {rows, cols, matrix} where .matrix is the candidate matrix constructed so far
# After all the columnwise- and rowwise-constraints have been examined...
def solve($colruns):
(.rows|length) as $nrows
| (.cols|length) as $ncols
| (.matrix|length) as $m
| if $m == $nrows
then .
else range(0; .rows[$m]|length) as $p
| .rows[$m][$p] as $row
| set($m; $row)
| solve($colruns)
end ;
# Generate all solutions
def generate( $rowruns; $colruns ):
($rowruns | length) as $nrows
| ($colruns | length) as $ncols
| setup( $rowruns; $colruns )
| winnow
| solve($colruns);
# Generate a single solution
# Top-level: $p should be an array of two alphabetic ([A-Z_]) strings representing
# the row-wise and columnwise run lengths, respectively,
# with _ signifying 0, A signifying 1, etc.
def generate($p):
($p[0] | alphabet2runs) as $rowruns
| ($p[1] | alphabet2runs) as $colruns
| first( generate($rowruns; $colruns ) ) ;
 
# Top-level convenience function, where p is a puzzle specification in alphabetic form.
def puzzle($title; p):
$title,
( generate(p)
| .matrix
| pp ),
"";
 
def p0: [ "B A A", "B A A"];
 
def p1:
["C BA CB BB F AE F A B", "AB CA AE GA E C D C"];
 
def p2: [
"F CAC ACAC CN AAA AABB EBB EAA ECCC HCCC",
"D D AE CD AE A DA BBB CC AAB BAA AAB DA AAB AAA BAB AAA CD BBA DA"
];
 
def p3: [
"CA BDA ACC BD CCAC CBBAC BBBBB BAABAA ABAD AABB BBH " +
"BBBD ABBAAA CCEA AACAAB BCACC ACBH DCH ADBE ADBB DBE ECE DAA DB CC",
"BC CAC CBAB BDD CDBDE BEBDF ADCDFA DCCFB DBCFC ABDBA BBF AAF BADB DBF " +
"AAAAD BDG CEF CBDB BBB FC"
];
 
def p4: [
"E BCB BEA BH BEK AABAF ABAC BAA BFB OD JH BADCF Q Q R AN AAN EI H G",
"E CB BAB AAA AAA AC BB ACC ACCA AGB AIA AJ AJ " +
"ACE AH BAF CAG DAG FAH FJ GJ ADK ABK BL CM"
];
 
puzzle("p1"; p1),
puzzle("p2"; p2),
puzzle("p3"; p3),
puzzle("p4"; p4)
</syntaxhighlight>
{{output}}
<pre>
p1
reduction by 2
reduction by 0
. 1 1 1 . . . .
1 1 . 1 . . . .
. 1 1 1 . . 1 1
. . 1 1 . . 1 1
1 1 1 1 1 1 . .
1 . 1 1 1 1 1 .
. 1 1 1 1 1 1 .
. 1 . . . . . .
. . 1 1 . . . .
 
p2
reduction by 4
reduction by 0
. . . . . . . . . 1 1 1 1 1 1 . . . . .
. . . . . . 1 1 1 . 1 . 1 1 1 . . . . .
. . . 1 . . 1 1 1 . 1 . . . . . . 1 1 1
. . 1 1 1 . 1 1 1 1 1 1 1 1 1 1 1 1 1 1
. . . 1 . . 1 . 1 . . . . . . . . . . .
. . 1 . 1 . 1 1 . 1 1 . . . . . . . . .
1 1 1 1 1 . . 1 1 . . . . . . . 1 1 . .
1 1 1 1 1 . . . 1 . . . . . . . . 1 . .
1 1 1 1 1 . . 1 1 1 . 1 1 1 . 1 1 1 . .
1 1 1 1 1 1 1 1 . 1 1 1 . 1 1 1 . 1 1 1
 
p3
reduction by 0
1 1 1 . 1 . . . . . . . . . . . . . . .
1 1 . 1 1 1 1 . 1 . . . . . . . . . . .
. 1 . 1 1 1 . 1 1 1 . . . . . . . . . .
1 1 . . . 1 1 1 1 . . . . . . . . . . .
1 1 1 . 1 1 1 . 1 . 1 1 1 . . . . . . .
1 1 1 . . 1 1 . 1 1 . 1 . 1 1 1 . . . .
. 1 1 . 1 1 . 1 1 . 1 1 . 1 1 . . . . .
. . . . 1 1 . 1 . 1 . 1 1 . 1 . 1 . . .
. 1 . 1 1 . 1 . 1 1 1 1 . . . . . . . .
. 1 . 1 . 1 1 . 1 1 . . . . . . . . . .
. 1 1 . 1 1 . 1 1 1 1 1 1 1 1 . . . . .
. 1 1 . 1 1 . 1 1 . 1 1 1 1 . . . . . .
. 1 . 1 1 . 1 1 . 1 . 1 . 1 . . . . . .
. 1 1 1 . 1 1 1 . 1 1 1 1 1 . 1 . . . .
. 1 . 1 . 1 1 1 . 1 . 1 . 1 1 . . . . .
. 1 1 . 1 1 1 . 1 . 1 1 1 . 1 1 1 . . .
. 1 . 1 1 1 . 1 1 . 1 1 1 1 1 1 1 1 . .
. 1 1 1 1 . 1 1 1 . 1 1 1 1 1 1 1 1 . .
. 1 . . 1 1 1 1 . 1 1 . 1 1 1 1 1 . . .
. 1 . 1 1 1 1 . 1 1 . 1 1 . . . . . . .
. . . 1 1 1 1 . 1 1 . . . . . 1 1 1 1 1
. . 1 1 1 1 1 . 1 1 1 . . . . 1 1 1 1 1
. . 1 1 1 1 . 1 . 1 . . . . . . . . . .
. 1 1 1 1 . 1 1 . . . . . . . . . . . .
. 1 1 1 . 1 1 1 . . . . . . . . . . . .
 
p4
reduction by 4
reduction by 0
1 1 1 1 1 . . . . . . . . . . . . . . . . . . . .
1 1 . 1 1 1 . 1 1 . . . . . . . . . . . . . . . .
1 1 . 1 1 1 1 1 . . . . . . . . . . . . 1 . . . .
1 1 . . . . . . . . . . . . . 1 1 1 1 1 1 1 1 . .
1 1 . 1 1 1 1 1 . . . 1 1 1 1 1 1 1 1 1 1 1 . . .
. 1 . 1 . 1 1 . 1 . . . . . . . 1 1 1 1 1 1 . . .
. 1 . 1 1 . 1 . . . . . . . . . . . 1 1 1 . . . .
. 1 1 . 1 . . . . . . . . . . . . . . . . . . . 1
. 1 1 . . . . . 1 1 1 1 1 1 . . . . . . . . . 1 1
. 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 . . . . . 1 1 1 1
. . . . . 1 1 1 1 1 1 1 1 1 1 . . 1 1 1 1 1 1 1 1
. 1 1 . 1 . . . . 1 1 1 1 . 1 1 1 . . 1 1 1 1 1 1
. . . . . . . . 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
. . . . . . . . 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
. . . . . . . 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
. 1 . . . . . . . . . 1 1 1 1 1 1 1 1 1 1 1 1 1 1
. 1 . 1 . . . . . . . 1 1 1 1 1 1 1 1 1 1 1 1 1 1
. 1 1 1 1 1 . . . . . . . . . 1 1 1 1 1 1 1 1 1 .
. . . . . . . . . . . . . . . . 1 1 1 1 1 1 1 1 .
. . . . . . . . . . . . . . . . . 1 1 1 1 1 1 1 .
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">using Base.Iterators
 
struct NonogramPuzzle
Line 1,949 ⟶ 2,533:
 
processtestpuzzles(testnonograms)
</syntaxhighlight>
</lang>
<pre>
Puzzle 1:
Line 2,060 ⟶ 2,644:
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.2.0
 
import java.util.BitSet
Line 2,189 ⟶ 2,773:
newPuzzle(puzzleData)
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,263 ⟶ 2,847:
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">ClearAll[VisualizeGrid, Possibilities, TryRow, TryColumn]
VisualizeGrid[candgrid_List] := StringRiffle[StringJoin/@Replace[candgrid,{{0}->" ",{1}->"#",{0,1}|{1,0}->"."},{2}],"\n"]
Possibilities[clues_List, len_Integer] := Module[{spaces, numclue, spacecands, cands},
Line 2,327 ⟶ 2,911:
,
{n, 4}
]</langsyntaxhighlight>
{{out}}
<pre> ###
Line 2,400 ⟶ 2,984:
To generate the sequence, we use the Java algorithm modified to directly generate bit strings (as integers) rather than character strings.
 
<langsyntaxhighlight Nimlang="nim">import std/[bitops, math, sequtils, strutils]
 
type
Line 2,410 ⟶ 2,994:
Possibility = int
 
# Possibilities described by towtwo masks and a list of integer values.
Possibilities = object
mask0: int # Mask indicating the positions of free cells.
Line 2,550 ⟶ 3,134:
echo ""
solve(rows, cols)
echo ""</langsyntaxhighlight>
 
{{out}}
Line 2,634 ⟶ 3,218:
 
=={{header|Ol}}==
<langsyntaxhighlight lang="scheme">
(import (owl parse))
 
Line 2,796 ⟶ 3,380:
(print))
(list first second third fourth))
</syntaxhighlight>
</lang>
{{out}}
<pre style="height:60ex;overflow:scroll">
Line 2,899 ⟶ 3,483:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use warnings;
 
Line 2,949 ⟶ 3,533:
. '[0.]*' # 6b append static pattern
} split ' ', shift; # 1 for each letter grouping
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,023 ⟶ 3,607:
=={{header|Phix}}==
Deduction only, no exhaustive search.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">grid</span>
Line 3,157 ⟶ 3,741:
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">grid</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre style="float:left">
Line 3,230 ⟶ 3,814:
########
#######
</pre>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">import util, sat.
 
main =>
Hr = "E BCB BEA BH BEK AABAF ABAC BAA BFB OD JH BADCF Q Q R AN AAN EI H G",
Hc = "E CB BAB AAA AAA AC BB ACC ACCA AGB AIA AJ AJ ACE AH BAF CAG DAG FAH FJ GJ ADK ABK BL CM",
Lr = [token_to_hints(Token) : Token in split(Hr)],
Lc = [token_to_hints(Token) : Token in split(Hc)],
MaxR = len(Lr),
MaxC = len(Lc),
foreach (Hints in Lr)
constrain_starts(Hints,MaxC)
end,
foreach (Hints in Lc)
constrain_starts(Hints,MaxR)
end,
M = new_array(MaxR,MaxC),
M :: 0..1,
foreach ({R,Hints} in zip(1..MaxR, Lr))
sum([M[R,C] : C in 1..MaxC]) #= sum([Num : (Num,_) in Hints])
end,
foreach ({R,Hints} in zip(1..MaxR, Lr), (Num,Start) in Hints, C in 1..MaxC-Num+1)
Start #= C #=> sum([M[R,C+I] : I in 0..Num-1]) #= Num
end,
%
foreach ({C,Hints} in zip(1..MaxC, Lc))
sum([M[R,C] : R in 1..MaxR]) #= sum([Num : (Num,_) in Hints])
end,
foreach ({C,Hints} in zip(1..MaxC, Lc), (Num,Start) in Hints, R in 1..MaxR-Num+1)
Start #= R #=> sum([M[R+I,C] : I in 0..Num-1]) #= Num
end,
solve((Lr,Lc,M)),
foreach (R in 1..MaxR)
foreach (C in 1..MaxC)
printf("%2c", cond(M[R,C] == 1, '#', '.'))
end,
nl
end.
 
% convert "BCB" to [(2,_),(3,_),(2,_)]
% a hint is a pair (Num,Start), where Num is the length of the 1 segment and Start is the starting row number or column number
token_to_hints([]) = [].
token_to_hints([C|Cs]) = [(ord(C)-ord('A')+1, _)|token_to_hints(Cs)].
 
% there must be a gap between two neighboring segments
constrain_starts([(Num,Start)],Max) =>
Start :: 1..Max,
Start+Num-1 #<= Max.
constrain_starts([(Num1,Start1),(Num2,Start2)|L],Max) =>
Start1 :: 1..Max,
Start1+Num1 #< Start2,
constrain_starts([(Num2,Start2)|L],Max).
</syntaxhighlight>
{{out}}
<pre>
. . . . . . . . . . . . . . . . . . . . # # # # #
. . # # . . . . . . . . . . . . . . # # # . . # #
. # # . . . . . . . . . . . . . . # # # # # . . #
# # . . . . . . . . . . . . . # # # # # # # # . .
# # . . . . # # # # # . # # # # # # # # # # # . .
# . # . . # # . . . . # . . . . # # # # # # . . .
# . . # # . . . . . # . . . . . . . # # # . . . .
# # . . . . . . . . # . . . . . . . . . . . . . #
. # # . . . . . # # # # # # . . . . . . . . . # #
. . # # # # # # # # # # # # # # # . . . . # # # #
. . . . . # # # # # # # # # # . . # # # # # # # #
. . . . # # . # . # # # # . # # # . . # # # # # #
. . . . . . . . # # # # # # # # # # # # # # # # #
. . . . . . . . # # # # # # # # # # # # # # # # #
. . . . . . . # # # # # # # # # # # # # # # # # #
. . . . . . . # . . . # # # # # # # # # # # # # #
. . . . . . . # . # . # # # # # # # # # # # # # #
. . . . . . . . # # # # # . . . # # # # # # # # #
. . . . . . . . . . . . . . . . . # # # # # # # #
. . . . . . . . . . . . . . . . . . # # # # # # #
</pre>
 
Line 3,238 ⟶ 3,899:
 
Module solve-nonogram.pl
<syntaxhighlight lang="prolog">/*
<lang Prolog>/*
* Nonogram/paint-by-numbers solver in SWI-Prolog. Uses CLP(FD),
* in particular the automaton/3 (finite-state/RE) constraint.
Line 3,304 ⟶ 3,965:
nono(Rows, Cols, Grid),
label(Vars),
print(Grid).</langsyntaxhighlight>
File nonogram.pl, used to read data in a file.
<langsyntaxhighlight Prologlang="prolog">nonogram :-
open('C:/Users/Utilisateur/Documents/Prolog/Rosetta/nonogram/nonogram.txt',
read, In, []),
Line 3,329 ⟶ 3,990:
compute_values([X | T], Current, Tmp, R) :-
V is X - 64,
compute_values(T, [V | Current], Tmp, R).</langsyntaxhighlight>
 
=={{header|Python}}==
Line 3,335 ⟶ 3,996:
 
=== Python 2 ===
<langsyntaxhighlight lang="python">from itertools import izip
 
def gen_row(w, s):
Line 3,453 ⟶ 4,114:
solve("B A A\nA A A")
 
main()</langsyntaxhighlight>
{{out}}
<pre>
Line 3,476 ⟶ 4,137:
=== Python 3 ===
Above code altered to work with Python 3:
<langsyntaxhighlight lang="python">from functools import reduce
 
def gen_row(w, s):
Line 3,580 ⟶ 4,241:
print("Vertical runs:", s[1])
deduce(s[0], s[1])
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
Line 3,589 ⟶ 4,250:
===Translation of Go===
{{trans|Go}}
<syntaxhighlight lang="raku" perl6line># 20220401 Raku programming solution
 
sub reduce(\a, \b) {
Line 3,688 ⟶ 4,349:
"E CB BAB AAA AAA AC BB ACC ACCA AGB AIA AJ AJ "
~"ACE AH BAF CAG DAG FAH FJ GJ ADK ABK BL CM" ),
);</langsyntaxhighlight>
 
===Translation of Perl===
{{trans|Perl}}
<syntaxhighlight lang="raku" perl6line>for './nonogram_problems.txt'.IO.lines.rotor(3, :partial) {
 
my (@rpats,@cpats) := @_[0,1]>>.&makepatterns;
Line 3,728 ⟶ 4,389:
==> map( *.join: '<[0.]>+' )
==> map( '^<[0.]>*' ~ * ~ '<[0.]>*$' )
}</langsyntaxhighlight>
 
=={{header|REXX}}==
Nonogram Solver/Rexx:
<langsyntaxhighlight lang="rexx">/*REXX*/
Parse Arg fn
Parse Var fn ou'.'
Line 4,047 ⟶ 4,708:
If ii > mx Then mx = ii
End
Return len</langsyntaxhighlight>
{{out}}
<pre>
Line 4,264 ⟶ 4,925:
{{libheader|Wren-pattern}}
{{libheader|Wren-math}}
<syntaxhighlight lang="wren">import "./pattern" for Pattern
{{libheader|Wren-fmt}}
<lang ecmascript>import "./patternmath" for PatternNums, Boolean
import "/math" for Nums, Boolean
import "/fmt" for Conv
 
var p = Pattern.new("/s")
Line 4,398 ⟶ 5,057:
]
 
for (puzzleData in [p1, p2, p3, p4]) newPuzzle.call(puzzleData)</langsyntaxhighlight>
 
{{out}}