0

So far my c++ program looks like this:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int i;
    int maxLet;
    const int NumWords = 26;
    const int NumPhrase = 8;
    string ele;
    string n[NumWords] = {
        "crypt",  "by",     "my",     "cysts",  "glyph", "psych", "shyly",
        "slyly",  "try",    "sylph",  "tryst",  "gypsy", "ply",   "pry",
        "shy",    "sly",    "spy",    "thy",    "cry",   "sty",   "glyphs",
        "sylphs", "trysts", "crypts", "psychs", "sprly"};
    vector<string> words(n, n + NumWords);
    vector<string> phrase(n, n + NumPhrase);
    for (i = 0; i < words.size(); i++) {
        cout << words.at(i) << endl;
        cout << words[i] << endl;
    }

    char aaaaa;
    cin >> aaaaa;
    return 0;
}

I need to create a phrase that resembles [YYY] [YYYYY] [YYYBC] [GHLLLM] [PPPRR] [RS] [SS] [SSTTT] Where The letters are all scrambled and the brackets denote the length of the word. Essentially I need to create a phrase of words with those specific word lengths, and those specific number of letters total there are, 11 y's 1 b 1 c 1 g 1 h 3 L's 1 m 3 p's 3 r's 5 s's 3t's I have been pulling my hair out trying to figure out how to do it. Your input would be greatly appreciated.

NetVipeC
  • 4,402
  • 1
  • 17
  • 19
Joe
  • 9
  • 2
  • 1
    your program is really too far from the solution, it does not even contains valid parsing of input string ( cin ) that would be string with '['']{, and there is not even the slight start of an algorithm to resolve the problem... if the problem is too big, split in in part, first try to only find all words of a given size, to be able to fill brakets, and maintain a string of unused characters. – philippe lhardy Aug 02 '14 at 19:20
  • 1
    A couple of hints, eliminate words that contain letter no used in the phrase, or the size not in the phrase, try to begin with the letter less used (ex: `b, c, g, h, m` the words that contain that letter). For example word `by` is the only one with `b` in the list of words and has size 2, it could be used in the place occupied by `RS` or `SS`. With recursion to backtrack if a dead end is reached, it could be completed. Try to put a word with the previous checks, update the used letter and retry, if a dead end is reach, backtrack and try with other word. – NetVipeC Aug 02 '14 at 20:03

2 Answers2

1

Since all your word templates(the set of [...]s) are distinct, you simply need to count possible matches for each such element and multiply these numbers. So, lets write such a function first:

bool isMatch(string templ, string word)
{
sort(templ.begin(), templ.end());
sort(word.begin(), word.end());
return templ==word;
}

long long countMatches(string templ, vector<string> const& dict)
{
long long ret=0;
for(int i = 0; i < dict.size(); i++)
  ret += isMatch(templ, dict[i]);
return ret;
}

long long finalAnswer(vector<string> const& templs, vector<string> const& dict)
{
 long long ans=1;
 for(int i=0; i<templs.size(); i++)
   ans*=countMatches(templs[i], dict);
 return ans;
}
Pradhan
  • 16,391
  • 3
  • 44
  • 59
  • Given the question i thought that letter match are for the full sentence, not for each word in brakets ( but i don't have the exact text of the full exam that Joe want to us to pass at his place ). because ... – philippe lhardy Aug 02 '14 at 19:29
  • @philippelhardy Questions like this make me glad I am clairvoyant :) – Pradhan Aug 02 '14 at 19:40
  • If you calculate your clairvoyance degree from the fact you got a +1, be aware it comes from me and not from Joe ... who does not seems to follow so well his first post ever. – philippe lhardy Aug 02 '14 at 20:43
  • I'm still a little confused on what some of your functions are doing. what is the vector const& dict you are referring to? Is that the vector I have set up already or is it a new one? – Joe Aug 02 '14 at 21:26
0

Because the problem statement is not available, i am assuming that:

  1. The words of the phrases in total have to use the total chars inside the [] but not each word the exact char inside the [].
  2. The phrase have to use exactly all the char inside the []
  3. You can use a word more that one time (can be easily updated to use words only once)
  4. The words to use are enter in lower case.
  5. The char to use in the phrase are enter in upper case.

Code (Tested in GCC 4.9.0 with C++11):

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

