Non-repeating random numbers - c++

I'm working on a synonym puzzle, it gives you a word and wants you to find the synonym of it given the lenght of the word. Everything works fine, but it happens on an ordered sequence; words do not appear randomly. I need knumber of non-repeating random numbers for that. Here's my code:
#include<iostream>
#include<string>
#include<cstdlib>
#include<ctime>
using namespace std;
int main()
{
const int k=4;
string word[k]={"furious","tiny","untrue", "humorous", "harm"};
string nword[k]={"angry","small","false", "funny", "damage"};
string j;
int point, p = 0;
int ctr=0;
srand(time(NULL));
int randNum = (rand() % k) + 0;
for(int i=0; i<k; i++)
{
cout << nword[i] << "\n";
cout << "The length of the word: " << word[i].length() << "\n";
cin>>j;
ctr++;
if(j==word[i])
{
cout<<"Correct! Score: " << i+1 << " point." << "\n\n";
}
else
{
cout<<"Wrong"<<endl;
}
}
return 0;
}
As you can see, the variable randNum holds the value of the random number from 0 to k, (k is 4, combined with 0, I got 5 words). In for loop, when I set the nword and word like nword[randNum], and word[randNum], the result leaves a lot to be desired. First, I think there's no sync for the two (nword and word). It will apply different random numbers for the two (I might be wrong) and the second, it will be repetitive. As seen, the execution is score-based and completable, so I need non repeating questions until it reaches to k.

