Hi I'm working a program to unscramble a set of letters and output all the words that can be made from that set of letters, for example: If i inputed the letters "vlei", the program would output "live", "evil", and "vile".
So far I have looked through the internet about this quiiiite a bit and can't find anything on my specific questions relevant to my skill level at this point (level 2 noob).
So far I have gotten as far as making all the possible combinations from the the given letters. Excluding any that are less than 7 letters, which is a problem.
This is the code I have so far:
string letter;
char newWord[7];
int main()
{
cout << "Type letters here: ";
cin >> letter;
for(int i = 0 ; i < 7 ; i++)
{
for(int j = 0 ; j < 7 ; j++)
{
for(int k = 0 ; k < 7 ; k++)
{
for(int l = 0 ; l < 7 ; l++)
{
for(int m = 0 ; m < 7 ; m++)
{
for(int n = 0 ; n < 7 ; n++)
{
for(int o = 0 ; o < 7 ; o++)
{
sprintf(newWord, "%c%c%c%c%c%c%c", letter[i], letter[j], letter[k], letter[l], letter[m], letter[n], letter[o]);
}
}
}
}
}
}
}
return 0;
}
I was wondering if anyone has any experience with anything like this, and can offer and hints or advice.
Specifically what I'm having difficulty with is how to read in a .txt file to use as a dictionary to compare words to.
Also, I was having trouble using strcmp() which is what I was planning to use to compare the scrambled words to the dictionary. So if there are any other maybe simpler ways to compare the two strings, that would be greatly appreciated.
Thanks in advance.
Hi guys, so I've just finished my program and I hope it can help someone else. Thanks a lot for all your help.
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <array>
using namespace std;
//declaring variables
int i;
int scores[531811]; //array for scores of found words
string wordlist[531811]; //array for found matched words
string word[531811]; //array of strings for dictionary words about to be read it
string tester;//string for scrambled letters that will be read in
int scorefinder(string scrab) //SCORE FINDER FUNCTION
{
int score = 0;
int x = 0;
int j = 0;
while (scrab[j])
{
char ltr = toupper(scrab[j]); //converts to all caps
//assings values to each letter and adds it to itself
if(ltr == 'A' || ltr == 'E' || ltr == 'I' || ltr == 'L' || ltr == 'N' || ltr == 'O' || ltr == 'R' || ltr == 'S' || ltr == 'T' || ltr == 'U')
x += 1;
else if(ltr == 'D' || ltr == 'G')
x += 2;
else if(ltr == 'B' || ltr == 'C' || ltr == 'M' || ltr == 'P')
x += 3;
else if(ltr == 'F' || ltr == 'H' || ltr == 'V' || ltr == 'W' || ltr == 'Y')
x += 4;
else if(ltr == 'K')
x += 5;
else if(ltr == 'J' || ltr == 'X')
x += 8;
else if(ltr == 'Q' || ltr == 'Z')
x += 10;
++j;
}
score = x;
return score;
}
int main () {
//READS IN DICTIONARY
ifstream file("words.txt"); //reads in dictionary
if (!file.is_open()){ //checks if file is being NOT read correctly
cout << "BROEKN \n"; //prints error message if so
}
if(file.is_open()){ //checks if file IS being read correctly
for(int i = 0; i < 531811; i++){
file >> word[i]; //read in each word from the file and
} //assigns each to it's position in the words array
}
//END OF READ IN DICTIONARY
cout << "Enter scrambled letters: ";
cin >> tester; //reads in scrambled letters
sort(tester.begin(),tester.end()); //sorts scrambled letters for next_permutation
while (next_permutation(tester.begin(),tester.end())){ //while there are still permutations available
for(i=0;i<531811;i++){
if ( is_permutation (word[i].begin(),word[i].end(), tester.begin())){
wordlist[i] = word[i]; //assigns found word to foundword array
scores[i] = scorefinder(word[i]); //assigns found word score to foundscore array
}
}
}
//PRINTS OUT ONLY MATCHED WORDS AND SCORES
for(i=0;i<531811;i++){
if(scores[i]!=0){
cout << "Found word: " << wordlist[i] << " " << scores[i] << "\n";
}
}
}
Well, what you need is some sort of comparison. C++ doesn´t know, what a right word in english is. So you may need a wordlist. Then you can Brutforce(that´s what you´re doing at the moment) until you find a match.
For comparing your brutforced result, you may use a .txt with as many english words as you can find. Then you have to use a FileStream for iterating through every word and comparing it to your brutforce result.
After you sucessfully unscrambled a word, you should think about your solution again. As you can see, you are limited to a specific amount of chars which is not that nice.
This sounds like an interesting Task for a beginner ;)
Suppose you have found a word list in the form of plain text file on the Internet, you may load all the words into a vector for string first.
ifstream word_list_file("word_list.txt");
string buffer;
vector<string> all_words;
while (getline(word_list_file, buffer))
all_words.push_back(buffer);
Then we want to compare the input letters with the each entry of all_words. I suggest using std::is_permutation. It compares two sequence regardless the order. But it can have trouble when the two sequence has different length, so compare the length yourself first.
// Remember to #include <algorithm>
bool match(const string& letters, const string& each_word)
{
if (letters.size() != each_word.size())
return false;
return is_permutation(begin(letters), end(letters), begin(each_word));
}
Note that I have not tested my codes. But that's the idea.
An edit responsing the comment:
In short, just use std::string, not std::array. Or copy my match function directly, and invoke it. This will be easier for your case.
Details:
std::is_permutation can be used with any container and any element type. For example:
#include <string>
#include <array>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
//Example 1
string str1 = "abcde";
string str2 = "ecdba";
is_permutation(begin(str1), end(str1), begin(str2));
//Example 2
array<double, 4> array_double_1{ 4.1, 4.2, 4.3, 4.4 };
array<double, 4> array_double_2{ 4.2, 4.1, 4.4, 4.3 };
is_permutation(begin(array_double_1), end(array_double_1), begin(array_double_2));
//Example 3
list<char> list_char = { 'x', 'y', 'z' };
string str3 = "zxy";
is_permutation(begin(list_char), end(list_char), begin(str3));
// Exampl 4
short short_integers[4] = { 1, 2, 3, 4 };
vector<int> vector_int = { 3, 4, 2, 1 };
is_permutation(begin(list_char), end(list_char), begin(str3));
return 0;
}
Example 1 uses std::string as containers of chars, which is exactly how my match function work.
Example 2 uses two arrays of double of size 4.
Example 3 even uses two different kinds of containers, with the same element types. (Have you heard of `std::list'? Never mind, just focus on our problem first.)
Example 4 is even stranger. One container is old style raw array, another is a std::vector. There are also two element types, short and int, but they are both integer. (The exact difference between short and int is not relevant here.)
Yet, all four cases can use is_permutation. Very flexiable.
The flexibility is enabled by the following facts:
is_permutation is not exactly a function. It is a function template, which is a language feature to generate new functions according to the data type you pass to it.
The containers and is_permutation algorithm do not know each other. They communicate through a middleman called "iterator". The begin and end functions together give us a pair of iterators representing the "range" of elements.
It requires more studies to understand these facts. But the general idea is not hard. Also, these facts are also true for other algorithms in the Standard Library.
Try this :
# include <stdio.h>
/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char a[] = "vlei";
permute(a, 0, 3);
getchar();
return 0;
}
Related
This question already has answers here:
Testing stream.good() or !stream.eof() reads last line twice [duplicate]
(3 answers)
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 24 days ago.
I'm currently working on the "Name That Number" USACO training problem.
It takes a number as input and outputs any matching names found in a dictionary using touch tone telephone keymapping.
The full code consistently gets a bad_alloc thrown on the USACO grader. I've been coding in a replit and it runs fine each time. I've also tried commenting out different parts of the code and running it on the USACO grader but sometimes it runs fine and sometimes it gets a bad_alloc thrown. I think it has something to do with my 2d array of vectors but I'm not sure exactly what or how to fix it.
/*
ID:*****
TASK: namenum
LANG: C++14
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
//function that takes letter and returns associated number
int convert(int letter){ //implicit conversion
if (letter < 81){
letter = letter - 65;
}
else {
letter = letter - 66;
}
int modify = letter % 3;
letter = (letter - modify) / 3 + 2;
return letter;
}
int main() {
ifstream numin ("namenum.in");
ifstream dictin ("dict.txt");
ofstream fout ("namenum.out");
//2d array storing vectors that will store matching names for that index
vector<string> names[8][8]{};
//read names in from dict and store in table
while (dictin.good())
{
string name{};
dictin >> name;
if (name[0] != 'Z' && name[1] != 'Z'){
int i = convert(name[0]) - 2;
int j = convert(name[1]) - 2;
names[i][j].push_back(name);
}
}
//read in digits from input
string digits{};
numin >> digits;
//output matches
int index1 = static_cast<int>(digits[0]) - 50;
int index2 = static_cast<int>(digits[1]) - 50;
string output{};
//check for matches
if (index1 >= 0 && index1 <= 8 && index1 >= 0 && index1 <= 8){
for (int i = 0; i < names[index1][index2].size(); i++){
string matchdigits{};
for (int j = 0; j < names[index1][index2][i].length(); j++){
matchdigits += static_cast<char>(convert(names[index1][index2][i][j]) + 48);
}
if (matchdigits == digits){
output = names[index1][index2][i] + "\n";
}
}
}
if (output == ""){
output = "NONE\n";
}
fout << output;
return 0;
}
I am trying to solve such competitive programming problem:
Alex likes to laugh a lot. Laughter is a sequence of alternating letters "a" and "h". For example, "ahahaha", "hah" and "a" are laughter and "abacaba" and "hh" are not.
Alex speaks very quickly, so all his words merge into one big one. You need to find out how long he can laugh. You have a line - a recording of Alex's conversation. Determine the maximum length of laughter in this conversation.
Input file is called "laugh.in"
Output file is called "laugh.out"
Input data:
The first line of the input file contains a single integer N (1 < N ≤ 10^5) - the length of the string with Alex's conversation. The second line contains a string of small Latin letters of length N - recording Alex's conversation.
Output data:
Output one number - the longest laugh length in Alex's conversation
Here's some examples of how input/output data must look like.
Examples:
Input in laugh.in
5
ahaha
Output in laugh.out
5
Input in laugh.in
24
ahahrunawayahahsofasthah
Output in laugh.out
4
Input in laugh.in
10
ahahaahaha
Output in laugh.out
5
So, here is my code, that is supposed to solve given problem:
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
freopen("laugh.in", "r", stdin);
freopen("laugh.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, i;
cin >> n;
char *s = new char[n + 1];
getchar();
for (i = 0; i < n; i += 1)
{
s[i] = getchar();
}
s[n] = '\0';
int max_length = 0;
int length = 0;
for (i = 0; i < n; i += 1)
{
length += !length && (s[i] == 'a' || s[i] == 'h');
if ((s[i] == 'a' && s[i + 1] == 'h') ||
(s[i] == 'h' && s[i + 1] == 'a'))
{
length += 1;
}
else
{
max_length = max(max_length, length);
length = 0;
}
}
cout << max(max_length, length) << endl;
delete[] s;
return 0;
}
It only passes 13 tests with other 33 resulting in "Wrong answer" verdict.
So why my code is not working? Please, give counter examples to it or explain error.
Any help would be highly appreciated.
First of all, do not write everything in main (learn to avoid it ASAP).
Secondly, the task doesn't say anything about opening files.
Avoid the use of new delete in modern C++; it is a bad practice to use it.
Here is pattern you can start over:
size_t laugh_length(const std::string& s)
{
...
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
size_t l;
cin >> l;
std::string s;
s.reserve(l);
cin >> s;
cout << laugh_length(s) << '\n';
}
After an extra comment form OP I see another bit problem with OP code:
ios::sync_with_stdio(false);
and then use of:
getchar();
which is cstdio API which synchronization has been disabled.
https://wandbox.org/permlink/PJzjc1joKQgmpbwa
vs https://wandbox.org/permlink/aH3OypI94CpgNuxd
The below program is intended to make all characters in a string lowercase, remove all vowels, and then print a full stop before every letter. For example, an input of "umbrella" would become ".m.b.r.l.l". But when I input "tour", the 'u' is not removed.
char ChangeToLow(char letter) {
if(letter <= 'Z' && letter >= 'A')
return letter - ('A' - 'a');
return letter;
}
int main()
{
string name;
cin>>name;
for (int i = 0 ; i < name.length() ; i++)
{
name[i] = ChangeToLow(name[i]);
if (name[i] == 'y' || name[i] == 'a'|| name[i] == 'u'|| name[i] == 'i'|| name[i] == 'e'|| name[i] == 'o')
{
name.erase(i,1);
}
}
for (int i = 0 ; i < name.length() ; i++)
{
cout<<'.'<<name[i];
}
}
I expect the output ".t.r" but instead it prints ".t.u.r".
Thanks in advance.
When you erase a character from the string, the remaining contents move over to fill the space. Their indexes adjust accordingly. With your tour example, it'll look something like the following:
Your loop counter, i, was incremented to 2 after you deleted the 'o' from tour, and name[i] is now 'r'. One option to avoid this behavior is to decrement i when you delete a vowel.
I have some suggestion for you. Firstly you shouldn't put using namespace std; in your code. It just adds confusion and is considered a bad practice. I think it would be also a good thing, if you would consider to learn the STL, if it is really your aim to learn C++ in depths. As for the error I think that the already posted answer shows your wrong assumptions.
#include <iostream>
#include <cstdlib>
#include <locale>
#include <set>
#include <algorithm>
int main()
{
std::string name;
std::cin>>name;
std::set<char> vowels={'a','u','i','e','o'};
std::transform(name.begin(), name.end(), name.begin(), [](auto v){ return std::tolower(v, std::locale());});
auto iter=std::remove_if(name.begin(), name.end(), [&vowels](auto v){ return vowels.find(v)!=vowels.end();});
name.erase(iter,name.end());
for (int i = 0 ; i < name.length() ; i++)
{
std::cout<<'.'<<name[i];
}
return EXIT_SUCCESS;
}
I'm trying to figure out if there is a way to compare if a content of a string is the start of another string. For example, I want to know the number of strings that start with the string "c", in an array whose content's is [cowboy, air, cow, cat]. Using the compare function from the string library works fine. The issue is when instead of trying with "c", I try with "b" I get the same number of answers. I don't know the reason why, Does anybody have a suggestion on how to fix the problem? Here are the two versions that I have.
#include <iostream>
#include <string>
using namespace std;
int main() {
// insert code here...
string A[4] = {"cowboy", "air", "c", "count"};
string b = "c";
int count = 0;
for(int i = 0; i < 4; i++)
{
if(b.compare(A[i]) == 0 || b.compare(A[i]) == -1)
count++;
}
cout << count << endl;
}
The output for this part is 3, which is right
#include <iostream>
#include <string>
using namespace std;
int main() {
// insert code here...
string A[4] = {"cowboy", "air", "c", "count"};
string b = "b";
int count = 0;
for(int i = 0; i < 4; i++)
{
if(b.compare(A[i]) == 0 || b.compare(A[i]) == -1)
count++;
}
cout << count << endl;
}
The output for this part is also 3, which is wrong.
Any help would be really appreciated!
There is an overload of the compare function which accepts position and a length, and compares only a part of the string to the other string. If you pass 0 for the position, and the size of the string you are searching for as the length, it will only compare that many characters at the start of the string, instead of comparing the whole thing.
if(A[i].compare(0, b.size(), b) == 0)
count++;
By the way, the only reason your first test appeared to be working, was that you were basically checking if "c" is lexicographically less than or equal to your target strings. And since that is the case for "cowboy", "c" and "count", but not "air", your result was 3. But if you added a string like, "direwolf", which comes lexicographically after "c", but does not start with "c", you would find that your results were not what you are expecting.
You can try using the find function:
string A[4] = {"cowboy", "air", "c", "count"};
string b = "b";
int count = 0;
for(int i = 0; i < 4; i++)
{
auto found = A[i].find(b);
if(found != string::npos && found == 0)
count++;
}
cout << count << endl;
What I do here is find b in A[i], if I get npos which means it wasn't found if I do find it, I check if its at the start by checking found == 0
Similarly to simplify if I only want to check for just a character match at the start I could simply A[i] == b[0]
Live Demo
Replace your if condition with the following. This compares the string b with A[i]'s 1st character.
if(b.compare(0, A[i].length(), A[i], 0, 1) == 0)
In your for loop when you pass in b = "c" the first conditions satisfies b.compare(A[i]) == 0 and for b="a" second condition satisfies. So in both cases you see 3.
You can do it easily by changing string b to character b and then checking if the first letter of each string in the array is equal to b or not and incrementing the count when they are equal.
The problem:
A function which gets degrees and factors as inputs and returns a equation as output.
The issue:
I did not know how to read an array of numbers in form of a string in c++ back then in 2016 when I was a super junior. I also did not know how to search good enough!
Update:
I answered my question and you can test this in this link: http://cpp.sh/42dwz
Answer details:
Main part of the code will be like this:
int main()
{
Poly mypoly("2 -4 3", "1 5 1");
return 0;
}
Inputs are 2 -4 3 and 1 5 1.
Output should be (2X) + (-4X5) + (3X)
Class Poly has a built-in feature to print the result
To make it easier we should convert degrees and factors from a single string into an array of strings.
This means that a string like 2 -4 3 changes into [2, -4, 3] which makes it easy to iterate over items and create equation sentences
This action is called splitting a string into an array by a delimiter which I found here for c++ https://stackoverflow.com/a/16030594/5864034
Rest of the code is just looping over the array of degrees and factors to create sentences(which is pretty easy just check the answer link http://cpp.sh/42dwz)
The code:
// Example program
#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
using namespace std;
template <size_t N>
void splitString(string (&arr)[N], string str)
{
int n = 0;
istringstream iss(str);
for (auto it = istream_iterator<string>(iss); it != istream_iterator<string>() && n < N; ++it, ++n)
arr[n] = *it;
}
class Poly {
public:
string degree[10];
string factor[10];
Poly(string input_degree, string input_factor) {
splitString(degree, input_degree);
splitString(factor, input_factor);
for (int i = 0; i < 10; i++){
int this_degree = stoi(degree[i]);
int this_factor = stoi(factor[i]);
string this_sentence = "";
if(this_degree != 1 && this_degree != 0 ){
this_sentence = this_sentence + degree[i];
if(this_factor != 0){
if(this_factor != 1){
this_sentence = this_sentence + "X" + factor[i];
}else{
this_sentence = this_sentence + "X";
}
}
}
if(this_sentence != ""){
cout << "(" << this_sentence << ")";
}
if(stoi(degree[i+1]) != 0 && stoi(degree[i+1]) != 1){
cout << " + ";
}
}
}
};
int main()
{
Poly mypoly("2 -4 3", "1 5 1");
return 0;
}
The process of reading a string and extracting information from it into some sort of structure is called parsing. There are many ways to do this, and which way is appropriate depends on exactly what you want to do, how quickly it needs to run, how much memory you've got available and various other things.
You can write a simple loop which steps over each character and decides what to do based on some variables that store current state - so you might have a flag that says you're in the middle of a number, you see another digit so you add that digit to another variable which is collecting the digits of the current number. When the current number completes (perhaps you find a character which is a space), you can take what's in the accumulator variable and parse that into a number using the standard library.
Or you can make use of standard library features more fully. For your example, you'll find that std::istringstream can do what you want, out of the box, just by telling it to extract ints from it repeatedly until the end of the stream. I'd suggest searching for a good C++ input stream tutorial - anything that applies to reading from standard input using std::cin will be relevant, as like std::istringstream, cin is an input stream and so has the same interface.
Or you could use a full-blown parsing library such as boost::spirit - total overkill for your scenario, but if you ever need to do something like parsing a structured configuration file or an entire programming language, that kind of tool is very useful.
So for the community rules and to make it clear i want to answer my question.
#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
using namespace std;
template <size_t N>
void splitString(string (&arr)[N], string str)
{
int n = 0;
istringstream iss(str);
for (auto it = istream_iterator<string>(iss); it != istream_iterator<string>() && n < N; ++it, ++n)
arr[n] = *it;
}
class Poly {
public:
string degree[10];
string factor[10];
Poly(string input_degree, string input_factor) {
splitString(degree, input_degree);
splitString(factor, input_factor);
for (int i = 0; i < 10; i++){
int this_degree = stoi(degree[i]);
int this_factor = stoi(factor[i]);
string this_sentence = "";
if(this_degree != 1 && this_degree != 0 ){
this_sentence = this_sentence + degree[i];
if(this_factor != 0){
if(this_factor != 1){
this_sentence = this_sentence + "X" + factor[i];
}else{
this_sentence = this_sentence + "X";
}
}
}
if(this_sentence != ""){
cout << "(" << this_sentence << ")";
}
if(stoi(degree[i+1]) != 0 && stoi(degree[i+1]) != 1){
cout << " + ";
}
}
}
};
int main()
{
Poly mypoly("2 1 -4", "1 3 5");
return 0;
}