Package: kdbg
Version: 2.5.0-1
Severity: important

I'm trying to debug a program that uses the SpiderMonkey JavaScript engine - I
don't know if this is a factor.

I will attach the program itself.
You compile it with

  g++ -O0 -g -Wall -o sudoku-solver $(pkg-config --cflags mozilla-js) \
  $(pkg-config --libs mozilla-js) sudoku-solver.cpp

When you run

  kdbg sudoku-solver

You will notice that the startup takes ages.

I'm using KDE Trinity so I can launch system guard and it tells me that gdb is
really busy.

After a few minutes kdbg finally shows the source code.
I have kdbg configured to hide itself until it hits a breakpoint or exception.

Set a breakpoint at line 763, 'cout << "Values";'

When you tell it to run, it minimizes for a few minutes until it hits the
breakpoint in what is a really trivial program that should be instantaneous.

The time kdbg takes seems to increase the more you restart it.



-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (500, 'testing'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.38-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_IE.UTF-8, LC_CTYPE=en_IE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages kdbg depends on:
ii  kdebase-runtime               4:4.4.5-1  runtime components from the offici
ii  libc6                         2.13-4     Embedded GNU C Library: Shared lib
ii  libgcc1                       1:4.6.0-2  GCC support library
ii  libkdecore5                   4:4.4.5-5  the KDE Platform Core Library
ii  libkdeui5                     4:4.4.5-5  the KDE Platform User Interface Li
ii  libkio5                       4:4.4.5-5  the Network-enabled File Managemen
ii  libqt4-dbus                   4:4.7.3-1  Qt 4 D-Bus module
ii  libqt4-network                4:4.7.3-1  Qt 4 network module
ii  libqt4-svg                    4:4.7.3-1  Qt 4 SVG module
ii  libqt4-xml                    4:4.7.3-1  Qt 4 XML module
ii  libqtcore4                    4:4.7.3-1  Qt 4 core module
ii  libqtgui4                     4:4.7.3-1  Qt 4 GUI module
ii  libstdc++6                    4.6.0-2    The GNU Standard C++ Library v3

Versions of packages kdbg recommends:
ii  gdb                           7.2-1      The GNU Debugger

kdbg suggests no packages.

-- no debconf information
// Copyright (C) 2011  Philip Ashmore ([email protected])
// License: LGPLv3.  See LICENSE.txt for the full license.

// (libc.info.gz)Memory-mapped I/O
// https://developer.mozilla.org/En/SpiderMonkey/JSAPI_User_Guide

// Release mode
// g++ -O3 -g -Wall -o sudoku-solver $(pkg-config --cflags mozilla-js) $(pkg-config --libs mozilla-js) sudoku-solver.cpp

// Debug mode
// g++ -O0 -g -Wall -o sudoku-solver $(pkg-config --cflags mozilla-js) $(pkg-config --libs mozilla-js) sudoku-solver.cpp

#include <sys/types.h>
#include <sys/mman.h>
#include <ftw.h>
#include <fcntl.h>
#include <string.h>

#include <iostream>
#include <iomanip>
#include <map>
#include <set>

using namespace std;

#include <jsapi.h>

typedef map< string, uintN > SolutionsMap;
SolutionsMap solutions;

string last_text, puzzle;

uint64_t permute_count = 0;
uint64_t solution_count = 0;

bool g_all = false, g_quiet = false;

namespace Sudoku {

class BoardItem {
public:
	BoardItem(uintN n = 0) : m_data(n) {}
	BoardItem & operator =(uintN x) { set_number(x, false); return *this; }
	uintN number() const { return m_data & 15; }
	bool given() const { return m_data & 16; }
	void set_number(uintN num, bool given_) { m_data = num + (given_ ? 16 : 0); }
	void set_given(bool b) { m_data = number() + (b ? 16 : 0); }
	operator uintN() const { return number(); }
protected:
	uintN m_data;
};
typedef BoardItem Board[9][9];
struct Row {
	Row() : m_data()
	{
		for(uintN n = 0; n < 9; ++n)
			m_data[n] = BoardItem();
	}
	Row(const Row & o)
	: m_data(o.m_data)
	{
		for(uintN n = 0; n < 9; ++n)
			m_data[n] = o.m_data[n];
	}
	Row & operator =(const Row & o)
	{
		for(uintN n = 0; n < 9; ++n)
			m_data[n] = o.m_data[n];
		return *this;
	}
	BoardItem & operator[](uintN n) { return m_data[n]; }
	const BoardItem & operator[](uintN n) const { return m_data[n]; }
	bool empty() const
	{
		uintN n;
		for(n = 0; n < 9; ++n)
			if(m_data[n])
				return false;
		return true;
	}
	inline uintN length() const
	{
		uintN n;
		for(n = 0; n < 9; ++n)
			if(!m_data[n])
				break;
		return n;
	}
protected:
	BoardItem m_data[9];
};
ostream & operator <<(ostream & s, const Row & r)
{
	uintN len = r.length();
	for(uintN n = 0; n < len; ++n) {
		if(n)
			s << ' ';
		s << r[n];
	}
	return s;
}
struct stream_range
{
	stream_range(const Row & r_, uintN m_)
	: row(r_)
	, mark(m_)
	{}
	const Row & row;
	uintN mark;
};
ostream & operator <<(ostream & s, const stream_range & r)
{
	uintN len = r.row.length();
	for(uintN n = 0; n < len; ++n) {
		if(n)
			s << ' ';
		if(n == r.mark)
			s << '[';
		s << r.row[n];
		if(n == r.mark)
			s << ']';
	}
	return s;
}
const Row row_all_filled()
{
	Row r;
	for(uintN n = 0; n < 9; ++n)
		r[n] = n + 1;
	return r;
}
const Row all_filled = row_all_filled();

class Solver
{
public:
	Solver() : m_board() {}
	virtual ~Solver() {}
	virtual uint64_t count() = 0;

	Board m_board;
};

template< bool all, bool quiet >
class SolverT : public Solver
{
public:
	SolverT() : Solver() {}
	Row filter_by_row(uintN x0, uintN y0, const Row & a0)
	{
		Row a1;
		uintN a, x;
		for(a = 0; a < 9; ++a) {
			if(!a0[a])
				continue;
			for(x = 0; x < 9; ++x) {
				if(x == x0)
					continue;
				if(m_board[x][y0] == a)
					break;
			}
			if(x != 9)
				continue;
			a1[a] = a + 1;
		}
		//cout << "filter_by_row[" << x0 << ", " << y0 << "] returning [" << a1
		//	<< ']' << endl;
		return a1;
	}
	Row filter_by_column(uintN x0, uintN y0, const Row & a0)
	{
		Row a1;
		uintN a, y;
		for(a = 0; a < 9; ++a) {
			if(!a0[a])
				continue;
			for(y = 0; y < 9; ++y) {
				if(y == y0)
					continue;
				if(m_board[x0][y] == a)
					break;
			}
			if(y != 9)
				continue;
			a1[a] = a + 1;
		}
		//cout << "filter_by_column[" << x0 << ", " << y0 << "] returning [" << a1
		//	<< ']' << endl;
		return a1;
	}
	Row filter_by_grid(uintN x0, uintN y0, const Row & a0)
	{
		Row a1;
		uintN a, x, y, gx = (x0/3)*3, gy = (y0/3)*3;
		for(a = 0; a < 9; ++a) {
			if(!a0[a])
				continue;
			for(x = gx; x < (gx + 3); ++x) {
				for(y = gy; y < (gy + 3); ++y) {
					if((x == x0) && (y == y0))
						continue;
					if(m_board[x][y] == a)
						break;
				}
				if(y != (gy + 3))
					break;
			}
			if(x != (gx + 3))
				continue;
			a1[a] = a + 1;
		}
		//cout << "filter_by_grid[" << x0 << ", " << y0 << "] returning [" << a1
		//	<< ']' << endl;
		return a1;
	}
	struct BlankFinderResult {
		BlankFinderResult(uintN x_ = 0, uintN y_ = 0, bool g_ = false)
		: x(x_), y(y_), good(g_) {}
		uintN x, y;
		bool good;
	};
	BlankFinderResult first_blank(uintN x0, uintN y0)
	{
		uintN xn = x0;
		for(uintN y = y0; y < 9; ++y) {
			for(uintN x = xn; x < 9; ++x) {
				if(!m_board[x][y])
					return BlankFinderResult(x, y, true);
			}
			xn = 0;
		}
		return BlankFinderResult(0, 0, false);
	}
	BlankFinderResult next_blank(uintN x, uintN y)
	{
		if(x == 8) {
			if(y == 8)
				return BlankFinderResult(0, 0, false);
			return first_blank(0, y+1);
		}
		return first_blank(x+1, y);
	}
	void permute_square(uintN level, uintN x, uintN y)
	{
		if(all) {
			if(!quiet) {
				++permute_count;
				if(!(permute_count % 10000000)) {
					cout << "#solutions " << solution_count
						<< "\n==================\n";
					dump_solution();
				}
			}
		}
		// Iterate through the valid entries for this square.
		// If there are no valid entries then we're sunk.
		Row range = filter_by_grid(x,y
			, filter_by_row(x,y
				, filter_by_column(x,y, all_filled)));
		uintN rl = range.length();
		if(!rl) {
			//cout << '[' << setw(2) << level << "] no solutions possible\n"
			//"==========================\n";
			//dump_solution();
			return; // No solutions possible.
		}
		uintN a;
		if(!level) {
			//this.worker.postMessage({ cmd : "range", value : range.length });
			//this.worker.postMessage({ cmd : "update", value : 0 });
			;
		}
		for(a = 0; a < rl; ++a) {
			//for(uintN i = 0; i < level; ++i)
			//	cout << "  ";
			//cout << "[" << (x+1) << ", " << (y+1) << "] "
			//	<< "-> " << stream_range(range, a) << endl;
			if(!level) ;
				//this.worker.postMessage({ cmd : "update", value : a });
			m_board[x][y] = range[a];
			//this.report();
			BlankFinderResult ret = next_blank(x, y);
			if(!ret.good) {
				++solution_count;

				if(!quiet) {
					if(all) {
						if(!(solution_count % 100000))
							cout << '.' << flush;
					}else{
						cout << "solution\n==================\n";
						dump_solution();
					}
				}
				continue; // All filled.
			}
			permute_square(level + 1, ret.x, ret.y);
		}
		if(!level) ;
			//this.worker.postMessage({ cmd : "update", value : a });
		m_board[x][y] = 0;
		//this.report();
	}
	uint64_t count_blanks()
	{
		uint64_t count = 0;
		for(uintN x = 0; x < 9; ++x)
			for(uintN y = 0; y < 9; ++y)
				if(!m_board[x][y])
					++count;
		return count;
	}
	uint64_t count()
	{
		solution_count = 0;
		cout << "Initial puzzle\n==================\n";
		dump_solution();
		if(!all) {
			if(count_blanks() > 63) {
				cerr << "too many blanks" << endl;
				return 0;
			}
		}
		if(!valid())
			return 0;

		BlankFinderResult ret = first_blank(0,0);
		if(!ret.good)
			return 1; // Already done.

		permute_square(0, ret.x, ret.y);
	
		//document.gSudokuBoard.m_pieces = backup;
		//this.report();
		return solution_count;
	}
	void dump_solution()
	{
		for(uintN y = 0; y < 9; ++y) {
			//cout << '[' (9-y) << ']';
			for(uintN x = 0; x < 9; ++x) {
				uintN v = m_board[x][9-y-1].number();
				if(v)
					cout << ' ' << v;
				else
					cout << "  ";
			}
			cout << '\n';
		}
	}
	bool row_valid(uintN y)
	{
		BlankFinderResult found[9];
		uintN x;
		for(x = 0; x < 9; ++x) {
			if(!m_board[x][y])
				continue;
			BlankFinderResult & loc = found[m_board[x][y]-1];
			//cout << "Saw " << m_board[x][y] << " in "
			//	"(" << (x+1) << ", " << (y+1) << ")." << endl;
			if(loc.good) {
				cerr << "row_valid: number " << m_board[x][y]
					<< " found in (" << (loc.x+1) << ", " << (loc.y+1) <<
					") AND in (" << (x+1) << ", " << (y+1) << ")." << endl;
				return false;
			}
			loc = BlankFinderResult(x, y, true);
			//cout << "Noting " << m_board[x][y] << " in "
			//	"(" << (x+1) << ", " << (y+1) << ")." << endl;
		}
		return true;
	}
	bool column_valid(uintN x)
	{
		BlankFinderResult found[9];
		uintN y;
		for(y = 0; y < 9; ++y) {
			if(!m_board[x][y])
				continue;
			BlankFinderResult & loc = found[m_board[x][y]-1];
			if(loc.good) {
				cerr << "column_valid: number " << m_board[x][y]
					<< " found in (" << (loc.x+1) << ", " << (loc.y+1) <<
					") AND in (" << (x+1) << ", " << (y+1) << ")." << endl;
				return false;
			}
			loc = BlankFinderResult(x, y, true);
		}
		return true;
	}
	bool grid_valid(uintN x0, uintN y0)
	{
		BlankFinderResult found[9];
		uintN x, y;
		for(x = x0; x < (x0+3); ++x) {
			for(y = y0; y < (y0+3); ++y) {
				if(!m_board[x][y])
					continue;
				BlankFinderResult & loc = found[m_board[x][y]-1];
				if(loc.good) {
					cerr << "grid_valid: number " << m_board[x][y]
						<< " found in (" << (loc.x+1) << ", " << (loc.y+1) <<
						") AND in (" << (x+1) << ", " << (y+1) << ")." << endl;
					return false;
				}
				loc = BlankFinderResult(x, y, true);
			}
		}
		return true;
	}
	bool valid()
	{
		for(uintN y = 0; y < 9; ++y)
			if(!row_valid(y))
				return false;
		for(uintN x = 0; x < 9; ++x)
			if(!column_valid(x))
				return false;
		for(uintN x = 0; x < 3; ++x)
			for(uintN y = 0; y < 3; ++y)
				if(!grid_valid(x*3,y*3))
					return false;
		return true;
	}
};

} // namespace Sudoku {

JSBool board(JSContext *cx, JSObject *pObj, uintN argc, jsval *argv, jsval *vp)
{
	cout << "board" << endl;
	(void)pObj;
	
	if ((!argc) || (!JSVAL_IS_OBJECT(argv[0]))) {
		cerr << "Failed to get board data." << endl;
		return JS_FALSE;
	}
	JSObject * obj = JSVAL_TO_OBJECT(argv[0]);
	if(!obj) {
		cerr << "Board data isn't an object." << endl;
		return JS_FALSE;
	}
	uintN n, rc;
	
	Sudoku::Solver * psolver;
	if(g_all) {
		if(g_quiet)
			psolver = new Sudoku::SolverT< true, true >;
		else
			psolver = new Sudoku::SolverT< true, false >;
	}else{
		if(g_quiet)
			psolver = new Sudoku::SolverT< false, true >;
		else
			psolver = new Sudoku::SolverT< false, false >;
	}
	Sudoku::Solver & solver = * psolver;
	for(n = 0; n < 9; ++n) {
		char name[3];
		cout << '[' << (n+1) << ']';
		sprintf(name, "%u", n);
		jsval numarr;
		JSBool b = JS_GetProperty(cx, obj, name, & numarr);
		if(!b) {
			cerr << "\nFailed to get board data for number " << (n + 1) << '.'
				<< endl;
			return JS_FALSE;
		}
		if(!JSVAL_IS_OBJECT(numarr))
			return JS_FALSE;
		JSObject * numobj = JSVAL_TO_OBJECT(numarr);
		if(!numobj) {
			cerr << "\nNumber [" << (n+1) << "] object isn't an object."
				<< endl;
			return JS_FALSE;
		}

		for(rc = 0; rc < 81; ++rc) { // At most 81 squares.
			char name[3];
			sprintf(name, "%u", rc);
			jsval numval;
			// Any not-present property has a value of undefined.
			JSBool b = JS_GetProperty(cx, numobj, name, & numval);
			if(!b) {
				cerr << "\nFailed to get board data[" << rc << "] for number "
					<< (n + 1) << '.' << endl;
				return JS_FALSE;
			}
			// Try all those that work.
			uint32_t val, x, y;
			// undefined -> uint32_t(0).
			if(!JS_ConvertArguments(cx, 1, & numval, "u", &val) || !val)
				break;
			x = (val / 10) - 1; y = (val % 10) - 1;
			cout << " " << (x+1) << (y+1);
			solver.m_board[x][y] = n + 1;
		}
		cout << '\n';
	}
	solver.count();
	solutions[puzzle] = solution_count;
	delete psolver;
	JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined */
	return JS_TRUE;
}
JSBool text(JSContext *cx, JSObject *pObj, uintN argc, jsval *argv, jsval *vp)
{
	(void)pObj;
	(void)argv;
	const char *cmd;

	if (!JS_ConvertArguments(cx, argc, argv, "s", &cmd))
		return JS_FALSE;

	last_text = cmd;
	//cout << "text(" << last_text << ')' << endl;
	JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined */
	return JS_TRUE;
}
JSBool noop(JSContext *cx, JSObject *pObj, uintN argc, jsval *argv, jsval *vp)
{
	(void)pObj;
	(void)argc;
	(void)argv;
	JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined */
	//cout << "noop" << endl;
	return JS_TRUE;
}

static JSFunctionSpec myjs_global_functions[] = {
	JS_FS("clear",    noop,  1, 0, 0),
	JS_FS("text",     text,  1, 0, 0),
	JS_FS("board",    board, 1, 0, 0),
	JS_FS("delay",    noop,  1, 0, 0),
	JS_FS("number",   noop,  1, 0, 0),
	JS_FS("numbers",  noop,  1, 0, 0),
	JS_FS("l2r",      noop,  1, 0, 0),
	JS_FS("r2l",      noop,  1, 0, 0),
	JS_FS("b2t",      noop,  1, 0, 0),
	JS_FS("t2b",      noop,  1, 0, 0),
	JS_FS("slide",    noop,  1, 0, 0),
	JS_FS("sliders",  noop,  1, 0, 0),
	JS_FS("slideX",   noop,  1, 0, 0),
	JS_FS("slidersX", noop,  1, 0, 0),
	JS_FS("textX",    noop,  1, 0, 0),
	JS_FS("numberX",  noop,  1, 0, 0),
	JS_FS("numbersX", noop,  1, 0, 0),
	JS_FS("l2rX",     noop,  1, 0, 0),
	JS_FS("r2lX",     noop,  1, 0, 0),
	JS_FS("b2tX",     noop,  1, 0, 0),
	JS_FS("t2bX",     noop,  1, 0, 0),
	JS_FS_END
};

/* The class of the global object. */
static JSClass global_class =
{ "global"
, JSCLASS_GLOBAL_FLAGS
, JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub // JS_StrictPropertyStub
, JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, JS_FinalizeStub
, JSCLASS_NO_OPTIONAL_MEMBERS
};

/* The error reporter callback. */
void reportError(JSContext *cx, const char *message, JSErrorReport *report)
{
	fprintf(stderr, "%s:%u:%s\n",
			report->filename ? report->filename : "<no filename>",
			(unsigned int) report->lineno,
			message);
}

/* JS variables. */
JSRuntime *rt;
JSContext *cx;
JSObject  *global;

string dir;

string puzzle_fn_name(const char * file)
{
	const char * last_slash = strrchr(file, '/');
	if(!last_slash)
		return "no_slash";
	const char * last_dot = strrchr(last_slash, '.');
	if(!last_dot)
		return "no_dot";
	return string(last_slash + 1, last_dot);
}

int process_script(const char * file)
{
	// Call function puzzlefn_eh20081122md()
	puzzle = puzzle_fn_name(file);
	if(g_all) {
		if(puzzle != "empty")
			return 0;
	}else{
		if(puzzle == "empty")
			return 0;
	}

	int fd = open(file, O_RDONLY);
	if(!fd)
		return 1;
	size_t length = lseek(fd, 0, SEEK_END);
	lseek(fd, 0, SEEK_SET);
	char * src = (char *)mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
	if(src == ((char *)-1)) {
		cerr << "Couldn't mmap(" << file << ")." << endl;
		return 1;
	}
	JSBool b = JS_EvaluateScript(/*JSContext * */cx, /*JSObject *obj*/global,
    src, /*uintN */length, file,
    /*uintN lineno*/1, /*jsval *rval*/0);
	if(!b) {
		cerr << "Executing script(" << file << ") failed." << endl;
		munmap(src, length);
		return 1;
	}
	munmap(src, length);

	string call = string("puzzlefn_") + puzzle + "()";

	cout << "Calling " << call << " for file(" << file << ")." << endl;

	b = JS_EvaluateScript(/*JSContext * */cx, /*JSObject *obj*/global
		, call.c_str(), /*uintN */call.length(), "<call>"
		, /*uintN lineno*/1, /*jsval *rval*/0);
	if(!b) {
		cerr << "Executing call for file(" << file << ") failed." << endl;
		return 1;
	}
	return 0;
}

set< string > to_process;

int process_dir_entry(const char * file, const struct stat * p, int type)
{
	if(type != FTW_F)
		return 0;
	if(file[strlen(file)-1] == '~')
		return 0; // Skip backups.
	puzzle = puzzle_fn_name(file);
	if(g_all) {
		if(puzzle != "empty")
			return 0;
	}else{
		if(puzzle == "empty")
			return 0;
	}
	to_process.insert(file);
	return 0;
}

int process_dir()
{
	int ret = ftw(dir.c_str(), & process_dir_entry, 100);
	if(ret)
		return ret;
	cout << to_process.size() << " files to process." << endl;
	set< string >::const_iterator i = to_process.begin();
	set< string >::const_iterator j = to_process.end();
	for(; i != j; ++i) {
		const string & file = *i;
		cout << "Processing " << file << '{' << endl;
		ret = process_script(file.c_str());
		cout << "Processing " << file << "} " << ret << endl;
		if(ret)
			return ret;
	}
	return 0;
}
int Usage()
{
	cerr << "Usage: sudoku-solver [-a] [-q] <dir>" << endl;
	return 1;
}
int mainX(int argc, const char *argv[])
{
	for(int narg = 1; narg < argc; ++narg) {
		const char * arg = argv[narg];
		if(strlen(arg) < 1)
			return Usage();
		if(arg[0] == '-') {
			if(strlen(arg) < 2)
				return Usage();
			if(arg[1] == 'a')
				g_all = true;
			else if(arg[1] == 'q')
				g_quiet = true;
			else
				return Usage();
		}else{
			if(dir.length())
				return Usage();
			dir = arg;
		}
	}
	/* Create a JS runtime. */
	rt = JS_NewRuntime(8L * 1024L * 1024L);
	if (rt == NULL)
		return 1;

	/* Create a context. */
	cx = JS_NewContext(rt, 8192);
	if (cx == NULL)
		return 1;
	JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT /*| JSOPTION_METHODJIT*/);
	JS_SetVersion(cx, JSVERSION_LATEST);
	JS_SetErrorReporter(cx, reportError);

	/* Create the global object in a new compartment. */
	//global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
	//global = JS_NewGlobalObject(cx, &global_class, NULL);
	global = JS_NewObject(cx, &global_class, NULL, NULL);
	if (global == NULL)
		return 1;

	/* Populate the global object with the standard globals,
		like Object and Array. */
	if (!JS_InitStandardClasses(cx, global))
		return 1;

	/* Your application code here. This may include JSAPI calls
		to create your own custom JS objects and run scripts. */
	if (!JS_DefineFunctions(cx, global, myjs_global_functions))
		return 1;

	// Read in the scripts, one at a time, and print their solutions.
	int ret = 0;
	if(process_dir())
		ret = 1;

	/* Cleanup. */
	JS_DestroyContext(cx);
	JS_DestroyRuntime(rt);
	JS_ShutDown();

	cout << "Summary." << endl;
	cout << "Name                 Count" << endl;
	cout << "==================== =====" << endl;
	SolutionsMap::const_iterator i = solutions.begin();
	SolutionsMap::const_iterator j = solutions.end();
	for(; i != j; ++i)
		cout << left << setw(20) << i->first << ' ' << right << setw(5)
			<< i->second << endl;
	return ret;
}

int main(int argc, const char *argv[])
{
	(void)argc;
	(void)argv;
	Sudoku::Row row;
	cout << "Values";
	for(int n = 0; n < 9; ++n)
		cout << ' ' << uintN(row[n]);
	cout << endl;
	return 0;
}

Reply via email to