Suppose I want to get every combination of 1's and 0's with length n. For example, if n = 3, then I want
000
001
010
011
100
101
110
111
My initial thought was to use something like:
#include <iostream>
#include <bitset>
#include <cmath>
int main() {
int n = 3;
for (int i = 0; i < pow(2, n); i++)
std::cout << std::bitset<n>(i).to_string() << '\n';
}
but this does not work since std::bitset takes a const, whereas I need n to be variable (for example if I am in a loop).
How can I do this?
A straightforward way: Extract each bits using bitwise shift operation.
#include <iostream>
int main() {
int n = 3;
for (int i = 0; i < (1 << n); i++) {
for (int j = n - 1; j >= 0; j--) {
std::cout << ((i >> j) & 1);
}
std::cout << '\n';
}
return 0;
}
Note that this method will work only if n is small enough not to cause an integer overflow (1 << n doesn't exceed INT_MAX).
To generate larger sequence, you can use recursion:
#include <iostream>
#include <string>
void printBits(int leftBits, const std::string& currentBits) {
if (leftBits <= 0) {
std::cout << currentBits << '\n';
} else {
printBits(leftBits - 1, currentBits + "0");
printBits(leftBits - 1, currentBits + "1");
}
}
int main() {
int n = 3;
printBits(n, "");
return 0;
}
C++20 format to the rescue:
int main()
{
int p;
while (std::cin >> p) {
std::cout << std::format("--------\n2^{}\n", p);
auto n = 1 << p;
for (int i = 0; i < n; i++) {
std::cout << std::format("{:0{}b}\n", i, p);
}
}
}
https://godbolt.org/z/5so59GGMq
Sadly for now only MSVC supports it.
It is also possible to declare and use an Integer class with a parametrable number of bits (static variable) like below ? Use is simple :
#include "Integer.hpp"
int main (int argc, char* argn []) {
Integer::set_nbit (3);
Integer i (0);
do {
i.write (std::cout); std::cout << std::endl;
++i;
}
while (!i.is_max ());
if (i.is_max ()) {i.write (std::cout); std::cout << std::endl;}
return 0;
}
The results are those expected :
000
001
010
011
100
101
110
111
And the Integer class is not that complex now (to be completed with other operation than pre-incrementation, operator =, ==...) : using Little Endian Convention internally, and Big Endian convention for outputs (Integer class can be easily extended to an undetermined number of bits Integer)
#include <iostream>
#include <vector>
#include <algorithm>
class Integer {
static int nbit_;
static int nmax_;
public :
static void set_nbit (int s) {nbit_ = s; auto q (1); auto nb (0); while ((nb +1) < nbit_) {q <<= 1;++nb; nmax_ += q;} }
Integer (int i = 0) : val_ (nbit_, 0) {
int q (1);
int siz (0);
while (q <= i) { ++siz; q<<=1;}
if (!siz) return;
if (q > 1) q >> 1;
auto rit (val_.rbegin ());
auto rest (i);
while (rest > 1) {
*rit++ = rest%q ?true:false;
rest -= q;
q >>= 1;
}
if (q) *rit++ = true;
}
Integer (const Integer& i) : val_ (i.val_) {
}
void operator ++ () {
auto carry ((int) 1);
std::find_if (val_.begin (), val_.end (), [&carry] (std::_Bit_iterator::reference b) {
if (!carry) return true;
if (b) {
b = false;
//carry continues to be 1
}
else {
b = true; carry = 0;
}
return false;
});
if (carry) exit (1);
}
operator std::string () const {
std::string str (val_.size (), '0');
auto i (str.begin ());
auto b0 ('0'), b1 ('1');
std::for_each (val_.rbegin (), val_.rend (), [&i, &b0, &b1] (const auto& b) {*i++ = b ?b1:b0;});
return str;
}
void write (std::ostream& os) const{
os << operator std::string ();
}
bool is_max () const {
auto i (val_.begin ());
i = std::find_if (val_.begin (), val_.end (), [] (const auto& b) {return !b;});
if (i == val_.end ()) return true;
return false;
}
//operators == (string), < (int), < (Integer), =, == TO be written
private :
std::vector<bool> val_;
};
int Integer::nmax_ (0);
int Integer::nbit_ (0);
Related
Getting totally unexpected results while comparing binary search vs linear search's real time performance in C++ using the code below -
typedef std::chrono::microseconds us;
int linear_search(uint64_t* val, int s, int e, uint64_t k) {
while (s < e) {
if (!less<uint64_t>()(val[s], k)) {
break;
}
++s;
}
return {s};
}
int binary_search(uint64_t* val, int s, int e, uint64_t k) {
while (s != e) {
const int mid = (s + e) >> 1;
if (less<uint64_t>()(val[mid], k)) {
s = mid + 1;
} else {
e = mid;
}
}
return {s};
}
int main() {
// Preparing data
int iter = 1000000;
int m = 1000;
uint64_t val[m];
for(int i = 0; i < m;i++) {
val[i] = rand();
}
sort(val, val + m);
uint64_t key = rand();
// Linear search time computation
auto start = std::chrono::system_clock::now();
for (int i = 0; i < iter; i++) {
linear_search(val, 0, m - 1, key);
}
auto end = std::chrono::system_clock::now();
auto elapsed_us = std::chrono::duration_cast<us>(end - start);
std::cout << "Linear search: " << m << " values "
<< elapsed_us.count() << "us\n";
// Binary search time computation
start = std::chrono::system_clock::now();
for (int i = 0; i < iter; i++) {
binary_search(val, 0, m - 1, key);
}
end = std::chrono::system_clock::now();
elapsed_us = std::chrono::duration_cast<us>(end - start);
std::cout << "Binary search: " << m <<" values "
<< elapsed_us.count() << "us\n";
}
Compiling without optimisation, getting following output -
Linear search: 1000 values 1848621us
Binary search: 1000 values 24975us
When compiled with -O3 optimisation, getting this output -
Linear search: 1000 values 0us
Binary search: 1000 values 13424us
I understand that for small array size, binary search may be expensive than linear but can't understand reason for difference of this magnitude by adding -O3
I benchmarked your code with https://quick-bench.com and binary search is much faster (for m = 100, it breaks for m = 1000). That's my benchmark code:
int linear_search(uint64_t* val, int s, int e, uint64_t k) {
while (s < e) {
if (!std::less<uint64_t>()(val[s], k)) {
break;
}
++s;
}
return s;
}
int binary_search(uint64_t* val, int s, int e, uint64_t k) {
while (s != e) {
const int mid = (s + e) >> 1;
if (std::less<uint64_t>()(val[mid], k)) {
s = mid + 1;
} else {
e = mid;
}
}
return s;
}
constexpr int m = 100;
uint64_t val[m];
uint64_t key = rand();
void init() {
static bool isInitialized = false;
if (isInitialized) return;
for(int i = 0; i < m;i++) {
val[i] = rand();
}
std::sort(val, val + m);
isInitialized = true;
}
static void Linear(benchmark::State& state) {
init();
for (auto _ : state) {
int result = linear_search(val, 0, m - 1, key);
benchmark::DoNotOptimize(result);
}
}
BENCHMARK(Linear);
static void Binary(benchmark::State& state) {
init();
for (auto _ : state) {
int result = binary_search(val, 0, m - 1, key);
benchmark::DoNotOptimize(result);
}
}
BENCHMARK(Binary);
and the result:
Only the code inside for (auto _ : state) { is benchmarked.
The compiler manages to realize that your linear search is a noop (it has no side effects) and converts it to doing nothing. So it takes zero time.
To fix that, consider taking the return value and adding it up, then printing it outside the timing block.
I solved this problem statement (Yeah Yeah, I know, I am putting the problem statement below).
Given are an integer X and an integer sequence of length N: p1, …, pN.
Among the integers not contained in the sequence p1, …, pN (not necessarily positive),
find the integer nearest to X, i.e. the integer whose absolute difference with X is the minimum.
If there are multiple such integers, report the smallest such integer
This is the code I used:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
int main() {
int x = 0;
int n = 0;
std::cin >> x >> n;
std::vector<decltype(x)> vect(n);
bool vect_contains_x = false;
for (auto& elem : vect) {
std::cin >> elem;
if (elem == x) {
vect_contains_x = true;
}
}
int num = 0;
if (!vect_contains_x) {
num = x;
}
else {
std::sort(vect.begin(), vect.end());
while (1) {
static int i = 1;
if (std::find(vect.begin(), vect.end(), x - i) == vect.end()) {
num = x - i;
break;
}
else if (std::find(vect.begin(), vect.end(), x + i) == vect.end()) {
num = x + i;
break;
}
else {
i += 1;
}
}
}
std::cout << num << "\n";
return 0;
}
This code renders the result in 13-18ms.
I was able to get it down to 8-10ms by using the following optimised code:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
int main() {
int x = 0;
int n = 0;
std::cin >> x >> n;
std::vector<decltype(x)> vect(n);
bool vect_contains_x = false;
for (auto& elem : vect) {
std::cin >> elem;
if (elem == x) {
vect_contains_x = true;
}
}
int num = 0;
if (!vect_contains_x) {
num = x;
}
else {
std::sort(vect.begin(), vect.end());
auto isPresent = [=](auto num) {
for (const auto& elem : vect) {
if (num == elem) {
return true;
}
}
return false;
};
while (1) {
static int i = 1;
if (!isPresent(x - i)) {
num = x - i;
break;
}
else if (!isPresent(x + i)) {
num = x + i;
break;
}
else {
i += 1;
}
}
}
std::cout << num << "\n";
return 0;
}
However, the problem with both the codes (as they both use the same approach) is that,
If there is a large continuous stream of integers in the given list, something like:
1,2,3,4,5,6,7,8,9,10,...,1501
and the X given is
751
The code will need 750 iterations of the for loop, which is a lot. Can we use a better algorithm to find the closest integer?
EDIT:
Got it down to 6ms by using binary_search (Thanks #Sebastian), but still, the algorithm remains the same...
You can see this "cheating" algorithm. It's cheating because the _Find_next method is only in the GCC compiler. Also, with the help of printf and scanf, I accelerated input and output, due to which the program runs faster. I sent it for execution several times and received 4, 6 and 8 ms (6 ms most often):
#include <bitset>
#include <algorithm>
using namespace std;
int main()
{
const int MAX_VALUES = 101;
bitset<MAX_VALUES> bits;
bitset<MAX_VALUES> reversed;
bits.flip();
reversed.flip();
int x, n, t;
scanf("%d %d", &x, &n);
if (n == 0) {
printf("%d", x);
exit(0);
}
for (int i = 0; i < n; i++) {
scanf("%d", &t);
bits.reset(t);
reversed.reset(MAX_VALUES - 1 - t);
}
if (bits[x]) {
printf("%d", x);
exit(0);
}
int rV = bits._Find_next(x);
int lV = MAX_VALUES - 1 - reversed._Find_next(MAX_VALUES - 1 - x);
int d1 = abs(rV - x);
int d2 = abs(lV - x);
if (d1 < d2) {
printf("%d", rV);
} else if (d2 < d1) {
printf("%d", lV);
} else {
printf("%d", min(rV, lV));
}
return 0;
}
I am not saying that this "algorithm" is better than yours. But, as I understand it, you asked for some other solutions, this is one of the possible.
According to your link, the total number of integers is at most 100.
So 100 bits are enough to hold the flags, which numbers appear in the sequence. Those can be held in the processor registers.
The following code shows only the storage, afterwords you would have to chose suitable bit scan operations:
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <limits>
#include <bitset>
using namespace std;
int main() {
bitset<100> flags;
int x = 0;
int n = 0;
int min = std::numeric_limits<int>::max();
int num = 0;
std::cin >> x >> n;
for (int i = 0; i < n; i++) {
int elem;
std::cin >> elem;
flags.set(elem);
}
// then you can shift the result by x bits and do bit scan operations
// there are built-ins depending on the compiler and processor architecture or the portable De Bruijn with multiplications
}
// alternatively (to the shift) you can use two bitsets, and for one set all the elements (elem - x) or for the other (x - elem)
I have a 1D char vector emulating a 2D vector (this is a requirement). This vector is 000111 and it's equivalent to vector[0] = 000 and vector[1] = 111 of a 2D. So it has two strings, all of same length (3 in this case). I want to set every string as a key in a std::unordered_map, so I am doing:
#include <iostream>
#include <unordered_map>
#include <string>
#include <vector>
int main ()
{
std::unordered_map<std::string, int> mymap;
std::vector<char> keys(2 * 3); // 2 keys, each one of length 3
for(int i = 0; i < 2; ++i)
{
for(int j = 0; j < 3; ++j)
{
keys[j + i * 3] = (i) ? '1' : '0';
}
}
// keys = 000111
for(int i = 0; i < 2; ++i)
{
mymap[std::string(keys.begin() + i * 3, keys.begin() + (i + 1) * 3)] = i;
}
for (auto& x: mymap) {
std::cout << x.first << ": " << x.second << std::endl;
}
/*
Output:
111: 1
000: 0
*/
return 0;
}
which makes me unhappy because I have to construct a new string and then insert that to the map. It would be nice if I could just emplace it or something in one step. Can I?
I think this is a drop-in replacement for a c++17 string_view. A string_view doesn't own any of the strings, so const-ness can be a problem (see the const-cast when inserting into the map)
The only changes that nedded to be made was
const-cast, you'll have to solve this.
the type of the multimap.
Note the using statement just at the #endif
I just bolted a class, a hash-struct(in std::!) and a few overloads onto your code.
#include <iostream>
#include <unordered_map>
#include <string>
#include <vector>
#ifdef HAS_STRING_VIEW
#include <string_view>
#else
class lps_noz_view{
public:
lps_noz_view() = delete;
lps_noz_view(const char* start, size_t size):start(start), stop(start + size){}
lps_noz_view(const lps_noz_view& ) = default;
lps_noz_view(lps_noz_view&& ) = default;
const char* begin(){ return start;}
const char* end(){ return stop;}
const char* begin() const{ return start;}
const char* end() const{ return stop;}
std::string to_string() const{ return std::string(start, stop);}
private:
const char* start;
const char* stop;
};
bool operator < (const lps_noz_view& lhs, const lps_noz_view& rhs){
return lhs.to_string() < rhs.to_string();
// or use strncmp to avoid creating strings =)
}
bool operator == (const lps_noz_view& lhs, const lps_noz_view& rhs){
return lhs.to_string() == rhs.to_string();
// strncmp
}
std::ostream& operator << (std::ostream& os, const lps_noz_view& rhs){
return os << rhs.to_string();
}
namespace std{
template<>
struct hash<lps_noz_view>
{
using argument_type = lps_noz_view;
using result_type = size_t;
size_t operator()(const lps_noz_view& arg) const{
return std::hash<std::string>()(std::string(arg.begin(), arg.end()));
}
};
};
using string_view = lps_noz_view;
#endif
//
int main ()
{
std::unordered_map<string_view, int> mymap;
std::vector<char> keys(2 * 3); // 2 keys, each one of length 3
for(int i = 0; i < 2; ++i)
{
for(int j = 0; j < 3; ++j)
{
keys[j + i * 3] = (i) ? '1' : '0';
}
}
// keys = 000111
for(int i = 0; i < 2; ++i)
{
mymap[string_view(const_cast<const char*>(&(*keys.begin()) + i * 3),
(i + 1) * 3)] = i;
}
for (auto& x: mymap) {
std::cout << x.first << ": " << x.second << std::endl;
}
/*
Output:
111: 1
000: 0
*/
return 0;
}
I want to write a function which will return amount of no repeating digits. So far I have written a function which is iterating through char and collecting to vector all number, but the problem comes when I have to get from vector only non repeating digits.
My code:
int norepeat(char *word){
int i = 0;
int size = 0;
vector<int> tab;
while (word[i] != '\0'){
if (word[i] >= '0' && word[i] <= '9') {
int num = word[i];
tab.push_back(num);
sort(tab.begin(),tab.end());
unique(tab.begin(),tab.end());
size = tab.size();
}
++i;
}
return size;
}
EDIT:
Several examples how should it work:
norepeat("de32ge2sa3ds1") => 1
norepeat("defegtdsg") => 0
norepeat("12341234") => 0
norepeat("1yle2le49") => 4
Create a map of digits -> digit count.
Then iterate through the map and count the number of digits that have a count of 1.
int norepeat(char *word){
int i = 0;
std::map<char, int> m;
while (word[i] != '\0'){
if ( isdigit(word[i] )
m[word[i]]++;
++i;
}
int count = 0;
for ( auto& p : m )
{
if ( p.second == 1 )
++count;
}
return count;
}
When working with a compiler that does not support C++11, the for loop can be changed to:
std::map<char, int>::iterator iter = m.begin();
std::map<char, int>::iterator end = m.end();
for ( ; iter != end; ++iter )
{
if ( iter->second == 1 )
++count;
}
Nice thing of C++ is the ability to mix Plain-Old-Data pointers and libc functions and algorithms from the C++ standard template library: (note: uses some C++11 features)
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <ctype.h>
using namespace std;
size_t norepeat(const char* word) {
vector<char> digits;
vector<char>::iterator uniq;
// Filter the digits
copy_if(word, word+strlen(word), back_inserter(digits), ::isdigit);
// get the unique ones
sort(digits.begin(), digits.end());
uniq = unique(digits.begin(), digits.end());
// return amount
size_t uniques = std::distance(digits.begin(), uniq);
size_t duplicates = std::distance(uniq, digits.end());
return uniques - duplicates;
}
int main( void ) {
cout << norepeat("hello 123 world 124") << endl;
cout << norepeat("hello world") << endl;
return 0;
}
Outputs:
2
0
EDIT
Just for laughs: wrote a counting-output-iterator-class; it counts occurrences of values copied into it into a map of value -> unsigned int. Combined with the count_if algorithm (with C++ lambdas) the norepeat function itself is only three statements: a variable declaration, filtering the digits and return the result of the counting:
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <ctype.h>
using namespace std;
template <typename T>
struct counter : public iterator<output_iterator_tag, T> {
typedef map<T, unsigned int> counter_type;
counter(counter_type* ptr) : mapptr( ptr ) {}
// decorate with dereference and assignment
counter<T>& operator=( const T& t ) {
mapptr->operator[]( t )++;
return *this;
}
counter<T>& operator++() { return *this; }
counter<T>& operator*() { return *this; }
counter_type* mapptr;
};
size_t norepeat(const char* word) {
typename counter<char>::counter_type countert;
// Filter the digits
copy_if(word, word+strlen(word), counter<char>(&countert), ::isdigit);
// Count the ones that have a value of one
return count_if(countert.begin(), countert.end(),
[](const counter<char>::counter_type::value_type& kv) {
return kv.second==1; } );
}
int main( void ) {
cout << norepeat("hello 123 world 124") << endl;
cout << norepeat("hello world") << endl;
return 0;
}
Since my last answer was based on a misreading of the question, How about this?
int norepeat(const char *word){
int i = 0;
int size = 0;
int arr[10] = {0}; // there are only 10 unique possibilities,
// so we'll mark them when found
while (word[i] != '\0')
{
if (std::isdigit(word[i]))
{
int num = word[i] - '0'; // get numeric value of digit to use as index
arr[num]++; // count the number of times we've seen this digit
}
++i;
}
for (i = 0; i < 10; i++)
{
if (arr[i] == 1) // count all element seen only once
{
size++;
}
}
return size;
}
This gag is really limited because it will only work for decimal digits, but with a slight modification it could do upper or lower case characters. With a std::map... The possibilities are limitless! I'll add that for completeness in a second.
EDIT
The map version.
int norepeat(const char *word){
int i = 0;
int size = 0;
std::map<char, int> counts;
while (word[i] != '\0')
{
if (std::isdigit(word[i])) // could use any or no filtering logic here
{
counts[word[i]]++;
}
++i;
}
for (auto &count: counts)
{
if (count.second == 1) // count all element seen only once
{
size++;
}
}
return size;
}
int norepeat(char *word){
int i = 0;
int size = 0;
vector<int> tab;
while (word[i] != '\0'){
if (word[i] >= '0' && word[i] <= '9') {
int num = word[i];
tab.push_back(num);
}
++i;
}
size = std::distance( unique(tab.begin(),tab.end()), tab.end() );
return size;
}
My code is in
#include <iostream>
#include <string>
#include <algorithm>
#include <climits>
#include <vector>
#include <cmath>
using namespace std;
struct State {
int v;
const State *rest;
void dump() const {
if(rest) {
cout << ' ' << v;
rest->dump();
} else {
cout << endl;
}
}
State() : v(0), rest(0) {}
State(int _v, const State &_rest) : v(_v), rest(&_rest) {}
};
void ss(int *ip, int *end, int target, const State &state) {
if(target < 0) return; // assuming we don't allow any negatives
if(ip==end && target==0) {
state.dump();
return;
}
if(ip==end)
return;
{ // without the first one
ss(ip+1, end, target, state);
}
{ // with the first one
int first = *ip;
ss(ip+1, end, target-first, State(first, state));
}
}
vector<int> get_primes(int N) {
int size = floor(0.5 * (N - 3)) + 1;
vector<int> primes;
primes.push_back(2);
vector<bool> is_prime(size, true);
for(long i = 0; i < size; ++i) {
if(is_prime[i]) {
int p = (i << 1) + 3;
primes.push_back(p);
// sieving from p^2, whose index is 2i^2 + 6i + 3
for (long j = ((i * i) << 1) + 6 * i + 3; j < size; j += p) {
is_prime[j] = false;
}
}
}
}
int main() {
int N;
cin >> N;
vector<int> primes = get_primes(N);
int a[primes.size()];
for (int i = 0; i < primes.size(); ++i) {
a[i] = primes[i];
}
int * start = &a[0];
int * end = start + sizeof(a) / sizeof(a[0]);
ss(start, end, N, State());
}
It takes one input N (int), and gets the vector of all prime numbers smaller than N.
Then, it finds the number of unique sets from the vector that adds up to N.
The get_primes(N) works, but the other one doesn't.
I borrowed the other code from
How to find all matching numbers, that sums to 'N' in a given array
Please help me.. I just want the number of unique sets.
You've forgotten to return primes; at the end of your get_primes() function.
I'm guessing the problem is:
vector<int> get_primes(int N) {
// ...
return primes; // missing this line
}
As-is, you're just writing some junk here:
vector<int> primes = get_primes(N);
it's undefined behavior - which in this case manifests itself as crashing.