How to avoid constructing a new string? - c++

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;
}

Related

Convert integer to binary string with variable size

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);

How to construct a convenient iterator over blocks of Matrix using Eigen

I want to construct a "block-columnwise" iterator which runs over all possible blocks of of Dense Matrix with Eigen.
#include <iostream>
#include <Eigen/Dense>
int main() {
Eigen::MatrixXd A(4,4);
A << 1,2,3,4,
5,6,7,8,
9,10,11,12,
13,14,15,16;
for (Eigen::Index k=0; k< ? ; ++k) {
//?????
Eigen::Iterator it.... ;
std::cout<<it<<std::endl;
}
}
The output should be:
1 2
5 6
9 10
13 14
3 4
7 8
11 12
15 16
Essentially, I'm searching a nice version of
#include <iostream>
#include <Eigen/Dense>
int main() {
Eigen::MatrixXd A(4,4);
A << 1,2,3,4,
5,6,7,8,
9,10,11,12,
13,14,15,16;
int numberOfBlocksPerDir =2;
for (int i = 0; i < numberOfBlocksPerDir ; i++) {
for (int j = 0; j < numberOfBlocksPerDir ; j++) {
Eigen::Block<Eigen::MatrixXd, 2, 2> currentBlock = A.block<2, 2>(numberOfBlocksPerDir * j, numberOfBlocksPerDir * i);
std::cout<<currentBlock <<std::endl;
}
}
}
Is something like that possible using Eigen build-in functions? If not what would be a nice way to accomplish this on my own? ( Defining my own iterator?)
I couldn't find anything in the Eigen documentation, but a simple forward iterator doesn't need too much:
equality operators
increment operators
dereference operator
This is what I came up with
template <Eigen::Index RowSize, Eigen::Index ColSize>
struct EigenBlockIt {
using Self = EigenBlockIt<RowSize, ColSize>;
// constructors for end()/begin() equivalents
EigenBlockIt() : matrix(nullptr) , col(0), row(0) { }
EigenBlockIt(const Eigen::MatrixXd& matrix) : matrix(&matrix) , col(0), row(0) { }
// comparison
friend bool operator ==(const Self& lhs, const Self& rhs) {
return lhs.matrix == rhs.matrix && lhs.row == rhs.row && lhs.col == rhs.col;
}
friend bool operator !=(const Self& lhs, const Self& rhs) {
return lhs.matrix != rhs.matrix || lhs.row != rhs.row || lhs.col != rhs.col;
}
// increment (postfix/prefix)
Self& operator++() {
row++;
if (row >= matrix->rows() / RowSize) {
row = 0;
col++;
if (col >= matrix->cols() / ColSize) {
matrix = nullptr;
row = 0;
col = 0;
}
}
return *this;
}
Self operator++(int) {
EigenBlockIt it = *this;
++(*this);
return it;
}
// dereference
const Eigen::Block<const Eigen::MatrixXd, RowSize, ColSize> operator *() const {
return matrix->block<RowSize, ColSize>((matrix->rows() / RowSize) * row, (matrix->cols() / ColSize) * col);
}
const Eigen::MatrixXd* matrix;
Eigen::Index row;
Eigen::Index col;
};
Usage:
for (auto it = EigenBlockIt<2, 2>(A); it != EigenBlockIt<2, 2>(); ++it) {
std::cout << *it << std::endl;
}
Demo: https://godbolt.org/z/boz9xG

Pointers to keys of sparsepp: Does the location of the keys change?

