I want to obtain all words of specific length/alphabet which have a minimal hamming distance among themselves.
I'm not a mathematician so I try to show an example to make it clear what I need.
Word Length L = 4
Word Alphabet A = {0,1}
Word Alphabet Size |A| = 2
Word Min. Hamming Dist. H = 2
The first word is
w0 = {0,0,0,0}
Now the other words could be:
w1 = {0,0,1,1}
w2 = {1,1,0,0}
And hamming distances are
Hamming(w0,w1) = 2 >= H
Hamming(w0,w2) = 2 >= H
Hamming(w1,w2) = 4 >= H
As you see, all hamming distances are equal or greater H.
For my purpose I would need L=512 and A={0,1} and |A|=2 and H=70.
How can I calculate this all without brute force / try and error?
Below is some ugly quick hack code which is ultimately slow. How to get this lightning fast?
// std header(s)
#include <array>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <iterator>
#include <random>
#include <chrono>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <bitset>
#include <fstream>
#include <iostream>
class Hamming {
public:
Hamming(int & _distance) : distance_(_distance) {};
void operator() ( boost::tuple<int, int> const & words) {
if(boost::get<0>(words)!=boost::get<1>(words)) {
std::bitset<4> n=boost::get<0>(words);
std::bitset<4> m=boost::get<1>(words);
distance_+=(n ^ m).count();
}
}
private:
int & distance_;
};
int main(int argc,char** argv) {
const int arraysize=61;
std::array<int,arraysize> a;
int distance=0;
int num;
std::cout << "Input number of bag_words"<<std::endl;;
std::cin>>num;
std::vector<std::array<int, arraysize>> bag;
Hamming myobject(distance);
////
std::mt19937 mt(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::uniform_int_distribution<int> d(0, 255);
std::generate(a.begin(),a.end(),[&]{return d(mt);});
bag.push_back(a);
int counter=1;
while (counter<num) {
std::generate(a.begin(),a.end(),[&]{return d(mt);});
int test=0;
distance=0;
for (int i=0 ; i<counter ; i++) {
std::for_each(
boost::make_zip_iterator(
boost::make_tuple(a.begin(), bag[i].begin())
),
boost::make_zip_iterator(
boost::make_tuple(a.end(), bag[i].end())
),
Hamming(distance)
);
if(distance>10) {
++test;
}
else break;
}
if (test==counter) {
bag.push_back(a);
++counter;
}
}
std::cout << std::endl;
std::ofstream myfile ("example.txt");
if (myfile.is_open()) {
for(int i = 0; i < counter; i ++) {
for (int j=0 ; j<arraysize ; j++) {
myfile << bag[i][j] << " " ;
}
myfile << "\n";
}
myfile.close();
}
else std::cout << "Unable to open file";
}
Related
I need my program to make a random sequence from 1-3 each time, but I don't understand how I'd use rand() to make the sequence of numbers 1 to 3 in a different order each program. It can't be the same number again, so I don't know what I'd do to prevent that. An example run would be
123 the first, 231 the second, 321 and so fourth
What would you use to make a sequence that doesn't repeat numbers
The simplest way to generate your sequence would be to use std::shuffle to re-order a vector containing your desired values:
#include <vector>
#include <algorithm>
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 g(rd());
std::vector<int> elements = { 1, 2, 3 };
std::shuffle(elements.begin(), elements.end(), g);
for (int i : elements)
{
std::cout << i << "\n";
}
}
If you really must use rand() (its not generally a very good random number generator) you can just about squeeze it into shuffle too:
#include <vector>
#include <algorithm>
#include <ctime>
#include <iostream>
struct RandDevice
{
using result_type = uint32_t;
static result_type max() { return static_cast<result_type>(RAND_MAX); };
static result_type min() { return 0; };
result_type operator()() {
return static_cast<result_type>(rand());
}
};
int main()
{
std::vector<int> elements = { 1, 2, 3 };
srand(time(0));
std::shuffle(elements.begin(), elements.end(), RandDevice());
for (int i : elements)
{
std::cout << i << "\n";
}
}
You can use std::next_permutation
Example here : https://en.cppreference.com/w/cpp/algorithm/next_permutation
it's pretty easy to do.. just compare the number you with every occupied element in the array. if it is not in the array, add to array. else, try again.
I have done similar code check this out
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
void displayArray(int randNum[], int elements);
void randomNum(int randNums[], int elements);
int main ()
{
//declare array
int numbers[999] = {0};
//random number generator
srand(static_cast<int>(time(0)));
randomNum(numbers, 999);
displayArray(numbers, 999);
system("pause");
return 0;
}
void randomNum(int randNums[], int elements)
{
for (int i = 0; i < elements; i++)
{
bool same;
do
{
same = false;
randNums[i] = rand() % 999 + 100;
// Check if the newly generated number is a duplicate:
for (int check = 0; check < i; check++)
{
if (randNums[i] == randNums[check])
{
same = true;
break;
}
}
} while (same);
}
}
void displayArray(int randNum[], int elements)
{
for (int sub = 0; sub < elements; sub ++)
{
cout << "Unique Numbers: " << randNum[sub] << endl;
}
}
I am trying to do is display all the suffixes of a word as such:
word: house
print:
h
ho
hou
hous
house
What I did is:
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char cuvant[100];
int i,k;
cin>>cuvant;
for(i=0;i<strlen(cuvant);i++)
{
for(k=0;k<i;k++)
{
if(k==0)
{
cout<<cuvant[k]<<endl;
}else
{
for(k=1;k<=i;k++){
if(k==i) cout<<endl;
cout<<cuvant[k];
}
}
}
}
}
What am I doing wrong?
You're over-complicating it. Here's a simpler way:
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s;
std::cin >> s;
for (std::string::size_type i = 0, size = s.size(); i != size; ++i)
std::cout << std::string_view{s.c_str(), i + 1} << '\n';
}
If you don't have access to a C++17 compiler, you can use this one:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
int main() {
std::string s;
std::cin >> s;
for (auto const& ch : s) {
std::copy(s.c_str(), (&ch + 1),
std::ostream_iterator<decltype(ch)>(std::cout));
std::cout << '\n';
}
}
Even so, I think it would be better for your learning progress to use a debugger to finger out the problem yourself. Here the problems with your code:
For the i=0 (the first iteration of your outer loop) the for(k=0;k<i;k++) will not be executed at all, as k<0 evaluates to false.
And having a running variable (k) that you change in two for loops that are nested, is most of the time also an indication that something is wrong.
So what you want to do: You want to create each possible prefix, so you want to create n strings with the length of 1 to n. So your first idea with the outer loop is correct. But you overcomplicate the inner part.
For the inner part, you want to print all chars from the index 0 up to i.
int main() {
char cuvant[100];
std::cin >> cuvant;
// loop over the length of the string
for (int i = 0, size = strlen(cuvant); i < size; i++) {
// print all chars from 0 upto to i (k<=0)
for (int k = 0; k <= i; k++) {
std::cout << cuvant[k];
}
// print a new line after that
std::cout << std::endl;
}
}
But instead of reinventing the wheel I would use the functions the std provides:
int main() {
std::string s;
std::cin >> s;
for (std::size_t i = 0, size = s.size(); i < size; i++) {
std::cout << s.substr(0, i + 1) << std::endl;
}
}
For this very simple string suffix task you can just use:
void main()
{
std::string s = "house";
std::string s2;
for(char c : s)
{
s2 += c;
cout << s2 << endl;
}
}
For more complicated problems you may be interested to read about Suffix Tree
Your code is wrong, the following code can fulfill your requirements
#include <iostream>
using namespace std;
int main()
{
char cuvant[100];
int i,k;
cin>>cuvant;
for(i=0;i<strlen(cuvant);i++)
{
for (k = 0; k <= i; ++k)
{
cout<<cuvant[k];
}
cout<<endl;
}
}
Finding the following as the source of a segfault just cost me about 4h of work:
#include <boost/range/combine.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <vector>
#include <list>
int main(int, const char*[])
{
std::vector<int> v;
std::list<char> l;
for (int i = 0; i < 5; ++i)
{
v.push_back(i);
l.push_back(static_cast<char>(i) + 'a');
}
v.push_back(5);
int ti;
char tc;
BOOST_FOREACH(boost::tie(ti, tc), boost::combine(v, l))
{
std::cout << '(' << ti << ',' << tc << ')' << '\n';
}
return 0;
}
If you execute this example, you will note that combine happily iterates as long as the longer range has values. I do not see this in the documentation.
Is there a way to limit the iteration to the shorter of the two ranges?
I'm doing this exercise from DCoder, and I'm trying to solve it in C++. But I need a little help. Although I know this should be simple, I just seem to miss something.
I'm given 2 inputs, the first one is the number of letters that will follow, and the second input is these letters. I need to write a code that will give an output of the letter array in alphabetically sorted order.
Example input:
5
Z k a P b
Expected output:
a b k P Z
Can any of you guys show me what the simplest way is to solve my problem?
I tried the std::sort() function in many ways, but it's not helping me much.
Is the std::sort() function even a good way to sort something like this?
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
//Compiler version g++ 6.3.0
int main() {
int n;
cin >> n;
char s;
vector<char> vec;
while (cin >> s){
vec.push_back(s);
}
sort(vec.begin(), vec.end());
for (int i = 0; i <= vec.size(); i++){
cout << vec[i] << " " ;
}
}
My code is supposed to output a c D M, but it's giving D M a c instead.
std::sort() will work fine, but note that it orders values in ascending order by default, and in ASCII uppercase letters appear before lowercase letters. To get around that, you can give std::sort() a custom comparator that performs a case-insensitive comparison, eg:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cctype>
int main() {
int n;
char c;
std::vector<char> vec;
std::cin >> n;
for (int i = 0; (i < n) && (std::cin >> c); ++i) {
vec.push_back(c);
}
/* alternatively:
std::copy_n(std::istream_iterator<char>(std::cin), n, std::back_inserter(vec));
*/
std::sort(vec.begin(), vec.end(),
[](unsigned char c1, unsigned char c2){ return std::tolower(c1) < std::tolower(c2); }
);
for (size_t i = 0; i < vec.size(); ++i){
std::cout << vec[i] << " ";
}
/* alternatively:
for (char c : vec){
std::cout << c << " ";
}
*/
}
Live Demo
This is the code that worked for me:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cctype>
using namespace std;
//Compiler version g++ 6.3.0
char my_tolower(char ch)
{
return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
}
int main() {
int n;
cin >> n;
char c;
vector<char> vec;
for (int i = 0; (i < n) && (cin >> c); ++i){
vec.push_back(c);
}
sort(vec.begin(), vec.end(),
[](char c1, char c2){ return my_tolower(c1) < my_tolower(c2); }
);
for (auto &&c : vec){
cout << c << " ";
}
}
I have to write a short routine that will write out only upper case letters in reversed order. I managed to muster up code that somehow works, but whenever I test out my code with one specific input:
7 ENTER a b C d E f G
Instead of getting G E C I get
G (special) r E
I can't see what causes the problem, especially because it works for so many other cases. Here's the code:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
char stringa[n];
int length = 0;
for (int i = 0; i <= n-1; i++) {
char letter;
cin >> letter;
if (isupper (letter)) {
stringa[((n-i) - 1)] = letter;
length = length +1;
} } for ( int i =0; i<=length-1; i++) {
cout << ciag[i]
The main problem is that you are not populating your array correctly.
You are not initializing the content of the array before filling it, so it contains random garbage. Then you are filling specific elements of the array using indexes that are the directly related to each uppercase character's original position in the input, rather than the position they should appear in the output.
Since you are not initializing the array, and the input has mixed lower/upper casing, your array is going to have gaps containing random data:
stringa[0] = G
stringa[1] = <random>
stringa[2] = <random>
stringa[3] = <random>
stringa[4] = E
stringa[5] = <random>
stringa[6] = <random>
stringa[7] = <random>
stringa[8] = C
stringa[9] = <random>
stringa[10] = <random>
stringa[11] = <random>
stringa[12] = <random>
stringa[13] = <random>
stringa[14] = R
stringa[15] = E
stringa[16] = T
stringa[17] = N
stringa[18] = E
stringa[19] = <random>
stringa[20] = <random>
That is what you are seeing appear in your garbled output.
Try something more like this instead:
#include <iostream>
#include <vector>
#include <cctype>
int main()
{
int n;
std::cin >> n;
std::vector<char> stringa(n); // 'char stringa[n];' is not standard!
int length = 0;
for (int i = 0; i < n; ++i)
{
char letter;
std::cin >> letter;
if (std::isupper (letter))
{
stringa[length] = letter;
++length;
}
}
for (int i = length-1; i >= 0; --i)
{
std::cout << stringa[i];
}
return 0;
}
Or:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cctype>
int main()
{
int n;
std::cin >> n;
std::vector<char> stringa(n); // 'char stringa[n];' is not standard!
int length = 0;
for (int i = 0; i < n; ++i)
{
char letter;
std::cin >> letter;
if (std::isupper (letter))
{
stringa[length] = letter;
++length;
}
}
std::reverse(stringa.begin(), stringa.begin()+length);
for (int i = 0; i < length; ++i)
{
std::cout << stringa[i];
}
return 0;
}
Both approaches produces the following array content during the first loop, and then simply output it in reverse order in the second loop:
stringa[0] = E
stringa[1] = N
stringa[2] = T
stringa[3] = E
stringa[4] = R
stringa[5] = C
stringa[6] = E
stringa[7] = G
Alternatively, I would suggest using std::getline() instead of a reading loop to obtain the user's input, and then simply manipulate the resulting std::string as needed:
#include <iostream>
#include <string>
#include <algorithm>
bool IsNotUpper(char ch)
{
return !std::isupper(ch);
}
int main()
{
std::string stringa;
std::getline(std::cin, stringa); // returns "7 ENTER a b C d E f G"
// so std::isupper() will return false for everything not in A-Z
std::setlocale(LC_ALL, "C");
stringa.erase(
std::remove_if(stringa.begin(), stringa.end(), &IsNotUpper),
stringa.end());
// returns "ENTERCEG"
std::reverse(stringa.begin(), stringa.end());
// returns "GECRETNE"
std::cout << stringa;
return 0;
}
Or, if using C++11 and later, you can use a lambda instead of a function for the std::remove_if() predicate:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string stringa;
std::getline(std::cin, stringa);
std::setlocale(LC_ALL, "C");
stringa.erase(
std::remove_if(
stringa.begin(), stringa.end(),
[](char ch){return !std::isupper(ch);}
),
stringa.end());
std::reverse(stringa.begin(), stringa.end());
std::cout << stringa;
return 0;
}
Your algorithm just doesn't make any sense. You are expecting the characters to be in the array with no gaps but you skip an entry in the array when the input isn't a capital letter. Instead, put the capital letters in consecutive slots in the array in the forward direction and then traverse it in reverse order afterwards.