diff options
Diffstat (limited to 'alphabetparameters.cpp')
-rw-r--r-- | alphabetparameters.cpp | 349 |
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; +} + |