bool can_use_word(std::vector<long>& chars_in_phrase, const std::string& word) {
    unsigned int idx = 0;
    bool valid = true;
    // Verifing that the word could be used, that no char is used more that the
    // phrase indicate
    // Updating the char use count in place.
    for (; idx < word.size(); idx++) {
        if (chars_in_phrase[word[idx] - 'a'] == 0) {
            valid = false;
            break;
        }

        chars_in_phrase[word[idx] - 'a']--;
    }

    if (!valid) {
        // If invalid revert the char use count as before.
        for (unsigned int idx_revert = 0; idx_revert < idx; idx_revert++) {
            chars_in_phrase[word[idx_revert] - 'a']++;
        }
        return false;
    }
    return true;
}

bool solve_phrase(std::vector<long>& chars_in_phrase,
                  std::vector<long>& phrase_word_length,
                  const std::vector<std::string>& words_to_use,
                  std::vector<std::string>& phrase,
                  unsigned int phrase_word_idx = 0) {
    if (phrase_word_idx == phrase_word_length.size()) {
        // If we reach the last word length of the phrase and no char is left
        // for use, we found our solution.
        bool valid = true;
        for (auto cu : chars_in_phrase) {
            if (cu != 0) {
                valid = false;
                break;
            }
        }
        return valid;
    }

    // Find the first word with the length needed.
    auto it = std::find_if(
        words_to_use.begin(), words_to_use.end(),
        [&phrase_word_length, phrase_word_idx](const std::string& str) {
            return str.size() == phrase_word_length[phrase_word_idx];
        });

    // If not have the length needed (it's not possible in the actual algorithm,
    // because we allow using
    // the same word multiple times, if its only used once, could be necessary).
    if (it == words_to_use.end() ||
        it->size() != phrase_word_length[phrase_word_idx])
        return false;

    // Iterate throught the words with the same target length.
    while (it != words_to_use.end() &&
           it->size() == phrase_word_length[phrase_word_idx]) {
        if (can_use_word(chars_in_phrase, *it)) {
            phrase.push_back(*it);
            // Continue searching the next word in the phrase
            if (solve_phrase(chars_in_phrase, phrase_word_length, words_to_use,
                             phrase, phrase_word_idx + 1))
                return true;
            // If it reach dead end, revert the state of the used chars and
            // continue with the next possible word.
            phrase.pop_back();
            for (unsigned int idx = 0; idx < it->size(); idx++) {
                chars_in_phrase[(*it)[idx] - 'a']++;
            }
        }
        it++;
    }

    return false;
}

int main() {
    std::vector<std::string> words_to_use{
        "crypt",  "by",     "my",     "cysts",  "glyph", "psych", "shyly",
        "slyly",  "try",    "sylph",  "tryst",  "gypsy", "ply",   "pry",
        "shy",    "sly",    "spy",    "thy",    "cry",   "sty",   "glyphs",
        "sylphs", "trysts", "crypts", "psychs", "sprly"};

    std::string phrase =
        "[YYY] [YYYYY] [YYYBC] [GHLLLM] [PPPRR] [RS] [SS] [SSTTT]";
    std::vector<long> chars_in_phrase(26, 0);
    std::vector<long> phrase_word_length;

    // Initializing the char used in the phrase and the word length of the
    // phrase
    unsigned int begin_idx = 0;
    for (unsigned int idx = 0; idx < phrase.size(); idx++) {
        char c = phrase[idx];
        if (c == '[') {
            begin_idx = idx;
        } else if (c == ']') {
            phrase_word_length.push_back(idx - begin_idx - 1);
        } else if (c != ' ') {
            chars_in_phrase[c - 'A']++;
        }
    }

    // Sorting the words by size.
    std::sort(words_to_use.begin(), words_to_use.end(),
              [](const std::string& left, const std::string& right) {
        if (left.size() == right.size())
            return left < right;
        return left.size() < right.size();
    });

    std::vector<std::string> phrase_solved;
    solve_phrase(chars_in_phrase, phrase_word_length, words_to_use,
                 phrase_solved);

    for (auto p : phrase_solved) {
        std::cout << p << " ";
    }
    std::cout << std::endl;

    return 0;
}

Output obtained: pry crypt gypsy trysts shyly by my slyly

NetVipeC
  • 4,402
  • 1
  • 17
  • 19
  • This is literally perfect. I was up for some 30 hourts trying to do this. are you a programmer? – Joe Aug 02 '14 at 21:38
  • Yes, I'm a programmer, it's a really strange question, most people checking this tags would be programmers, by hobby, by profession or both. – NetVipeC Aug 02 '14 at 22:04
  • Well I had to first cut down a text file of over 10,000 words and random characters to those 26 words. But anyways I really appreciate your assistance and I wish I could up vote you but apparently you need at least a 15 rep to do it. – Joe Aug 02 '14 at 22:11
  • You could check the answer, i assume? I'm glad that this help you. – NetVipeC Aug 02 '14 at 22:16