Hi,
Here's the code I wrote on 0.94 level (sorry, haven't tried 0.95 much yet).
It will require the following change in gaddag.h in order to handle the
negative indexing generated by the gaddgag minimization:
inline const GaddagNode *
GaddagNode::firstChild() const
{
int p = (data[0] << 16) + (data[1] << 8) + (data[2]);
if (p == 0) {
return 0;
} else {
if(p & 0x00800000)
p |= 0xff000000;
return this + p;
}
}
That's it. With that change the minimized gaddag, quacletest seemed to
work. Let me know how it goes.
On a separate note, every time I compile the Qt based code, it fails to
find the built libraries, because they are placed either under release
or debug directories. Am I missing something to make my life easier?
Francisco Moraes
/*
* Quackle -- Crossword game artificial intelligence and analysis tool
* Copyright (C) 2005-2006 Jason Katz-Brown and John O'Laughlin.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <stdio.h>
#include <string>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <map>
using namespace std;
class Node {
public:
char c;
bool t;
vector<Node> children;
Node* parent;
int pointer;
int location;
int oldpointer;
bool lastchild;
void pushword(string word);
void print(string prefix, int nthChild, Node* parent);
bool dexplored;
bool sexplored;
bool lexplored;
int d;
int s;
int l;
int depth();
int subtreesize();
int lettersum();
bool equals(Node &n);
bool deleted;
Node* cloneof;
bool written;
};
vector< Node* > nodelist;
Node root;
vector< int > ofdepth[20][100];
bool Node::equals(Node &n)
{
if (c != n.c)
return false;
if (children.size() != n.children.size())
return false;
if (t != n.t)
return false;
if (l != n.l)
return false;
if (s != n.s)
return false;
if (d != n.d)
return false;
for (int i = 0; i < children.size(); i++)
if (!children[i].equals(n.children[i]))
return false;
return true;
}
int Node::depth()
{
if (dexplored)
return d;
dexplored = true;
if (children.size() == 0)
{
d = 1;
return d;
}
int childmax = 0;
for (int i = 0; i < children.size(); i++)
{
int d = children[i].depth();
if (d > childmax)
childmax = d;
}
d = 1 + childmax;
return d;
}
int Node::subtreesize()
{
if (sexplored)
return s;
sexplored = true;
if (children.size() == 0)
{
s = 1;
return s;
}
int childsum = 0;
for (int i = 0; i < children.size(); i++)
{
int s = children[i].subtreesize();
childsum += s;
}
s = 1 + childsum;
return s;
}
int Node::lettersum()
{
if (lexplored)
return l;
lexplored = true;
int thisletter = c - 'A' + 1;
if (children.size() == 0)
{
l = thisletter;
return l;
}
int childsum = 0;
for (int i = 0; i < children.size(); i++)
{
int s = children[i].lettersum();
childsum += s;
}
l = thisletter + childsum;
return l;
}
void Node::print(string prefix, int nthChild, Node* parent) {
written = true;
if (t) {
// cout << prefix << endl;
}
// cout << "prefix: " << prefix << ", children: " << children.size() <<
", deleted: " << deleted << ", oldpointer: " << oldpointer << ", nthChild: " <<
nthChild << endl;
if (children.size() == 0)
{
// cout << " no children. nothing to do." << endl;
return;
}
if (!deleted)
{
// cout << " Setting pointer to " << nodelist.size() << " before
I push_back the children." << endl;
pointer = nodelist.size();
}
else
{
pointer = cloneof->pointer;
// cout << " Setting pointer to clone's (" << pointer << ") and
not pushing anything." << endl;
}
if (!deleted)
{
for (int i = 0; i < children.size(); i++) {
children[i].parent = this;
nodelist.push_back(&children[i]);
}
for (int i = 0; i < children.size(); i++) {
if (!children[i].deleted)
children[i].print(prefix + children[i].c, i, this);
else if (!children[i].cloneof->written)
children[i].cloneof->print(prefix +
children[i].c, i, this);
}
}
if (children.size() > 0)
children[children.size() - 1].lastchild = true;
}
void Node::pushword(string word) {
if (word.length() == 0) {
t = true;
}
else {
char first = word[0];
string rest = word.substr(1, word.length() - 1);
int index = -1;
// cout << "first: " << first << ", rest: " << rest << endl;
for (int i = 0; i < children.size(); i++) {
if (children[i].c == first) {
index = i;
i = children.size();
}
}
if (index == -1) {
Node n;
n.c = first;
n.t = false;
n.pointer = 0;
n.oldpointer = 0;
n.lastchild = false;
children.push_back(n);
index = children.size() - 1;
}
children[index].pushword(rest);
}
dexplored = false;
sexplored = false;
lexplored = false;
deleted = false;
written = false;
}
void minimize()
{
nodelist[0]->depth();
nodelist[0]->subtreesize();
nodelist[0]->lettersum();
for (int i = 0; i < nodelist.size(); i++)
{
int d = nodelist[i]->d;
if ((d >= 1) & (d <= 20))
ofdepth[d - 1][nodelist[i]->l%100].push_back(i);
}
for (int d = 0; d < 20; d++)
{
for (int l = 0; l < 100; l++)
{
//cout << "l: " << l << endl;
if (ofdepth[d][l].size() > 0)
for (vector<int>::iterator it =
ofdepth[d][l].begin(); it != ofdepth[d][l].end() - 1; it++)
{
if (!nodelist[(*it)]->deleted)
{
for (vector<int>::iterator jt =
it + 1; jt != ofdepth[d][l].end(); jt++)
{
if
(!nodelist[(*jt)]->deleted)
{
// cout <<
"Comparing " << (*it) << " and " << (*jt) << endl;
if
(nodelist[(*it)]->equals(nodelist[(*jt)][0]))
{
//
cout << "Hey! " << (*it) << " == " << (*jt) << endl;
//
ones[l].erase(jt);
nodelist[(*jt)]->deleted = true;
nodelist[(*jt)]->cloneof = nodelist[(*it)];
}
}
}
}
}
}
for (int i = 0; i < nodelist.size(); i++)
{
nodelist[i]->oldpointer = nodelist[i]->pointer;
nodelist[i]->pointer = 0;
nodelist[i]->written = false;
}
}
nodelist.clear();
nodelist.push_back(&root);
root.print("", 0, NULL);
cout << "nodelist.size(): " << nodelist.size() << endl;
}
int main() {
ifstream file("gaddaginput.raw");
root.t = false;
root.c = '.';
root.pointer = 0;
root.lastchild = true;
while(!file.eof()) {
string word;
file >> word;
if (!file.eof()) {
root.pushword(word);
}
}
nodelist.push_back(&root);
root.print("", 0, NULL);
cout << "nodelist.size(): " << nodelist.size() << endl;
minimize();
ofstream out("output.gaddag", ios::out | ios::binary);
for (int i = 0; i < nodelist.size(); i++) {
//cout << nodelist[i]->c << " " << nodelist[i]->pointer << " " <<
nodelist[i]->t << " " << nodelist[i]->lastchild << endl;
Node* n = nodelist[i];
unsigned int p;
if (n->deleted)
{
p = (unsigned int)(n->cloneof->pointer);
// n = nodelist[i]->cloneof;
}
else
p = (unsigned int)(n->pointer);
if(p != 0)
p -= i;
char bytes[4];
unsigned char n1 = (p & 0x00FF0000) >> 16;
unsigned char n2 = (p & 0x0000FF00) >> 8;
unsigned char n3 = (p & 0x000000FF);
unsigned char n4;
if (n->c == '^') {
n4 = 27; // 26 is reserved for blank
} else
n4 = n->c - 'A';
if (n->t) {
n4 |= 32;
}
if (n->lastchild) {
n4 |= 64;
}
bytes[0] = n1; bytes[1] = n2; bytes[2] = n3; bytes[3] = n4;
out.write(bytes, 4);
}
}