You could shuffle your word arrays by using the Durstenfeld shuffle:
for(int i=k-1; i>0; i--)
{
int j = rand() % (i+1)
string temp = word[i];
word[i] = word[j];
word[j] = temp;
temp = nword[i];
nword[i] = nword[j];
nword[j] = temp;
}
As pointed out by WhozCraig, an alternative option (arguably better, as it doesn't require permuting multiple arrays), is to create an array with indices 0..(k-1) and shuffle this array instead. This array would then contain a set of randomised indices which could be used to iterate over your word arrays.
#include <iostream>
#include <algorithm>
#include <string>
#include <random>
#include <numeric>
using namespace std;
int main()
{
static const size_t k=5;
string word[k]={"furious","tiny","untrue", "humorous", "harm"};
string nword[k]={"angry","small","false", "funny", "damage"};
int ctr=0;
// build prng
std::random_device rd;
std::mt19937 rng(rd());
// build index sequence, then shuffle
size_t idx[k];
std::iota(std::begin(idx), std::end(idx), 0);
std::shuffle(std::begin(idx), std::end(idx), rng);
for(auto i : idx)
{
std::string s;
cout << nword[i] << "\n";
cout << "The length of the word: " << word[i].length() << "\n";
if (!(cin>>s))
break;
if(s==word[i])
{
cout<<"Correct! ";
++ctr;
}
else
{
cout<<"Wrong. ";
}
std::cout << "Score: " << ctr << " point(s).\n\n";
}
return 0;
}

Related

Finding and printing common letters in different strings

I need to find and print common characters in different strings. My code does not work as it should, it checks for same letters at the same index but thats not what I want. I couldn't find better solution for now. Thank you for help :)
#include <iostream>
#include <string>
using namespace std;
int main() {
string niz1, niz2, niz3 = "";
cout << "string 1: ";
getline(cin, niz1);
cout << "string 2: ";
getline(cin, niz2);
for (int i = 0; i < niz1.length() - 1; i++) {
for (int j = 0; j < niz2.length() - 1; j++) {
if (niz1[i] == niz2[j])
niz3 += niz1[i];
}
}
cout << "Same letters are: " << niz3 << endl;
return 0;
}
Below is corrected working code. Basically the only correction that was needed to do is to make both loops have upper bound of niz.length() instead of niz.length() - 1.
Variant 1:
Try it online!
#include <string>
#include <iostream>
using namespace std;
int main() {
string niz1, niz2, niz3 = "";
cout << "string 1: ";
getline(cin, niz1);
cout << "string 2: ";
getline(cin, niz2);
for (int i = 0; i < niz1.length(); i++) {
for (int j = 0; j < niz2.length(); j++) {
if (niz1[i] == niz2[j])
niz3 += niz1[i];
}
}
cout << "Same letters are: " << niz3 << endl;
return 0;
}
Input:
string 1: adbc
string 2: cde
Output:
Same letters are: dc
Also you may want to sort letters and make them unique, then you need to use std::set too like in code below:
Variant 2:
Try it online!
#include <string>
#include <iostream>
#include <set>
using namespace std;
int main() {
string niz1, niz2, niz3 = "";
cout << "string 1: ";
getline(cin, niz1);
cout << "string 2: ";
getline(cin, niz2);
for (int i = 0; i < niz1.length(); i++) {
for (int j = 0; j < niz2.length(); j++) {
if (niz1[i] == niz2[j])
niz3 += niz1[i];
}
}
set<char> unique(niz3.begin(), niz3.end());
niz3.assign(unique.begin(), unique.end());
cout << "Same letters are: " << niz3 << endl;
return 0;
}
Input:
string 1: adbcda
string 2: cdecd
Output:
Same letters are: cd
Also you may use just sets plus set_intersection standard function. This will solve your task in less time, in O(N*log(N)) time instead of your O(N^2) time.
Variant 3:
Try it online!
#include <string>
#include <iostream>
#include <set>
#include <algorithm>
#include <iterator>
using namespace std;
int main() {
string niz1, niz2, niz3 = "";
cout << "string 1: ";
getline(cin, niz1);
cout << "string 2: ";
getline(cin, niz2);
set<char> s1(niz1.begin(), niz1.end()), s2(niz2.begin(), niz2.end());
set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), back_inserter(niz3));
cout << "Same letters are: " << niz3 << endl;
return 0;
}
Input:
string 1: adbcda
string 2: cdecd
Output:
Same letters are: cd
Instead of set it is also possible to use unordered_set, it will give even more faster algorithm especially for long strings, algorithm will have running time O(N) compared to O(N * log(N)) for set solution. The only drawback is that unlike for set solution output of unordered_set solution is unsorted (but unique) (unordered sets don't sort their data).
Variant 4:
Try it online!
#include <string>
#include <iostream>
#include <unordered_set>
#include <algorithm>
#include <iterator>
using namespace std;
int main() {
string niz1, niz2, niz3;
cout << "string 1: ";
getline(cin, niz1);
cout << "string 2: ";
getline(cin, niz2);
unordered_set<char> s1(niz1.begin(), niz1.end()), s2;
for (size_t i = 0; i < niz2.length(); ++i)
if (s1.count(niz2[i]))
s2.insert(niz2[i]);
niz3.assign(s2.begin(), s2.end());
cout << "Same letters are: " << niz3 << endl;
return 0;
}
Input:
string 1: adbcda
string 2: cdecd
Output:
Same letters are: dc
Also one more way is to use just plain for loops like you did, without sets, but do extra block of loops in order to remove non-unique letters, like in code below. The only drawbacks of this loops method compared to sets method is that loops method runs slower and produces non-sorted output string.
Variant 5:
Try it online!
#include <string>
#include <iostream>
using namespace std;
int main() {
string niz1, niz2, niz3, niz4;
cout << "string 1: ";
getline(cin, niz1);
cout << "string 2: ";
getline(cin, niz2);
for (int i = 0; i < niz1.length(); ++i)
for (int j = 0; j < niz2.length(); ++j)
if (niz1[i] == niz2[j])
niz3 += niz1[i];
for (int i = 0; i < niz3.length(); ++i) {
bool exists = false;
for (int j = 0; j < niz4.length(); ++j)
if (niz4[j] == niz3[i]) {
exists = true;
break;
}
if (!exists)
niz4 += niz3[i];
}
cout << "Same letters are: " << niz4 << endl;
return 0;
}
Input:
string 1: adbcda
string 2: cdecd
Output:
Same letters are: dc
This is sort of an answer in itself, and sort of an extended comment on #Arty's answer.
Hash tables (which are what underlies an unordered_map) are really useful under many circumstances. But in this case, they're kind of overkill. In particular, a hash table is basically a way of creating a sparse array for cases where it's unrealistic or unreasonable to use the underlying "key" type directly as an index into an array.
In this case, however, what we're using as the key in the hash table is a character--a single byte. This is small enough, it's utterly trivial to just use an array, and use the byte directly as an index into the array.
So, with arrays instead of hash tables, we get code something on this order:
#include <array>
#include <string>
#include <iostream>
#include <chrono>
std::string getstring(std::string const &s) {
std::cout << s << ": ";
std::string input;
std::getline(std::cin, input);
return input;
}
using namespace std::chrono;
int main() {
std::array<char, 256> a = {0};
std::array<char, 256> b = {0};
std::array<char, 256> result = { 0 };
std::size_t pos=0;
std::string s1 = getstring("s1");
std::string s2 = getstring("s2");
std::cout << "s1: " << s1 << "\n";
std::cout << "s2: " << s2 << "\n";
auto start = high_resolution_clock::now();
for (auto c : s1)
a[c] = 1;
for (auto c : s2)
b[c] = 1;
for (int i = 'a'; i < 'z'; i++)
if (a[i] != 0 && b[i] != 0)
result[pos++] = i;
for (int i = 'A'; i < 'Z'; i++)
if (a[i] != 0 && b[i] != 0)
result[pos++] = i;
auto stop = high_resolution_clock::now();
std::cout << "Common characters: " << std::string(result.data(), pos) <<"\n";
std::cout << "Time: " << duration_cast<nanoseconds>(stop - start).count() << " nS\n ";
}
To get some repeatable test conditions, I built an input file with a couple of long fairly strings:
asdffghjllkjpoiuwqertqwerxvzxvcn
qqweroiglkgfpoilkagfskeqwriougfkljzxbvckxzv
After adding instrumentation (timing code) to his Variant 4 code, I found that his code ran in about 12,000 to 12,500 nanoseconds.
The code above, on the other hand, runs (on the same hardware) in about 850 nanoseconds, or around 15 times as fast.
I'm going to go on record as saying the opposite: although this is clearly faster, I'm pretty sure it's not the fastest possible. I can see at least one fairly obvious improvement (store only one bit per character instead of one byte) that would probably improve speed by at least 2x, and could theoretically yield an improvement around 8x or so. Unfortunately, we've already sped other things up enough that I doubt we'd see 8x--we'd probably see a bottleneck on reading in the data from memory first (but it's hard to be sure, and likely to vary between processors). So, I'm going to leave that alone, at least for now. For now, I'll settle for only about fifteen times faster than "the fastest possible solution"... :-)
I suppose, in fairness, he probably really meant asymptotically the fastest. His has (expected, but not guaranteed) O(N) complexity, and mine also has O(N) complexity (but in this case, basically guaranteed, not not just expected. In other words, the 15x is roughly a constant factor, not one we expect to change significantly with the size of the input string. Nonetheless, even if it's "only" a constant factor, 15x is still a pretty noticeable difference in speed.

A program to find out if a word is palindrome

Written some algorithm to find out if a given word is a palindrome. But one of my variables (counter) seems not updating when I debugged and I can't figure out what is wrong with it. I may be wrong though... any help will be needed as I don's wanna copy some code online blindly.
Below is the code:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
//take input
string input;
cout << "Enter your word: ";
cin >> input;
//initialize arrays and variables
int counter = 0, k = 0;
int char_length = input.length();
char characters[char_length];
strcpy(characters, input.c_str());//copy the string into char array
//index of character at the midpoint of the character array
int middle = (char_length-1)/2;
int booleans[middle]; //to keep 1's and 0's
//check the characters
int m = 0, n = char_length-1;
while(m < middle && n > middle){
if(characters[m] == characters[n]){
booleans[k] = 1;
} else {
booleans[k] = 0;
}
k++;
m++;
n--;
}
//count number of 1's (true for being equal) in the booleans array
for(int i = 0; i < sizeof(booleans)/sizeof(booleans[0])-1; i++){
counter += booleans[i];
}
//compare 1's with size of array
if(counter == middle){
cout << input << " is a Palindrome!" << endl;
} else {
cout << input << " is not a Palindrome!" << endl;
}
return 0;
}
Brother it seems difficult to understand what your question is and what code you are typing. I am not very much experienced but according to me palindrome is a very very simple and easy program and i would have wrote it as:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char str1[20], str2[20];
int i, j, len = 0, flag = 0;
cout << "Enter the string : ";
gets(str1);
len = strlen(str1) - 1;
for (i = len, j = 0; i >= 0 ; i--, j++)
str2[j] = str1[i];
if (strcmp(str1, str2))
flag = 1;
if (flag == 1)
cout << str1 << " is not a palindrome";
else
cout << str1 << " is a palindrome";
return 0;
}
It will work in every case you can try.
If you get a mismatch i.e. (characters[m] == characters[n]) is false then you do not have a palindrome. You can break the loop at that point, returning false as your result. You do not do that, instead you carry on testing when the result is already known. I would do something like:
// Check the characters.
int lo = 0;
int hi = char_length - 1;
int result = true; // Prefer "true" to 1 for better readability.
while (lo < hi) { // Loop terminates when lo and hi meet or cross.
if(characters[lo] != characters[hi]) {
// Mismatched characters so not a palindrome.
result = false;
break;
}
lo++;
hi--;
}
I have made a few stylistic improvements as well as cleaning up the logic. You were doing too much work to solve the problem.
As an aside, you do not need to check when the two pointers lo and hi are equal, because then they are both pointing to the middle character of a word with an odd number of letters. Since that character must be equal to itself there is not need to test. Hence the < in the loop condition rather than <=.
Existing Code does not work for Palindromes of Odd Length because of
for(int i = 0; i < sizeof(booleans)/sizeof(booleans[0])-1; i++)
Either use i<=sizeof(booleans)/sizeof(booleans[0])-1; or i<sizeof(booleans)/sizeof(booleans[0]);.
Currently, you are not counting the comparison of character[middle-1] and character[middle+1].
For palindromes of even length, you will have to change your logic a bit because even length palindromes don't have a defined middle point.
#include <iostream>
#include <cstring>
using namespace std;
int main(){
//take input
string input;
cout << "Enter your word: ";
cin >> input;
//initialize arrays and variables
int counter = 0, k = 0;
int char_length = input.length();
char characters[char_length];
strcpy(characters, input.c_str());//copy the string into char array
//index of character at the midpoint of the character array
int middle = (char_length+1)/2;
int booleans[middle]; //to keep 1's and 0's
//check the characters
int m = 0, n = char_length-1;
while(m<=n){
if(characters[m] == characters[n]){
booleans[k] = 1;
} else {
booleans[k] = 0;
}
k++;
m++;
n--;
}
//count number of 1's (true for being equal) in the booleans array
for(int i = 0; i < sizeof(booleans)/sizeof(booleans[0]); i++){
counter += booleans[i];
}
cout<<counter<<" "<<middle<<endl;
//compare 1's with size of array
if(counter == middle){
cout << input << " is a Palindrome!" << endl;
} else {
cout << input << " is not a Palindrome!" << endl;
}
return 0;
}
Over here the size of the boolean array is (length+1)/2,
For string s like abcba it will be of length 3.
This corresponds to a comparison between a a, b b and c c. Since the middle element is the same, the condition is always true for that case.
Moreover, the concept of middle is removed and the pointers are asked to move until they cross each other.

How to count the number of times a letter shows up in a randomized string of alphabetical letters

I am trying to find the number of times each letter of the alphabet shows up in a randomized string that the user creates. I have all the code, minus the portion that would count each time a character is found. I have tried to use a couple of for...else loops to figure this out, but maybe I am just not learned to do it correctly, I keep either getting errors or a blank space under the rest of the output.
What I want is for the output to look like this:
A B C D E F G...
1 2 5 7 0 9 2...
Here is my code and my output so far:
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <map>
using namespace std;
int main() {
int i=0, n;
char alphabet[26];
char c;
char RandomStringArray [100];
srand(time(0));
cout <<"How many letters do you want in your random string (no less than 0, no more than 100): ";
cin >> n;
for (int i=0; i<=25; i++)
alphabet[i] = 'a' + i;
while(i<n) {
int temp = rand() % 26;
RandomStringArray[i] = alphabet[temp];
i++;
}
for(i=0; i<n; i++)
cout<<RandomStringArray[i];
cout<<"\n\n";
/*for(c = 'A'; c <= 'Z'; ++c)
cout<<" "<<c;
cout<<"\n";
*/
map<char,size_t> char_counts;
for (int i = 0; i < n; ++i) ++char_counts[RandomStringArray[i]];{
for (char ch :: alphabet) std::cout << ch << ' ';{
std::cout << '\n';
}
for (char ch :: alphabet) std::cout << char_counts[ch] <<'';{
std::cout << '\n';
}
}
}
std::unordered_map is good for this sort of thing. It's similar to the array approach of holding counts for each character but is more convenient to use, especially when the character ranges you're interested in are non-contiguous.
When you index a std::unordered_map the mapped value will be returned by reference, so you just increment it. If it doesn't exist it's created and default initialized (zero initialized for integer types).
So all you need to do is:
std::unordered_map<char, std::size_t> char_counts;
for (int i = 0; i < n; ++i) ++char_counts[RandomStringArray[i]];
After this, char_counts holds the total occurrence counts for all characters in the string. e.g. char_counts['a'] is the number of occurrences of 'a'.
Then to print them all out you could do:
for (char ch : alphabet) std::cout << ch << ' ';
std::cout << '\n';
for (char ch : alphabet) std::cout << char_counts[ch] << ' ';
std::cout << '\n';

Fibonacci series in C++ can't get more than 47 numbers

I designed this program that can print the Fibonacci Series (series[i] = series[i-1] + series[i-2]) but i can't get more than 47 numbers because the 48th they become negative and strange numbers (i think this happens when the list is out of range or the item is null):
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
int length;
string again = "";
do {
cout << "Enter the length you want in your sequence: ";
cin >> length;
vector<int> series(length);
for (int n=0; n<=1; n++) series[n] = n;
for (int number=2; number<=length; number++) {
series[number] = series[number-1] + series[number-2];
}
for (int i=0; i<length; i++) cout << series[i] << " ";
cout << endl << "Do it again ? <y/n> ";
cin >> again;
cout << endl;
} while (again == "y");
}
EDIT:
"Improved" code:
#include <iostream>
#include <vector>
#include <string>
std::vector<int> fibonacci (int length)
{
std::vector<int> series(length);
series[0] = 0;
series[1] = 1;
for (int num=2; num<length; num++) {
series[num] = series[num-1] + series[num-2];
}
return series;
}
int main ()
{
std::string again;
do {
std::cout << "Enter how many numbers you want in your series: ";
int length;
std::cin >> length;
std::vector<int> series(length);
series = fibonacci(length);
for (int n=0; n<length; n++) std::cout << series[n] << " ";
std::cout << "\nDo it again <y/n> ? ";
std::cin >> again;
std::cout << std::endl;
} while (again == "y");
}
When you get to the 47th value, the numbers go out of int range. The maximum int value is 2,147,483,647 and the 46th number is just below at 1,836,311,903. The 47th number exceeds the maximum with 2,971,215,073.
Also, as LeonardBlunderbuss mentioned, you are exceeding the range of the vector with the for loop that you have. Vectors start with 0, and so by having number<=length; the range+1 element will be called. The range only goes up to length-1.
You are encountering integer overflow, meaning that you are trying to calculate a number that is outsize of the bounds of INT_MAX and INT_MIN. In the case of an unsigned number, it just overflows to zero and starts over, while in the case of a signed integer, it rolls over to INT_MIN. In both cases this is referred to as integer overflow or integer wraparound.
You could put a band-aid on the solution by using long long int (likely 64-bits on most modern systems) instead of int for your primitive data type, or you could use a better approach like a library that supports (almost) arbitrarily long data types, like libBigInteger.
References
Integer Overflow, Accessed 2014-03-04, <http://en.wikipedia.org/wiki/Integer_overflow>
C++ Big Integer Library, Accessed 2014-03-04, <https://mattmccutchen.net/bigint/>
The limits.h Header File, Accessed 2014-03-04, <http://tigcc.ticalc.org/doc/limits.html>
This is my solution to calculating BIG fibonacci numbers
// Study for algorithm that counts n:th fibonacci number
#include <iostream>
#include <cstdlib>
#include "boost/multiprecision/cpp_int.hpp"
#define get_buffer(a) buffer[(a)%2]
#define BIG boost::multiprecision::cpp_int
int main(int argc, const char* argv[])
{
// atoi returns 0 if not integer
if(argc != 2 || atoi(argv[1]) < 1){
std::cout << "You must provide one argument. Integer > 0" << std::endl;
return EXIT_SUCCESS;
}
// ring buffer to store previous two fibonacci number, index it with [i%2]
// use defined function get_buffer(i), it will do the magic for you
BIG buffer[2]={ 1, 1 };
// n:th Fibonacci
unsigned int fn = atoi(argv[1]);
// count loop is used if seeked fibonacci number is gt 2
if(fn > 2){
for(unsigned int i = 2; i < fn; ++i){
get_buffer(i) = get_buffer(i-1) + get_buffer(i-2);
// get_buffer(i-1) + get_buffer(i-2) == buffer[0] + buffer[1]
// if you want to print out every result, do it here
}
}
// Result will be send to cout
std::cout << "Fibonacci[" << fn << "] is " << get_buffer(fn-1) << std::endl;
return EXIT_SUCCESS;
}

