# Ultimate nonograms solver written in Rust language. [![Crates.io](https://img.shields.io/crates/v/nonogrid)](https://crates.io/crates/nonogrid) [![minimum rustc version](https://img.shields.io/badge/rustc-1.39+-green.svg)](https://blog.rust-lang.org/2019/11/07/Rust-1.39.0.html) [![Build Status](https://travis-ci.org/tsionyx/nonogrid.svg?branch=master)](https://travis-ci.org/tsionyx/nonogrid) [![codecov](https://codecov.io/gh/tsionyx/nonogrid/branch/master/graph/badge.svg)](https://codecov.io/gh/tsionyx/nonogrid) ``` $ wget -qO- https://webpbn.com/export.cgi --post-data "id=32480&fmt=nin&go=1" | cargo run ``` ![Rust logo as nonogram image](examples/rust_logo.png) ## Features - solves binary (blank-and-white) and colored (<32 colors) nonograms; - supports wide variety of formats: - own TOML-based format ([example](examples/hello.toml)) (with `ini` feature); - [webpbn](https://webpbn.com)-s primary [XML format](https://webpbn.com/pbn_fmt.html) (with `xml` feature); - some other formats that can be [exported from webpbn](https://webpbn.com/export.cgi): _faase, ish, keen, makhorin, nin, olsak, ss, syro_. All of them, except _olsak_, supports only black-and-white puzzles; - the encoded format of https://nonograms.org. - combines several solving methods to achieve speed for various puzzle types: - very simple puzzles solved line-by-line (`line` + `propagation`); - if the puzzle cannot be solved, the `probing` phase begins, where some assumptions made about every unsolved cell following by the analysis of the impact they bring; - if the puzzle not solvable even here, the searching algorithms enabled: by default `backtracking` is used that colors a cell, then another one, and go on, until the solution(s) is found. There is another option (with `sat` feature): special SAT-solver, that uses the results of previous phases to more effectively explore the solution space. By default, the `--features="args std_time logger ini"` are enabled, but you can disable almost anything to speed up and/or shrink the size of the binary. ### Arguments parsing To support command-line arguments, the `args` feature enabled by default. You can disable it, but then you will not able to set solving timeout or maximum number of solutions to find. It also can be disabled when using the solver as a library in another projects, [e.g.](https://github.com/tsionyx/nono/blob/8e2f8f27/Cargo.toml#L19) ### Timeout (std_time) By default, you can provide the `--timeout` option to stop backtracking after reaching the specified time limit. You can disable this feature (`std_time`), and the timeout option will simply be ignored. ### Logging support To support pretty formatted logs the `env_logger` crate enabled by default. The simplest way to view them is to provide environment variable `RUST_LOG=nonogrid=`. For example, in the [benchmarks script](benches/batch.sh), the `RUST_LOG=nonogrid=warn` is used to inspect the intermediate results of solving. As always, you can disable the option by **skipping** the `--features=logger` while building. ### TOML puzzles parsing support [My custom TOML-based format](examples/hello.toml) is supported by default via feature `ini`. It can be disabled when using the solver as a library in another projects, [e.g.](https://github.com/tsionyx/nono/blob/8e2f8f27/Cargo.toml#L19) ### SAT By default, the backtracking algorithm used for solving hard puzzles. The feature `sat` allows to use the [SAT](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem) solver for such a job. The most of hard puzzles solved significantly faster with this option. The latest benchmarks show that the SAT-solver is very effective for the hardest webpbn puzzles (actually, only two puzzles found that solved longer than an hour: [25820](https://webpbn.com/25820) and [26520](https://webpbn.com/26520)). ### XML puzzles parsing support The [Jan Wolter's XML format](https://webpbn.com/pbn_fmt.html) supported via feature `xml`. You can enable it by building with the `--features=xml`. ### Colored nonograms You can enable the feature `colors` to allow printing colored nonograms with real terminal colors: ``` wget -qO- https://webpbn.com/export.cgi --post-data "fmt=olsak&go=1&id=2192" | cargo run --no-default-features --features=colors ``` ### HTTP client Solved puzzles can be automatically downloaded from the Internet with the `reqwest` library, but it requires too many dependencies and increases compile time, so it's optional by default. Enable it as simple as: ``` cargo run --features=web,xml -- --webpbn 5933 ``` ### Threading By default, the solver and all the algorithms are single-threaded. To use the solver's structures in multi-threaded environment, provide the `threaded` feature. In essence, this feature replaces every occurrence of `Rc/RefCell` with `Arc/RwLock`. ### Probing tweaking When the 'logical' solving (`line/propagation`) gets stuck, the `probing` phase starting which tries every variant for every unsolved cells. It does this by calculating the priority for each cell: ``` P = N + R + C, where 0<=N<=4 - number of neighbours which are solved cells or puzzle edges. For example, the cell which has all 4 heighboring cells solved, has N = 4. The upper left cell of the puzzle without any neighbours solved, has N = 2, since it has 2 edges of the puzzle. 0<=R<=1 - row solution rate, the ratio of solved cells in the row to total number of cells (width) 0<=C<=1 - column solution rate, the ratio of solved cells in the column to total number of cells (height) ``` By default, every cell with `P>=0` checked, but you can customize the threshold by specifying the `LOW_PRIORITY` environment variable. For example, running ``` LOW_PRIORITY=1 nonogrid puzzles/6574.xml ``` can be solved 3 times faster than standard way, by skipping the probing of cells with `P < 1`. ## Usage examples ### Solve locally saved puzzles from https://webpbn.com (XML format) ``` cargo build --features="xml" # solve puzzle https://webpbn.com/2992 wget 'https://webpbn.com/XMLpuz.cgi?id=2992' -O 2992.xml target/debug/nonogrid 2992.xml # with pipe wget -qO- 'https://webpbn.com/XMLpuz.cgi?id=2992' | target/debug/nonogrid ``` ### Solve puzzles from https://webpbn.com (with embedded HTTP-client) ``` cargo build --features="web,xml" # solve puzzle https://webpbn.com/5933 target/debug/nonogrid -w 5933 ``` ### Solve locally saved puzzles from https://nonograms.org ``` cargo build # solve puzzle https://webpbn.com/2992 wget -qO- 'https://www.nonograms.org/nonograms/i/2581' | grep 'var d=' > 2581.js target/debug/nonogrid 2581.js # with pipe wget -qO- 'https://www.nonograms.org/nonograms/i/2581' | target/debug/nonogrid ``` ### Solve puzzles from https://nonograms.org (with embedded HTTP-client) ``` cargo build --features="web" # solve puzzle https://www.nonograms.org/nonograms/i/13588 target/debug/nonogrid -o 13588 # solve puzzle https://www.nonograms.org/nonograms2/i/10270 target/debug/nonogrid -o 10270 ``` ### Solve other formats #### [TOML format](examples) ``` cargo build target/debug/nonogrid examples/hello.toml ``` #### Webpbn's [exportable formats](https://webpbn.com/export.cgi) ``` wget -qO- https://webpbn.com/export.cgi --post-data "fmt=syro&go=1&id=2040" | cargo run --no-default-features ``` ## Development ### See the INFO logs and unfold backtrace on panic ``` RUST_BACKTRACE=1 RUST_LOG=nonogrid=info cargo run -- examples/hello.toml ```