summaryrefslogtreecommitdiff
path: root/alphabetparameters.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alphabetparameters.cpp')
-rw-r--r--alphabetparameters.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/alphabetparameters.cpp b/alphabetparameters.cpp
new file mode 100644
index 0000000..9261282
--- /dev/null
+++ b/alphabetparameters.cpp
@@ -0,0 +1,349 @@
+/*
+ * 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 <algorithm>
+#include <cassert>
+
+#include "alphabetparameters.h"
+#include "datamanager.h"
+
+using namespace Quackle;
+
+LetterString String::left(const LetterString &letterString, int number)
+{
+ LetterString ret;
+
+ int i = 0;
+ LetterString::const_iterator myEnd(letterString.end());
+ for (LetterString::const_iterator it = letterString.begin(); i < number && it != myEnd; ++it, ++i)
+ ret += *it;
+
+ return ret;
+}
+
+LetterString String::alphabetize(const LetterString &letterString)
+{
+ LetterString ret = letterString;
+ sort(ret.begin(), ret.end());
+ return ret;
+}
+
+LetterString String::clearBlankness(const LetterString &letterString)
+{
+ LetterString ret;
+
+ LetterString::const_iterator myEnd(letterString.end());
+ for (LetterString::const_iterator it = letterString.begin(); it != myEnd; ++it)
+ ret += QUACKLE_ALPHABET_PARAMETERS->clearBlankness(*it);
+
+ return ret;
+}
+
+LetterString String::setBlankness(const LetterString &letterString)
+{
+ LetterString ret;
+
+ LetterString::const_iterator myEnd(letterString.end());
+ for (LetterString::const_iterator it = letterString.begin(); it != myEnd; ++it)
+ ret += QUACKLE_ALPHABET_PARAMETERS->setBlankness(*it);
+
+ return ret;
+}
+
+LetterString String::usedTiles(const LetterString &letterString)
+{
+ LetterString used;
+
+ const LetterString::const_iterator end(letterString.end());
+ for (LetterString::const_iterator it = letterString.begin(); it != end; ++it)
+ {
+ if (*it == QUACKLE_BLANK_MARK || QUACKLE_ALPHABET_PARAMETERS->isBlankLetter(*it))
+ used += QUACKLE_BLANK_MARK;
+ else if (QUACKLE_ALPHABET_PARAMETERS->isPlainLetter(*it))
+ used += *it;
+ }
+
+ return used;
+}
+
+void String::counts(const LetterString &letterString, char *countsArray)
+{
+ for (int j = 0; j < QUACKLE_FIRST_LETTER + QUACKLE_MAXIMUM_ALPHABET_SIZE; j++)
+ countsArray[j] = 0;
+
+ const LetterString::const_iterator end(letterString.end());
+ for (LetterString::const_iterator it = letterString.begin(); it != end; ++it)
+ countsArray[*it]++;
+}
+
+void String::counts(const LongLetterString &letterString, char *countsArray)
+{
+ for (int j = 0; j < QUACKLE_FIRST_LETTER + QUACKLE_MAXIMUM_ALPHABET_SIZE; j++)
+ countsArray[j] = 0;
+
+ const LongLetterString::const_iterator end(letterString.end());
+ for (LongLetterString::const_iterator it = letterString.begin(); it != end; ++it)
+ countsArray[*it]++;
+}
+
+////////////
+
+AlphabetParameters::AlphabetParameters()
+ : m_length(0)
+{
+ setAlphabet(emptyAlphabet());
+}
+
+void AlphabetParameters::setAlphabet(const Alphabet &alphabet)
+{
+ m_alphabet = alphabet;
+ updateLength();
+
+ const Alphabet::const_iterator alphabetEnd(m_alphabet.end());
+ Alphabet::const_iterator alphabetIt;
+ for (alphabetIt = m_alphabet.begin(); alphabetIt != alphabetEnd; ++alphabetIt) {
+ assert(m_letterLookup.find(alphabetIt->text()) == m_letterLookup.end());
+ m_letterLookup[alphabetIt->text()] = alphabetIt - m_alphabet.begin();
+ }
+
+}
+
+void AlphabetParameters::setLetterParameter(Letter letter, const LetterParameter &letterParameter)
+{
+ assert(m_letterLookup.find(letterParameter.text()) == m_letterLookup.end());
+ if (letter >= (int) m_alphabet.size())
+ {
+ m_alphabet.resize(letter + 1);
+ updateLength();
+ }
+
+ m_alphabet[letter] = letterParameter;
+ m_letterLookup[letterParameter.text()] = letter;
+}
+
+void AlphabetParameters::updateLength()
+{
+ m_length = m_alphabet.size() - QUACKLE_FIRST_LETTER;
+}
+
+Alphabet AlphabetParameters::emptyAlphabet()
+{
+ Alphabet ret(QUACKLE_FIRST_LETTER);
+ ret[QUACKLE_NULL_MARK] = LetterParameter(QUACKLE_NULL_MARK, MARK_UV(" "), MARK_UV(""));
+ ret[QUACKLE_BLANK_MARK] = LetterParameter(QUACKLE_BLANK_MARK, MARK_UV("?"), MARK_UV(""));
+ ret[QUACKLE_PLAYED_THRU_MARK] = LetterParameter(QUACKLE_PLAYED_THRU_MARK, MARK_UV("."), MARK_UV(""));
+ ret[QUACKLE_PLAYTHRU_START_MARK] = LetterParameter(QUACKLE_PLAYTHRU_START_MARK, MARK_UV("("), MARK_UV(""));
+ ret[QUACKLE_PLAYTHRU_END_MARK] = LetterParameter(QUACKLE_PLAYTHRU_END_MARK, MARK_UV(")"), MARK_UV(""));
+ return ret;
+}
+
+void AlphabetParameters::setCount(Letter letter, int count)
+{
+ m_alphabet[letter].setCount(count);
+}
+
+void AlphabetParameters::setScore(Letter letter, int score)
+{
+ m_alphabet[letter].setScore(score);
+}
+
+LetterString AlphabetParameters::clearBlankness(const LetterString &letterString) const
+{
+ LetterString ret;
+
+ const LetterString::const_iterator end(letterString.end());
+ for (LetterString::const_iterator it = letterString.begin(); it != end; ++it)
+ ret += clearBlankness(*it);
+
+ return ret;
+}
+
+UVString AlphabetParameters::userVisible(const LetterString &letterString) const
+{
+ UVString ret;
+
+ const LetterString::const_iterator end(letterString.end());
+ for (LetterString::const_iterator it = letterString.begin(); it != end; ++it)
+ ret += userVisible(*it);
+
+ return ret;
+}
+
+UVString AlphabetParameters::userVisible(Letter letter) const
+{
+ if (isBlankLetter(letter))
+ return letterParameter(letter - QUACKLE_BLANK_OFFSET).blankText();
+ else
+ return letterParameter(letter).text();
+}
+
+LetterString AlphabetParameters::encode(const UVString &word, UVString *leftover) const
+{
+ LetterString ret;
+
+ UVString leftoverQuery;
+ const Alphabet::const_iterator alphabetEnd(m_alphabet.end());
+ LetterLookupMap::const_iterator lookupEnd = m_letterLookup.end();
+
+ const UVString::const_iterator end(word.end());
+ for (UVString::const_iterator it = word.begin(); it != end; ++it)
+ {
+ UVString query(leftoverQuery);
+ query += *it;
+
+ bool blank = false;
+
+ Alphabet::const_iterator alphabetIt;
+ LetterLookupMap::const_iterator lookupIt = m_letterLookup.find(query);
+
+ if (lookupIt == lookupEnd)
+ {
+ for (alphabetIt = m_alphabet.begin(); alphabetIt != alphabetEnd; ++alphabetIt)
+ if ((*alphabetIt).blankText() == query)
+ break;
+
+ if (alphabetIt == alphabetEnd)
+ {
+ leftoverQuery = query;
+ continue;
+ }
+
+ blank = true;
+ ret += blank? setBlankness((*alphabetIt).letter()) : (*alphabetIt).letter();
+ } else {
+ ret += blank? setBlankness(m_alphabet[lookupIt->second].letter()) : m_alphabet[lookupIt->second].letter();
+ }
+ leftoverQuery.clear();
+ }
+
+ //UVcout << "encoded " << word << " to " << ret << endl;
+
+ if (leftover)
+ *leftover = leftoverQuery;
+
+ return ret;
+}
+
+string AlphabetParameters::findAlphabetFile(const string &alphabet)
+{
+ return DataManager::self()->findDataFile("alphabets", alphabet);
+}
+
+////////
+
+EnglishAlphabetParameters::EnglishAlphabetParameters()
+{
+ m_alphabetName = "default";
+
+ const int englishTileScores[26] =
+ {
+ 1, // A
+ 3, // B
+ 3, // C
+ 2, // D
+ 1, // E
+ 4, // F
+ 2, // G
+ 4, // H
+ 1, // I
+ 8, // J
+ 5, // K
+ 1, // L
+ 3, // M
+ 1, // N
+ 1, // O
+ 3, // P
+ 10,// Q
+ 1, // R
+ 1, // S
+ 1, // T
+ 1, // U
+ 4, // V
+ 4, // W
+ 8, // X
+ 4, // Y
+ 10,// Z
+ };
+
+ const int englishTileCounts[27] =
+ {
+ 9, // A
+ 2, // B
+ 2, // C
+ 4, // D
+ 12, // E
+ 2, // F
+ 3, // G
+ 2, // H
+ 9, // I
+ 1, // J
+ 1, // K
+ 4, // L
+ 2, // M
+ 6, // N
+ 8, // O
+ 2, // P
+ 1, // Q
+ 6, // R
+ 4, // S
+ 6, // T
+ 4, // U
+ 2, // V
+ 2, // W
+ 1, // X
+ 2, // Y
+ 1, // Z
+ 2, // ?
+ };
+
+ Letter letter = QUACKLE_FIRST_LETTER;
+ for (UVChar charIndex = MARK_UV('A'); charIndex <= MARK_UV('Z'); ++charIndex, ++letter)
+ {
+ UVString letterString;
+ UVString lowerLetterString;
+ letterString += charIndex;
+ lowerLetterString += towlower(charIndex);
+
+ const bool isVowel = (charIndex == MARK_UV('A')) || (charIndex == MARK_UV('E')) || (charIndex == MARK_UV('I')) || (charIndex == MARK_UV('O')) || (charIndex == MARK_UV('U'));
+
+ const int score = englishTileScores[letter - QUACKLE_FIRST_LETTER];
+ const int count = englishTileCounts[letter - QUACKLE_FIRST_LETTER];
+
+ setLetterParameter(letter, LetterParameter(letter, letterString, lowerLetterString, score, count, isVowel));
+ }
+
+ setCount(QUACKLE_BLANK_MARK, englishTileCounts[26]);
+}
+
+UVOStream &operator<<(UVOStream& o, const Quackle::LetterParameter &letterParameter)
+{
+ o << letterParameter.letter() << " [" << letterParameter.text() << ", " << letterParameter.blankText() << "]";
+ return o;
+}
+
+UVOStream &operator<<(UVOStream& o, const Quackle::Alphabet &alphabet)
+{
+ o << "Alphabet (size " << alphabet.size() << "): ";
+ Alphabet::const_iterator end(alphabet.end());
+ for (Alphabet::const_iterator it = alphabet.begin(); it != end; ++it)
+ o << (*it) << " ";
+ return o;
+}
+