In order to save memory (I need a map which is both sorted by values and by keys), I store pointers (well, actually iterators, according to the answer in this SO question) to the keys of a sparsepp in an std::vector and the sort the vector by the values of keys in the map:
size_t i = 0;
sorted_hashtable_pointer_.resize(hashtable_.size());
for (auto it = hashtable_.begin(); it != hashtable_.end(); it++)
{
sorted_hashtable_pointer_[i] = MapKeyPointer(it);
i++;
}
std::sort(sorted_hashtable_pointer_.begin(), sorted_hashtable_pointer_.end(),
[](MapKeyPointer a, MapKeyPointer b) { return *a < *b; });
where both hashtable_ and sorted_hashtable_pointer_ are members of a class.
This works well, just after the sorting (in the same method) I check whether the pointers (iterators) now point to the correct place and they do.
However, when I access the stored pointers (iterators) at a later point, they no longer point to the correct location. I didn't touch the hashtable_ in the meanwhile, but it looks like it has moved (most pointers still point to value locations, while some do not).
What am I doing wrong here? I, of course, do not insert / erase / ... to or from the map.
Edit: Here is a Minimal, Complete, and Verifiable example.
#include <sparsepp/spp.h>
#include <vector>
#include <stdint.h>
#include <algorithm>
#include <iostream>
struct MyHash {
size_t operator()(std::vector<uint8_t> vec) const
{
std::size_t seed = vec.size();
for(auto& i : vec) {
seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
};
struct MapKeyPointer
{
typedef spp::sparse_hash_map<std::vector<uint8_t>, std::vector<uint32_t>>::iterator iterator;
MapKeyPointer(iterator i) : it(i) {}
MapKeyPointer() {}
const std::vector<uint8_t>& operator*() const { return it->first; }
const std::vector<uint8_t>* operator->() const { return &it->first; }
iterator it;
};
class Test
{
public:
Test() : maps_(10), sorted_(10) {}
void Init()
{
for (uint32_t i = 0; i < 10; i++)
{
maps_[i] = spp::sparse_hash_map<std::vector<uint8_t>, int, MyHash>();
sorted_[i] = std::vector<MapKeyPointer>();
for (uint32_t j = 0; j < 10000; j++)
{
const std::vector<uint8_t> key
{
(uint8_t)(std::rand() % 255),
(uint8_t)(std::rand() % 255),
(uint8_t)(std::rand() % 255),
(uint8_t)(std::rand() % 255),
(uint8_t)(std::rand() % 255),
(uint8_t)(std::rand() % 255)
};
maps_[i][key] = std::rand();
}
}
}
void Sort()
{
for (size_t i = 0; i < 10; i++)
{
sorted_[i].resize(maps_[i].size());
size_t j = 0;
for (auto it = maps_[i].begin(); it != maps_[i].end(); it++)
{
sorted_[i][j] = MapKeyPointer(it);
j++;
}
std::sort(sorted_[i].begin(), sorted_[i].end(),
[](MapKeyPointer a, MapKeyPointer b) { return *a < *b; });
}
}
void Access()
{
for (size_t i = 0; i < 10; i++)
{
for (size_t j = 0; j < sorted_[i].size(); j++)
{
const std::vector<uint8_t> key = *sorted_[i][j];
std::cout << i << " " << j << " " << key.size() << std::endl;
}
}
}
private:
std::vector<spp::sparse_hash_map<std::vector<uint8_t>, int, MyHash>> maps_;
std::vector<std::vector<MapKeyPointer>> sorted_;
};
int main()
{
Test t;
t.Init();
t.Sort();
t.Access();
}

code crashes when using auto loop

I am sorting a vector using a swap function.
When I use the loop:
for (int i = 0; i < vec.size(); i++)
code runs fine but when I use:
for (auto const &i:vec)
it crashes!
Error in ./run': free(): invalid next size (fast): 0x0000000001df0c20
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <vector>
#include <array>
template <class T>
void myswap(T &a,
T &b)
{
T temp = a;
a = b;
b = temp;
}
int main() {
const int N = 5;
std::vector<int> vec = {112,32,11,4,7};
std::cout << "\nInit\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
int j;
for (auto const &i:vec)
//for (int i = 0; i < vec.size(); i++)
{
j = i;
while (j > 0 && vec[j] < vec[j-1])
{
myswap(vec[j], vec[j-1]);
j--;
}
}
std::cout << "\n\nFinal\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
std::cout << "\n";
return 0;
}
Answer already in the comments to the question (range based loop iterates over the values, not the indices), but for illustration, try this:
std::vector<std::vector<int>> v;
int j;
for(auto const& i : v)
{
j = v;
}
You will quickly discover that this piece of code does not compile – a good compiler will show you an error like this one (from GCC):
error: cannot convert 'std::vector<std::vector<int> >' to 'int' in assignment
What you now could do would be the following:
std::vector<std::vector<int>> v;
for(auto const& i : v)
{
std::vector<int> const& vv = v; // assign a reference
std::vector<int> vvv = v; // make a COPY(!)
}
Pretty self-explaining, isn't it?
it may be due to auto const try like this const auto and also you are using j in while loop instead of i you change it to j in while or change for(const auto &j:vec)
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <vector>
#include <array>
template <class T>
void myswap(T &a,
T &b)
{
T temp = a;
a = b;
b = temp;
}
int main() {
const int N = 5;
std::vector<int> vec = {112,32,11,4,7};
std::cout << "\nInit\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
int j;
for (const auto &j:vec)
//for (int j = 0; j < vec.size(); j++)
{
while (j > 0 && vec[j] < vec[j-1])
{
myswap(vec[j], vec[j-1]);
j--;
}
}
std::cout << "\n\nFinal\n";
for (const auto &i:vec)
{
std::cout << i << "\t";
}
std::cout << "\n";
return 0;
}
From the way you use swap, it is intended for j to represent a valid index of vec. Now i is not an index, but it is a value instead. When you assign j=i, then j contains 112 which is clearly out of bounds.
The way ranged loop works is that i takes the value vec[0], vec[1], vec[2] ... at each iteration.
Read here to learn about ranged loop.

How can I pass a substring by reference?

I call recursively a function passing as argument a substring which always starts from the beginning of the current string up to a position. If I was using C, I could pass the pointer to the first position of the string and then the necessary length. Nevertheless, I would like to achieve the same result using the class string. Is it possible? If I use const, is the compiler smart enough to make the optimization on its own? Even better, is there a way to check on my own whether the compiler actually makes a copy of the argument or passes a reference?
My question was motivated after having written the following code which passes the tests on problem Alphacode on poj, once someone uses atoi instead of atof.
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <string>
using namespace std;
map<string, int> cache;
bool valid_character_number(string a) {
return 0 < stoi(a.substr(a.size() - 2, 2)) && stoi(a.substr(a.size() - 2, 2)) <= 26;
}
bool zero_last_digit(string a) {
return a[a.size() - 1] == '0';
}
bool zero_before_last_digit(string a) {
return a[a.size() - 2] == '0';
}
int decodings(string a) {
if (a.size() == 0)
return 1;
if (a.size() == 1) {
if (zero_last_digit(a))
return 0;
else
return 1;
}
if (cache.find(a) != cache.end())
return cache[a];
if (zero_last_digit(a) && valid_character_number(a))
return cache[a] = decodings(a.substr(0, a.size() - 2));
else if (valid_character_number(a) && !zero_before_last_digit(a))
return cache[a] = decodings(a.substr(0, a.size() - 1)) + decodings(a.substr(0, a.size() - 2));
else
return cache[a] = decodings(a.substr(0, a.size() - 1));
}
int main() {
string input;
while (true) {
cin >> input;
if (input.size() == 1 && stoi(input) == 0)
return 0;
cout << decodings(input) << endl;
}
return 0;
}
You cannot use std::string for this purpose, but you can easily make a class of your own that holds a pair of iterators (begin and end) into another string, or a C-style char* and size. With C++11 (since you tagged it), you should even be able to make a User Defined Literal syntax for creating strings of your new type.
You can use your own wrapper class like this one:
struct RefString
{
RefString(const std::string & s, int i, int l) : s(s), i(i), l(l) {}
const char & operator [] (int x) const {
return s[i+x];
}
size_t length() const {
return l;
}
bool operator < (const RefString & s2) const {
return s.compare(i, l, s2.s, s2.i, s2.l) < 0;
}
private:
const std::string & s;
int i;
int l;
};
std::ostream & operator << (std::ostream &stream, const RefString & ms) {
for (int i = 0; i < ms.length(); i++)
stream << ms[i];
return stream;
}
And use it like this, for example for creating set of unique substrings:
std::string s = "hello";
std::set<RefString> st;
for (int i = 0; i < s.length(); i++)
for (int j = i; j < s.length(); j++)
st.insert(RefString(s, i, j-i+1));