diff --git a/.travis.yml b/.travis.yml index 5178adc..4705c2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: python python: - "2.6" - "2.7" - - "3.2" - "3.3" - "3.4" - "3.5" @@ -10,4 +9,4 @@ install: - "pip install -r requirements.txt" - "python setup.py install" script: py.test -email: false \ No newline at end of file +email: false diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c92db73 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,46 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: example.json", + "type": "python", + "request": "launch", + "program": "example.py", + "console": "integratedTerminal", + "args": [ + "json", + "--json", "example.json" + ] + }, + { + "name": "Python: example csv with svg", + "type": "python", + "request": "launch", + "program": "example.py", + "console": "integratedTerminal", + "args": [ + "--svgout", "example.svg", + "csv", + "--columncsv", "example.columns.csv", + "--rowcsv", "example.rows.csv" + ] + }, + { + "name": "Python: Current File (Integrated Terminal)", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + }, + { + "name": "Python: Current File (External Terminal)", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "externalTerminal" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..09b1ca0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "python.unitTest.pyTestArgs": [ + "tests" + ], + "python.unitTest.unittestEnabled": false, + "python.unitTest.nosetestsEnabled": false, + "python.unitTest.pyTestEnabled": true, + "restructuredtext.confPath": "" +} \ No newline at end of file diff --git a/README.rst b/README.rst index 024716a..f627826 100644 --- a/README.rst +++ b/README.rst @@ -11,14 +11,29 @@ This solver can be used to create nonogram puzzles given a successful final solu :target: https://travis-ci.org/mprat/nonogram-solver :alt: Build status +Example Usage +----------------------- +See example.py for sample use of the library. + +.. code:: bash + + python3 example.py json --json example.json + python3 example.py --svgout example.svg csv --columncsv example.columns.csv --rowcsv example.rows.csv + +SVG Example: + +.. image:: example.svg + :height: 420 + :width: 305 + Installation --------- +----------------------- To install, run `pip install nonogram-solver`. Project Website ---------- +----------------------- PyPI: `https://pypi.python.org/pypi/nonogram-solver `_ Github: `https://github.com/mprat/nonogram-solver `_ diff --git a/example.columns.csv b/example.columns.csv new file mode 100644 index 0000000..677c3ae --- /dev/null +++ b/example.columns.csv @@ -0,0 +1,8 @@ + +9 +9 +2,2 +2,2 +4 +4 + diff --git a/example.json b/example.json new file mode 100644 index 0000000..3cdcb60 --- /dev/null +++ b/example.json @@ -0,0 +1,25 @@ +{ +"rows":[ +[], +[4], +[6], +[2,2], +[2,2], +[6], +[4], +[2], +[2], +[2], +[] +], +"columns":[ +[], +[9], +[9], +[2,2], +[2,2], +[4], +[4], +[] +] +} diff --git a/example.py b/example.py new file mode 100644 index 0000000..7240434 --- /dev/null +++ b/example.py @@ -0,0 +1,93 @@ +import numpy as np +from nonogram_solver import solver +from nonogram_solver.nonogram import Nonogram +import argparse + +parser = argparse.ArgumentParser(description="Nonogram solver") +parser.add_argument("--verbose",action='store_true') +parser.add_argument("--addcontraints",action='store_true',help='add_puzzle_constraints arg to solver') +parser.add_argument("--svgout",help='svgoutfile',type=str) +subparsers=parser.add_subparsers(title='subcommands',dest='subparser_name') +jsongroup = subparsers.add_parser('json',help='JSON file input') +jsongroup.add_argument("--json", help="JSON File Path", required=True, type=str) +csvgroup = subparsers.add_parser('csv',help='CSV file input') +csvgroup.add_argument("--columncsv", help="Column Constraint File Path", required=True, type=str) +csvgroup.add_argument("--rowcsv", help="Row Constraint File Path", required=True, type=str) + +args = parser.parse_args() + +if not args.subparser_name: + parser.print_help() + exit(2) + +nonogram = Nonogram() +nonogram.rows_constraints = [] +nonogram.cols_constraints = [] +nonogram.solution_list=[] + +if args.subparser_name == 'json': + import json + with open(args.json) as jsonfile: + puzzle = json.load(jsonfile) + if not puzzle['rows'] or not puzzle['columns']: + print("No column or row info") + exit(1) + nonogram.n_cols=len(puzzle['columns']) + nonogram.n_rows=len(puzzle['rows']) + for c in puzzle['columns']: + nonogram.cols_constraints.append(c) + for r in puzzle['rows']: + nonogram.rows_constraints.append(r) + +if args.subparser_name == 'csv': + import csv + with open(args.columncsv, newline='') as columncsv: + columns = csv.reader(columncsv, quoting=csv.QUOTE_NONNUMERIC) + for row in columns: + nonogram.cols_constraints.append(list(map(int, row))) + nonogram.n_cols=len(nonogram.cols_constraints) + with open(args.rowcsv, newline='') as rowcsv: + rows = csv.reader(rowcsv, quoting=csv.QUOTE_NONNUMERIC) + for row in rows: + nonogram.rows_constraints.append(list(map(int, row))) + nonogram.n_rows=len(nonogram.rows_constraints) + +import io +from contextlib import redirect_stdout + +verbose = io.StringIO() +with redirect_stdout(verbose): + solveable, nonogram_solver = solver.solve(nonogram, add_puzzle_constraints=args.addcontraints) + +if args.verbose: + print(verbose.getvalue()) +if solveable: + print("The puzzle was solvable") +else: + print("The puzzle was not solvable") + +#import pprint +#pp = pprint.PrettyPrinter(indent=4) +#pp.pprint(nonogram_solver.puzzle_state) + +for r in nonogram_solver.puzzle_state: + print(*list(map(lambda x: '█' if x==1 else ' ', r)),sep='') + + +if args.svgout: + import svgwrite + from svgwrite import cm + dwg = svgwrite.Drawing(args.svgout, profile='tiny') + shapes = dwg.add(dwg.g(id='shapes', fill='white')) + + rc=0 + for r in nonogram_solver.puzzle_state: + cc=0 + for c in r: + if c == 1: + shapes.add(dwg.rect(insert=(cc*cm, rc*cm), size=(1*cm, 1*cm), fill='black', stroke='black', stroke_width=1)) + else: + shapes.add(dwg.rect(insert=(cc*cm, rc*cm), size=(1*cm, 1*cm), fill='white', stroke='black', stroke_width=1)) + cc=cc+1 + rc=rc+1 + dwg.save() \ No newline at end of file diff --git a/example.rows.csv b/example.rows.csv new file mode 100644 index 0000000..2c749ab --- /dev/null +++ b/example.rows.csv @@ -0,0 +1,11 @@ + +4 +6 +2,2 +2,2 +6 +4 +2 +2 +2 + diff --git a/example.svg b/example.svg new file mode 100644 index 0000000..b7e2561 --- /dev/null +++ b/example.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 296d654..40d9028 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -numpy \ No newline at end of file +numpy +svgwrite \ No newline at end of file diff --git a/setup.py b/setup.py index b0ab485..229e51a 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,6 @@ 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5'