C++ Two n sized integer lists

I'm new to C++ and I need some help creating this program:
I need to ask for the size of the list, then take the list containing integers and then ask the size of the second list and take those integers.
So far I have this:
#include <iostream>
using namespace std;
int main()
{
long int ARR[10];
int i,n;
printf("List 1 size: ");
scanf("%d",&n);
printf("List 1 data: ");
for(i=0;i<n;i++)
{
scanf("%ld",&ARR[i]);
}
So that will take the input for the first list. Now I will repeat this for the second list.
But the key point is I now need to compare the two lists. If list1 is in list2 then I say yay, or if not then nay.
How do I go about comparing these two lists? And I am I on the right track with the input?
Thanks,
EmptyPeace
I think that's what you expected.
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
bool mypredicate (int i, int j) {
return (i==j);
}
int main(){
int size_list = 0;
vector<int> list1, list2;
cin >> size_list;
list1.resize(size_list);
list2.resize(size_list);
cout << list1.size() << endl;
for (int i = 0; i < size_list; i++)
cin >> list1[i];
for (int i = 0; i < size_list; i++)
cin >> list2[i];
pair<vector<int>::iterator,vector<int>::iterator> mypair;
mypair = mismatch (list1.begin(), list1.end(), list2.begin(), mypredicate);
if( mypair.first == list1.end() && mypair.second == list2.end() )
cout << "are equals" << endl;
else{
cout << "aren't " << endl;
cout << *mypair.first << ", " << *mypair.second << endl;
}
system("pause");
return 0;
}
I think you should use either dynamic array or stl's vector to store data.
for example, dyn. array:
int size;
scanf("%d", size);
int *tab = new int[size];
...
delete[] tab;
or vector way:
#include <vector>
...
int size;
scanf("%d", size);
vector <int> tab(size);
// to insert an element, use tab.push_back( number );
// and getting an element goes array-way, for example tab[0];
And some words from me- if you are writing in c++, use cin and cout for input/output, unless you need extra speed or specific format. And remember, that list is something different than array/vector.