The problem is simple. From given set of digits (there are max 10 digits), compute all numbers that can be madeform this digits (a digit can be used as many times it's is included in the set).
Fist I think of using brute force and running through all possible combinations, but the number of combinations is as big as factorial of N, where N is the number of digits. And even if it's possible how can I run though all possible combinations withouit using 10 for loops?
Second I tried to put all those digits in a string and the erasing one from the string and putting on the end and keep trying like this, but this probably won't give any possible combinations and even if it does I don't believe it'll be in a reasonable time.
I'm sure there must be a quicker and better algorithm for getting all possibles nubmers from a given set of digits.
I found one code on th Internet and it's:
#include <iostream>
#include <algorithm>
using namespace std;
int main () {
int noOfDigits;
cin >> noOfDigits;
int myints[noOfDigits];
for(int i = 0; i<noOfDigits; i++)
{
cin >> myints[i];
}
sort (myints,myints+3);
do {
for(int i = 0; i<noOfDigits;i++)
{
cout << myints[i];
}
cout << endl;
} while ( next_permutation(myints,myints+noOfDigits) );
return 0;
}
My approach might seem a bit convoluted but I'll give an overview and a very simple bit of sample code (from the wrong language) first.
As you say you fundamentally want all the permutations of your elements. So the obvious approach would be to use a library function which already does this. Perhaps std::next_permutation (I'll use intertools.permutations for my simple example). However you specify that you might have duplicate elements among your input set, which violates the constraint on that tool.
So my approach would be to build a mapping between a set of unique keys and our elements (digits) with their possible duplicates. For the small number of digits that you describe the easiest would be to use single characters as keys, mapping them (through a dictionary, of course) to the given elements (digits). A convenient way to do that is through string.printable. So given a tuple, list or other sequence of "digits" called mydigits we can build our mapping as:
#!python
import string
digit_mapping = dict([(y,x) for x,y in zip(mydigits,string.printable)])
From there all we have to do is iterate over the permutations and map the keys back to their original "digits" (in this case the string representation of those "digits"
#!python
for i in itertools.permutations(digit_mapping.keys()):
perm = ''.join([str(digit_mapping[x]) for x in i])
print perm,
... of course you might have to work it a little differently if you wanted to print these permutations in some particular order rather than in whatever the .keys() method and the itertools.permutations() function does. (Those are implementation details).
So, can you create such a mapping, iterate over the permutation of its keys, and perform the map dereferencing as you return/print your results?
Related
I am trying to create a simple game where the user inputs a number, and the computer tries to guess it. The program randomly generates a number between 1 & 100. Whenever the user says a number is too high it stores that value, and every value above that, in an array and vice versa for too low. Then I want the program to generate another random number, but if the number it generates is within the array of wrong numbers, it tries again. But I have absolutely no idea how to check if the number is present in the array. Is this possible?
Yes, this is possible. You will want to use the std::find() algorithm, the reference page for which can be found Here.
It is called as std::find(std::begin(array), std::end(array), someObject);
and returns an iterator to the first element in the range [first,last) that compares equal to someObject. If no such element is found, the function returns last element i.e. end of range.
In building your random number game I would consider whether, checking if the computers guess is out of range and then guessing again if so, is the best way to approach the problem (because it's not the best way).
Also before asking a question please try to find similar questions such as This, or This before asking a new question in order to prevent stackoverflow from becoming too cluttered
For that game you don't need an array. Look at the following program:
#include <iostream>
constexpr long long average (long long a, long long b)
{
return (a+b)>>1;
}
int main()
{
char ans;
long long start, end;
std::cin >> start >> end;
do
{
auto n=average(start,end);
std::cout << n << std::endl;
std::cin >> ans;
if(ans=='<') end=n-1;
else if(ans=='>') start=n+1;
}
while(ans!='=');
}
Think of a number in the range [start, end] and the program will guess it.
It uses binary search algorithm so it will need approximately log2(end-start+1) tries in the worst case.
If I used (with appropriate #includes)
int main()
{
srand(time(0));
int arr[1000];
for(int i = 0; i < 1000; i++)
{
arr[i] = rand() % 100000;
}
return 0;
}
To generate random 5-digit ID numbers (disregard iomanip stuff here), would those ID numbers be guranteed by rand() to be unique? I've been running another loop to check all the values of the array vs the recently generated ID number but it takes forever to run, considering the nested 1000 iteration loops. By the way is there a simple way to do that check?
Since the question was tagged c++11,
you should consider using <random> in place of rand().
Using a standard distribution engine, you can't guarantee that you will get back unique values. If you use a std::set, you can keep retrying until you have the right amount. Depending on your distribution range, and the amount of unique values you are requesting, that may be adequate.
For example, here is a customized function to get n unique values from range [x,y].
#include <unordered_set>
#include <iostream>
#include <random>
template <typename T>
std::unordered_set<T> GetUniqueNumbers(int amount, T low, T high){
static std::random_device random_device;
static std::mt19937 engine{random_device()};
std::uniform_int_distribution<T> dist(low, high);
std::unordered_set<T> uniques;
while (uniques.size() < amount){
uniques.insert(dist(engine));
}
return uniques;
}
int main(){
//get 10 unique numbers between [0,100]
auto numbers = GetUniqueNumbers(10,0,100);
for (auto number: numbers){
std::cout << number << " ";
}
}
No, because any guarantee about the output of a random source makes it less random.
There are specific mathematical formulas that have the behavior known as a random permutation. This site seems to have quite a good write-up about it: http://preshing.com/20121224/how-to-generate-a-sequence-of-unique-random-integers/
No, there is definitely no guarantee rand will not produce duplicate numbers, designing it in such a way would not only be expensive in terms of remembering all the numbers it has returned so far but will also reduce its randomness greatly (after it had returned many numbers you could guess what it is likely to return from what it had already returned so far).
If uniqueness is your only goal, just use an incrementing ID number for each thing. If the numbers must also be arbitrary and hard to guess you will have to use some kind of random generator or hash, but should make the numbers much longer to make the chance of a collision much closer to 0.
However if you absolutely must do it the current way I would suggest storing all the numbers you have generated so far into a std::unordered_map and generating another random number if it is already in it.
There is a common uniqueness guarantee in most PRNGs, but it won't help you here. A generator will typically iterate over a finite number of states and not visit the same state twice until every other state has been visited once.
However, a state is not the same thing as the number you get to see. Many states can map to the same number and in the worst possible case two consecutive states could map to the same number.
That said, there are specific configurations of PRNG that can visit every value in a range you specify exactly once before revisiting an old state. Notably, an LCG designed with a modulo that is a multiple of your range can be reduced to exactly your range with another modulo operation. Since most LCG implementations have a power-of-two period, this means that the low-order bits repeat with shorter periods. However, 10000 is not a power of two, so that won't help you.
A simple method is to use an LCG, bitmask it down to a power of two larger than your desired range, and just throw away results that it produces that are out of range.
For fun and practice, I have tried to solve the following problem (using C++): Given a string, return all the palindromes that can be obtained by rearranging its characters.
I've come up with an algorithm that doesn't work completely. Sometimes, it finds all the palindromes, but other times it finds some but not all.
It works by swapping each adjacent pair of characters N times, where N is the length of the input string. Here is the code:
std::vector<std::string> palindromeGen(std::string charactersSet) {
std::vector<std::string> pals;
for (const auto &c : charactersSet) {
for (auto i = 0, j = 1; i < charactersSet.length() - 1; ++i, ++j) {
std::swap(charactersSet[i], charactersSet[j]);
if (isPalandrome(charactersSet)) {
if (std::find(pals.begin(), pals.end(), charactersSet) == pals.end()) {
// if palindrome is unique
pals.push_back(charactersSet);
}
}
}
}
return pals;
}
What's the fault in this algorithm? I'm mostly concerned about the functionality of the algorithm, rather than the efficiency. Although I'll appreciate tips about efficiency as well. Thanks.
This probably fits a bit better in Code Review but here goes:
Logic Error
You change charactersSet while iterating over it, meaning that your iterator breaks. You need to make a copy of characterSet, and iterate over that.
Things to Change
Since pals holds only unique values, it should be a std::set instead of a std::vector. This will simplify some things. Also, your isPalandrome method spells palindrome wrong!
Alternative Approach
Since palindromes can only take a certain form, consider sorting the input string first, so that you can have a list of characters with an even number of occurrences, and a list of characters with an odd number. You can only have one character with an odd number of occurrences (and this only works for an odd length input). This should let you discard a bunch of possibilities. Then you can work through the different possible combinations of one half of the palindrome (since you can build one half from the other).
Here is another implementation that leverages std::next_permutation:
#include <string>
#include <algorithm>
#include <set>
std::set<std::string> palindromeGen(std::string charactersSet)
{
std::set<std::string> pals;
std::sort(charactersSet.begin(), charactersSet.end());
do
{
// check if the string is the same backwards as forwards
if ( isPalindrome(charactersSet))
pals.insert(charactersSet);
} while (std::next_permutation(charactersSet.begin(), charactersSet.end()));
return pals;
}
We first sort the original string. This is required for std::next_permutation to work correctly. A call to the isPalindrome function with a permutation of the string is done in a loop. Then if the string is a palindrome, it's stored in the set. The subsequent call to std::next_permutation just rearranges the string.
Here is a Live Example. Granted, it uses a reversed copy of the string as the "isPalindrome" function (probably not efficient), but you should get the idea.
so I'm just learning (or trying to) a bit about hashing. I'm attempting to make a hashing function, however I'm confused where I save the data to. I'm trying to calculate the number of collisions and print that out. I have made 3 different files, one with 10,000 words, 20,000 words and 30,000 words. Each word is just 10 random numbers/letters.
long hash(char* s]){
long h;
for(int i = 0; i < 10; i++){
h = h + (int)s[i];
}
//A lot of examples then mod h by the table size
//I'm a bit confused what this table is... Is it an array of
//10,000 (or however many words)?
//h % TABLE_SIZE
return h
}
int main (int argc, char* argv[]){
fstream input(argv[1]);
char* nextWord;
while(!input.eof()){
input >> nextWord;
hash(nextWord);
}
}
So that's what I currently have, but I can't figure out what the table is exactly, as I said in the comments above... Is it a predefined array in my main with the number of words in it? For example, if I have a file of 10 words, do I make an array a of size 10 in my main? Then if/when I return h, lets say the order goes: 3, 7, 2, 3
The 4th word is a collision, correct? When that happens, I add 1 to collision and then add 1 to then check if slot 4 is also full?
Thanks for the help!
The point of hashing is to have a constant time access to every element you store. I'll try to explain on simple example bellow.
First, you need to know how much data you'd have to store. If for example you want to store numbers and you know, that you won't store numbers greater than 10. Simpliest solution is to create an array with 10 elements. That array is your "table", where you store your numbers. So how do I achieve that amazing constant time access? Hashing function! It's point is to return you an index to your array. Let's create a simple one: If you'd like to store 7, you just save it to array on position 7. Every time, you'd like to look, for element 7, you just pass it to your hasning funcion and bzaah! You got an position to your element in constant time! But what if you'd like to store more elements with value 7? Your simple hashing function is returning 7 for every element and now its position i already occupied! How to solve that? Well, there is not many solution, the simpliest are:
1: Chaining - you simply save element on first free position. This has significant draw back. Imagine, you want to delete some element ... (this is the method, you describing in question)
2: Linked list - if you create an array of pointers on some linked lists, you can easilly add your new element at the end of linked list, that is on position 7!
Both of this simple solutions has its drawbacks and cons. I guess you can see them. As #rwols has said, you don't have to use array. You can also use a tree or be a real C++ master and use unordered_map and unordered_set with custom hash function, which is quite cool. Also there is structure named trie, which is usefull, when you'd like to create some sort of dictionary (where is really hard to know, how many words you will need to store)
To sum it up. You has to know, how many things, you wan't to store and then, create ideal hashing function, that covers up array of apropriate size and in perfect world, it has to have uniform index distribution, with no colisions. (Achiving this is pretty hard and in the real world, I guess, this is impossible, so the less colisions, the better.)
Your hash function, is pretty bad. It will have lot of colisions (like strings "ab" and "ba") and also, you need to mod m it with m being the size of you array (aka. table), so you can save it to some array and you can profit of it. The modus is a way of simplyfiing the has function, because has function has to "fit" in table, that you specified in beginning, because you can't save element on position 11, 12, ... if you have array of 10.
How should good hashing function look like? Well, there is better sources than me. Some example (Alert! It's in Java)
To your example: You simply can't save 10k or even more words into table of size 10. That'll create a lot of collisions and you loose the main benefit of hashing function - constant access to elements you saved.
And how would your code look? Something like this:
int main (int argc, char* argv[]){
fstream input(argv[1]);
char* nextWord;
TypeOfElement table[size_of_table];
while(!input.eof()){
input >> nextWord;
table[hash(nextWord)] = // desired element which you want to save
}
}
But I guess, your goal isn't to save something somewhere, but to count number of colisions. Also note that code above doesn't solve colisions. If you'd like to count colisions, create array table of ints and initialize it to zero. Than, just increment the value, which is stored on index, which is returned by your hash funcion, like this:
table[hash(nextWord)]++;
I hope I helped. Please specify, what else you want to know.
If a hash table is required then as others have stated std::unordered_map will work in most cases. Now if you need something more powerful because of a large entry base, then I would suggest looking into tries. Tries combine the concepts of (Vector-Array) insertion, (Hashing) & Linked Lists. The run time is close to O(M) where M is the amount of characters in a string if you are hashing a string. It helps to remove the chance of collisions. And the more you add to a trie structure the less work has to be done as certain nodes are opened and created. The one draw back is that tries require more memory. Here is a diagram
Now your trie may vary on the size of the array due to what you are storing, but the overall concept and construction of one is the same. If you was doing a word - definition look up then you may want an array of 26 or a few more for each possible hashing character.
To count a number of words which have same hash, we should know hashes of all previous words. When you count a hash of some word, you should write it down, for example in some array. So you need an array with size equal to the number of words.
Then you should compare the new hash with all previous ones. Method of counting depends on what you need - number of pair of collisions or number off same elements.
Hash function should not be responsible for storing data. Normally you would have a container that uses hash function internally.
From what you wrote I understood that you want to create hashtable. One way you could do that (probably not the most efficient one, but should give you an idea):
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <memory>
using namespace std;
namespace example {
long hash(char* s){
long h;
for(int i = 0; i < 10; i++){
h = h + (int)s[i];
}
return h;
}
}
int main (int argc, char* argv[]){
fstream input(argv[1]);
char* nextWord;
std::map<long, std::unique_ptr<std::vector<std::string>>> hashtable;
while(!input.eof()){
input >> nextWord;
long newHash = example::hash(nextWord);
auto it = hashtable.find(newHash);
// Collision detected?
if (it == hashtable.end()) {
hashtable.insert(std::make_pair(newHash, std::unique_ptr<std::vector<std::string>>(new std::vector<std::string> { nextWord } )));
}
else {
it->second->push_back(nextWord);
}
}
}
I used some C++ 11 features to write an example faster.
I am not sure that I understand what you do not understand. The explanations below might help you.
A hash table is a kind of associative array. It is used to map keys to values in a similar manner an array is used to map indexes (keys) to values. For instance, an array of three numbers, { 11, -22, 33 }, associates index 0 to 11, index 1 to -22 and index 2 to 33.
Now, let us assume that we would like to associate 1 to 11, 2 to -22 and 3 to 33. The solution is simple: we keep the same array, only we transform the key by subtracting one from it, thus obtaining the original index
This is fine until we realize that this is just a particular case. What if the keys are not so “predictable”? A solution would be to put the associations in a list of {key, value} pairs and when someone is asking for a key, just search the list: { 123, 11}, {3, -22}, {0, 33} If the value associated to 3 is asked, we simply search the keys in list for a match and find -22. That’s fine, but if the list is large we’re in trouble. We could speed the search if we sort the array by keys and use binary search, but still the search may take some time if the list is large.
The search speed may be further enhanced if we break the list in sub-lists (or buckets) made of related pairs. This is what a hash function does: puts together pairs by related keys (an ideal hash function would associate one key to one value).
A hash table is a two columns table (an array):
The first column is the hash key (the index computed by a hash function). The size of the hash table is given by the maximum value of the hash function. If, for instance, the last step in computing the hash function is modulo 10, the size of the table will be 10; the pairs list will be broken into 10 sub-lists.
The second column is a list (bucket) of key/values pairs (the sub-list I was taking about).
I want to change the behavior of std::swap for char type. According to what I have learned, the only a way to do this is to add a template specialization for std::swap, isn't it?
Since char is a built-in type, we have no chance to use ADL.
Please give your advice for such cases.
Edit: Here is the original problem I needed to solve. Random shuffle a string except that non-alpha characters should keep their positions unchanged.
The first thing I want to do is to leverage the std::random_shuffle.
First: Don't do that. You may inadvertently break a different part of code that was previously working.
What you could try is to create your own class, make it hold only a single char element in it and then add any fancy functionality to it that you like. This way you would have your own swap behavior without breaking somebody elses code.
However, if you still want to do that, try the following (running) example:
#include <algorithm>
#include <iostream>
namespace std {
template <>
void swap<char>(char& a, char& b) {
std::cerr << "Swapped " << a << " with " << b << "\n";
char t=a;
a=b;
b=t;
}
}
int main() {
char arr[] = {'a', 'z', 'b', 'y'};
std::reverse(arr, arr+4);
return 0;
}
Do note that some stl algorithms may be specialized for basic types and not use std::swap at all.
Ad. Edited question:
Fair shuffling algorithm is fairly simple:
for (i = 0 .. n-2) {
j = random (i .. n-1); //and NOT random (0 .. n-1)
swap(array[i], array[j]);
}
however, if you modify swap to prevent the operation when either of the arguments is not alphanumeric (I presume that's what you wanted to change swap into?), the remaining permutation is not going to be fair. With the increasing number of non-alhanumeric characters, the chance that given character won't move - increases. In worst-case scenario, imagine a long string with only two alphanumeric characters - the chance of them getting swapped will be near 0.
If you want to have fair permutation on only non-alpha characters you can do:
a) Pretty straightforward way - extract the alphanumeric characters to separate array, shuffle, and then put them back.
Simple, no performance hit, but needs more memory.
b) If the number of nonalphanumeric characters is relatively low, you can repeat the dice roll:
for (i = 0 .. n-2) {
if (!alphanumeric(array[i]) continue;
do {
j = random (i .. n-1);
while (!alphanumeric(array[j]));
swap(array[i], array[j]);
}
This shuffling will be still fair, but will take a lot of time when you have a lot of nonalphanumeric characters.