The fastest way to generate a random permutation - c++

I need to permute N numbers between 0 and N-1 in the fastest way (on a CPU, without multi-threading, but maybe with SIMD). N is not large, I think in most cases, N<=12, so N! fits a signed 32-bit integer.
What I have tried so far is roughly the following (some optimizations are omitted, and my original code is in Java, but we speak performance in C++ if not pseudo-code):
#include <random>
#include <cstdint>
#include <iostream>
static inline uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
static uint64_t s[2];
uint64_t Next(void) {
const uint64_t s0 = s[0];
uint64_t s1 = s[1];
const uint64_t result = rotl(s0 + s1, 17) + s0;
s1 ^= s0;
s[0] = rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b
s[1] = rotl(s1, 28); // c
return result;
}
// Assume the array |dest| must have enough space for N items
void GenPerm(int* dest, const int N) {
for(int i=0; i<N; i++) {
dest[i] = i;
}
uint64_t random = Next();
for(int i=0; i+1<N; i++) {
const int ring = (N-i);
// I hope the compiler optimizes acquisition
// of the quotient and modulo for the same
// dividend and divisor pair into a single
// CPU instruction, at least in Java it does
const int pos = random % ring + i;
random /= ring;
const int t = dest[pos];
dest[pos] = dest[i];
dest[i] = t;
}
}
int main() {
std::random_device rd;
uint32_t* seed = reinterpret_cast<uint32_t*>(s);
for(int i=0; i<4; i++) {
seed[i] = rd();
}
int dest[20];
for(int i=0; i<10; i++) {
GenPerm(dest, 12);
for(int j=0; j<12; j++) {
std::cout << dest[j] << ' ';
}
std::cout << std::endl;
}
return 0;
}
The above is slow because the CPU's modulo operation (%) is slow. I could think of generating one random number between 0 and N!-1 (inclusive); this will reduce the number of modulo operations and Next() calls, but I don't know how to proceed then. Another approach could be to replace the division operation with multiplication by the inverse integer number at the cost of small bias in the modulos generated, but I don't these inverse integers and multiplication will probably not be much faster (bitwise operations & shifts should be faster).
Any more concrete ideas?
UPDATE: I've been asked why it's a bottleneck in the real application. So I just posted a task that may be of interest to the other folks. The real task in production is:
struct Item {
uint8_t is_free_; // 0 or 1
// ... other members ...
};
Item* PickItem(const int time) {
// hash-map lookup, non-empty arrays
std::vector<std::vector<Item*>>> &arrays = GetArrays(time);
Item* busy = nullptr;
for(int i=0; i<arrays.size(); i++) {
uint64_t random = Next();
for(int j=0; j+1<arrays[i].size(); j++) {
const int ring = (arrays[i].size()-j);
const int pos = random % ring + j;
random /= ring;
Item *cur = arrays[i][pos];
if(cur.is_free_) {
// Return a random free item from the first array
// where there is at least one free item
return cur;
}
arrays[i][pos] = arrays[i][j];
arrays[i][j] = cur;
}
Item* cur = arrays[i][arrays[i].size()-1];
if(cur.is_free_) {
return cur;
} else {
// Return the busy item in the last array if no free
// items are found
busy = cur;
}
}
return busy;
}

I came up with the following solution in C++ (though not very portable to Java, because Java doesn't allow parametrizing generics with a constant - in Java I had to use polymorphism, as well as a lot of code duplication):
#include <random>
#include <cstdint>
#include <iostream>
static inline uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
static uint64_t s[2];
uint64_t Next(void) {
const uint64_t s0 = s[0];
uint64_t s1 = s[1];
const uint64_t result = rotl(s0 + s1, 17) + s0;
s1 ^= s0;
s[0] = rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b
s[1] = rotl(s1, 28); // c
return result;
}
template<int N> void GenPermInner(int* dest, const uint64_t random) {
// Because N is a constant, the compiler can optimize the division
// by N with more lightweight operations like shifts and additions
const int pos = random % N;
const int t = dest[pos];
dest[pos] = dest[0];
dest[0] = t;
return GenPermInner<N-1>(dest+1, random / N);
}
template<> void GenPermInner<0>(int*, const uint64_t) {
return;
}
template<> void GenPermInner<1>(int*, const uint64_t) {
return;
}
// Assume the array |dest| must have enough space for N items
void GenPerm(int* dest, const int N) {
switch(N) {
case 0:
case 1:
return;
case 2:
return GenPermInner<2>(dest, Next());
case 3:
return GenPermInner<3>(dest, Next());
case 4:
return GenPermInner<4>(dest, Next());
case 5:
return GenPermInner<5>(dest, Next());
case 6:
return GenPermInner<6>(dest, Next());
case 7:
return GenPermInner<7>(dest, Next());
case 8:
return GenPermInner<8>(dest, Next());
case 9:
return GenPermInner<9>(dest, Next());
case 10:
return GenPermInner<10>(dest, Next());
case 11:
return GenPermInner<11>(dest, Next());
case 12:
return GenPermInner<12>(dest, Next());
// You can continue with larger numbers, so long as (N!-1) fits 64 bits
default: {
const uint64_t random = Next();
const int pos = random % N;
const int t = dest[pos];
dest[pos] = dest[0];
dest[0] = t;
return GenPerm(dest+1, N-1);
}
}
}
int main() {
std::random_device rd;
uint32_t* seed = reinterpret_cast<uint32_t*>(s);
for(int i=0; i<4; i++) {
seed[i] = rd();
}
int dest[20];
const int N = 12;
// No need to init again and again
for(int j=0; j<N; j++) {
dest[j] =j;
}
for(int i=0; i<10; i++) {
GenPerm(dest, N);
// Or, if you know N at compile-time, call directly
// GenPermInner<N>(dest, Next());
for(int j=0; j<N; j++) {
std::cout << dest[j] << ' ';
}
std::cout << std::endl;
}
return 0;
}

Related

Calculating function and writing output number by number as an array

So, what I basically need is to calculate value of an exponential function (2^n)*(2^(n-1)-1) using c++, where n is a unsigned int type user input. Since n can be assigned any value in unsigned int range, I cannot simply calculate function value and assign it to some unsigned int variable (because resulting number will clearly be out of said range). Therefore, it seems reasonable to me to somehow get my desired function value number by number and write each number as a array element. The only struggle is to realise this method.
Any ideas (both using proposed method or any other one) would be much appreciated.
edit:
Right now I have the following code:
outdated
As expected, it will only work with small values of n
Edit 2: as one of the commentators suggested, I've done some binary numbers by hand. It was pretty fruitful, but I still need sime assistance. Now i have the following code, which will correctly output binary value of said function:
outdated
The only thing left is to convert this value to decimal and hexadecimal. I am not experienced at working with string class, so advice would be appreciated.
Edit 3: Thanks everyone for help. I've completed my program and converted it co C (not willingly, because my professor told me to do so). For anyone interested, the current version of code looks like that:
#include <stdio.h>
#include <stdlib.h>
void binary(unsigned int);
void hex(unsigned int);
void decimal(unsigned int);
int *calculatepower(unsigned int, unsigned int);
void addition(int*, int*, int);
int main(int argc, char** argv){
if (argc != 2){
printf("wrong number of arguments \n");
return -2;
}
unsigned int n = atoi(argv[1]);
printf("exponent - %d \n", n);
binary(n);
hex(n);
decimal(n);
return 0;
}
void binary(unsigned int n){
int i;
printf("binary - ");
for (i=n-1; i>0; i--)
printf("1");
for (i=n; i>0; i--)
printf("0");
printf("\n");
}
void hex(unsigned int nn){
int ones = nn-1;
int zeroes = nn;
int hexzeroes=0, hexfs=0, i;
char switchf, switchzero;
while (zeroes > 3){
hexzeroes+=1;
zeroes-=4;
}
switch (zeroes){
case 0:
break;
case 1:
switchzero='E';
ones-=3;
break;
case 2:
switchzero='C';
ones-=2;
break;
case 3:
switchzero='8';
ones-=1;
break;
default:
break;
}
while (ones>3){
hexfs+=1;
ones-=4;
}
switch (ones){
case 0:
switchf='\0';
break;
case 1:
switchf='1';
break;
case 2:
switchf='3';
break;
case 3:
switchf='7';
break;
default:
break;
}
printf("hexadecimal - %c", switchf);
for (i=0; i<hexfs; i++)
printf("F");
if (zeroes !=0) printf("%c", switchzero);
for (i=0; i<hexzeroes; i++)
printf("0");
printf("\n");
}
void decimal(unsigned int nn){
unsigned int n=nn;
int *str,*powerstr, i, flag=0;
// decimal = 2^n+...+2^((2*n)-1)
unsigned int size = (2*n)/3 + 2;
str = (int*)calloc(size, sizeof(*str));
if(str==NULL)
{
printf("unable to allocate memory");
exit(0);
}
for (i=0; i<size; i++)
{
str[i] = 0;
}
for (n;n<2*nn-1;n++){
powerstr = calculatepower( n, size);
addition(str,powerstr,size);
}
printf("decimal - ");
for (i=0;i<size;i++) {
if ((*(str+i)==0) && (flag==0)){
continue;
}
printf("%d", *(str+i));
flag+=1;
}
}
int *calculatepower(unsigned int n, unsigned int size){
int i, j, buf=0, *powerstr;
powerstr = (int*)calloc(size, sizeof(*powerstr));
for (i=0; i<size; i++)
{
powerstr[i] = 0;
}
powerstr[size-1]=1;
for(j=0;j<n;j++) {
for (i=size-1; i > -1; i--) {
powerstr[i] = powerstr[i] * 2;
if (buf!=0) {
powerstr[i] += 1;
buf=0;
}
if (powerstr[i] > 9) {
buf = 1;
powerstr[i]%=10;
}
}
}
return powerstr;
}
void addition(int *str, int *powerstr, int size){
int i, buf=0;
for (i=size-1; i > -1; i--) {
str[i] = powerstr[i] + str[i];
if (buf!=0) {
str[i] += 1;
buf=0;
}
if (str[i] > 9) {
buf = 1;
str[i]%=10;
}
}
}
Unfortunately, I do not have enough time to polish it. The current biggest problem is not freeing allocated memory and I will fix it later, but I won't update queastion anymore. Thanks again everyone for your answers and comments.
For 16 bit ints it's doable and produces about 40k decimal chars. For 32 bit ints, not so much as it's about 10^20 decimal chars which is beyond anything possible. Even outputting a million chars per second would take longer than the lifetime of the universe.
Here's code for 16 bit ints. Runs in about 3 seconds for n = 65535 not including output time. It has performance improvements by accumulating base 10 sums and normalizing occasionally to prevent overflow.
#include <iostream>
#include <vector>
#include <string>
#include <cstdint>
using std::cout;
using std::vector;
using std::string;
struct BigDecPower2 {
static constexpr uint32_t Normalize_Max{ 26 }; // int8:3, int16:10, int32:26
vector<uint32_t> v;
uint32_t top;
uint32_t normalize_count;
BigDecPower2(uint32_t n) : v(n), top(0), normalize_count(0) {};
void normalize()
{
normalize_count = 0;
for (uint32_t i = 0;; i++)
{
v[i + 1] += v[i] / 10u;
v[i] = v[i] % 10u;
if (i >= top && v[i + 1] == 0)
{
top = i;
return;
}
}
}
void times2() {
for (uint32_t i = 0; i <= top; i++)
v[i] *= 2;
if ((++normalize_count) > Normalize_Max)
normalize();
}
};
void add(BigDecPower2& v1, const BigDecPower2& v2)
{
uint32_t max_top = v1.top > v2.top ? v1.top : v2.top;
for (uint32_t i = 0; i <= max_top; i++)
v1.v[i] += v2.v[i];
if (++v1.normalize_count < v2.normalize_count)
v1.normalize_count = v2.normalize_count;
if (v1.normalize_count > v1.Normalize_Max)
v1.normalize();
}
void print_base(unsigned int n, int number_base)
{
int64_t ones = n-1;
int64_t zeros = n;
if (number_base ==2)
{
while (ones-- > 0)
cout << '1';
while (zeros-- > 0)
cout << '0';
}
else if (number_base == 16) {
int resid = (ones + zeros) % 4;
if (resid == 0)
resid = 4;
cout << "~137F"[resid];
ones -= resid;
while ((ones -= 4) > 0)
cout << 'F';
cout << "8CEF"[ones + 3];
zeros /= 4;
while (zeros--)
cout << '0';
}
else if (number_base == 10)
{
BigDecPower2 v_accum(40000u);
BigDecPower2 v_pwr(40000u); v_pwr.v[0] = 1;
for (uint32_t i = 0; i < n - 1; i++)
{
add(v_accum, v_pwr);
v_pwr.times2();
}
for (uint32_t i = 0; i < n; i++)
v_accum.times2();
v_accum.normalize();
for (uint32_t i = v_accum.top; i != -1; i--)
cout << static_cast<char>(v_accum.v[i] + '0');
}
cout << '\n';
}
int main()
{
// calcs in about 3 seconds, outputs about 40k decimal chars
// print_base(0xffff, 10);
// Demo
for (int i = 1; i < 10; i++)
{
print_base(i, 2);
print_base(i, 16);
print_base(i, 10);
cout << '\n';
}
}
You can use unsigned long or unsigned long long (or uintX_t where X is the maximum supported size on your platform) if unsigned int cannot hold your output. If that's still not enough for your use case, then either implement your own big integer class, or use an existing library (recommended if you can afford it). There are a couple of them out there. For example, GNU Multiple Precision Arithmetic Library (GMP) and bigint-library. See this list for more.
In case you decided to go on your own and implement your own class, this might give you some clues on how to start. (Note that, for efficiency matters, number theory algorithms may be applied. It is not an easy task to come with a good implementation).
template<typename T = unsigned, int Base = 10> class Bigint {
std::vector<T> digits;
bool sign; // For e.g. true for + or 0, false for -
public:
Bigint() : digits(), sign(true) { }
Bigint(int x)
{
// Insert digits of x into digits vector
// Don't forget the sign
}
// Do the same with other types: short, long, unsigned, etc.
Bigint(const char *x)
{
// You need to parse x. Bad formatting is to be handled (tip: use exceptions)
}
// Provide an std::string version
Bigint(const Bigint& bi) : digits(bi.digits), sign(bi.sign) {}
Bigint& operator=(const Bigint& bi)
{
// Copy...
return *this;
}
// You also have to implement operators
Bigint& operator+(const Bigint& bi)
{
// Logic...
return *this;
}
// Other operators: -, /, %, bitwise, etc.
// Tip: you can use a helper class to be used by both / and % since they share a similar logic (for avoiding redundant code).
Bigint power(const Bigint& bi) // Provide other signatures: int, string, etc.
{
// Logic...
}
};

how to solve possible unique combinations problem

I need a combination algorithm for large numbers. I found something on StackOverflow but the implementation was not totally correct. The code below runs wrong if the size of the vector is larger than 22-24 and k is higher.
#include <bits/stdc++.h>
using namespace std;
template<typename T>
void pretty_print(const T& c, int combo)
{
int n = c.size();
for (int i = 0; i < n; ++i) {
if ((combo >> i) & 1)
cout << c[i] << ' ';
}
cout << endl;
}
template<typename T>
void combo(const T& c, int k)
{
int n = c.size();
int combo = (1 << k) - 1; // k bit sets
while (combo < 1<<n) {
pretty_print(c, combo);
int x = combo & -combo;
int y = combo + x;
int z = (combo & ~y);
combo = z / x;
combo >>= 1;
combo |= y;
}
}
int main()
{
vector<char> c0 = {'1', '2', '3', '4', '5'};
combo(c0, 3);
vector<char> c1 = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
combo(c1, 4);
return 0;
}
This is taken from Creating all possible k combinations of n items in C++
Now, I'm using std::prev_permutation, it works but too slow for my analysis program. There are more than one thousand of combinations in my program. So that I wanted to use the algorithm above. How can ı fix this algorithm to work under all circumstances?
Thank you, in advance.
The reason it would fail is because the original algorithm you were posting was utilizing some bit wise calculation. It is actually consider each bit of a int type as a different number. And depending on the int defined by your compiler, you might be limited to a maximum n of either 32 or 64. You could also change all the int declaration to int64_t to force them to be defined in 64 bit.
However, doing that would still capped your maximum n to 64. (In fact, it is capped to the bit size - 2 or 62 or 30, so not entirely sure why you got stuck around 23) The real solution is to change all the int to std::bitset so that it could store a maximum n of SIZE_MAX.
Code as below:
#include <iostream>
#include <vector>
#include <bitset>
template<size_t bitSize>
void pretty_print(const std::vector<std::bitset<bitSize>>& c, std::bitset<bitSize> combo)
{
int n = c.size();
for (int i = 0; i < n; ++i) {
if (((combo >> i) & std::bitset < bitSize>(1)) != std::bitset <bitSize>(0))
std::cout << c[i].to_ullong() << ' ';
}
std::cout << std::endl;
}
template<size_t bitSize>
bool smallerThan(std::bitset<bitSize> bits1, std::bitset<bitSize> bits2)
{
for (size_t i = bitSize - 1; i > 0; i--)
{
if (bits1[i] < bits2[i])
{
return true;
}
}
return false;
}
template<size_t bitSize>
std::bitset<bitSize> bitAddition(std::bitset<bitSize> bits1, std::bitset<bitSize> bits2)
{
std::bitset<bitSize> carry;
while (bits2 != std::bitset<bitSize>(0))
{
carry = bits1 & bits2;
bits1 = bits1 ^ bits2;
bits2 = carry << 1;
}
return bits1;
}
template<size_t bitSize>
std::bitset<bitSize> bitSubtraction(std::bitset<bitSize> bits1, std::bitset<bitSize> bits2)
{
while (bits2 != std::bitset<bitSize>(0))
{
std::bitset<bitSize> borrow = (~bits1) & bits2;
bits1 = bits1 ^ bits2;
bits2 = borrow << 1;
}
return bits1;
}
template<size_t bitSize>
std::bitset<bitSize> bitSubtractionStopAt0(std::bitset<bitSize> bits1, std::bitset<bitSize> bits2)
{
while (bits2 != std::bitset<bitSize>(0))
{
std::bitset<bitSize> borrow = (~bits1) & bits2;
bits1 = bits1 ^ bits2;
bits2 = borrow << 1;
if (bits1 == std::bitset<bitSize>(0)) return bits1;
}
return bits1;
}
template<size_t bitSize>
std::bitset<bitSize> bitDivision(std::bitset<bitSize> dividend, std::bitset<bitSize> divisor)
{
std::bitset<bitSize> quotient(0);
while (smallerThan(std::bitset<bitSize>(0), dividend))
{
dividend = bitSubtractionStopAt0(dividend, divisor);
quotient = bitAddition(quotient, std::bitset<bitSize>(1));
}
return quotient;
}
template<size_t bitSize>
void combo(const std::vector<std::bitset<bitSize>>& c, int k)
{
auto n = c.size();
std::bitset<bitSize> one(1);
std::bitset<bitSize> combo(bitSubtraction((one << k), std::bitset<bitSize>(1)));
while (smallerThan(combo, (one << n)))
{
pretty_print(c, combo);
auto negCombo = combo;
negCombo.flip();
for (size_t i = 0; i < bitSize; i++)
{
negCombo.flip(i);
if (negCombo[i])
{
break;
}
}
std::bitset<bitSize> x = combo & negCombo;
std::bitset<bitSize> y;
bool tempBit = 0;
for (size_t i = 0; i < bitSize; i++)
{
y[i] = combo[i] ^ x[i];
if (tempBit)
{
if (!y[i])
{
tempBit = 0;
}
y[i] = y[i] ^ 1;
}
if (combo[i] & x[i])
{
tempBit = 1;
}
}
std::bitset<bitSize> z = (combo & ~y);
combo = bitDivision(z, x);
combo >>= 1;
combo |= y;
}
}
int main()
{
const int n = 500;
int k = 2;
std::bitset<(n + 2)> n_bits(n);
std::vector<std::bitset<n + 2>> people;
for (unsigned long i = 1; i < n_bits.to_ullong() + 1; ++i) { people.push_back(i); }
combo(people, k);
return 0;
}
I've only tested 90C4 and 500C2, but this should work for all n smaller than SIZE_MAX. Also I believe there are ways to optimize the bitwise calculations I've used better, not an expert on it.
Another approach is probably use a larger number type, such as int128_t or int1024_t. However, you would also need to overload some bitwise calculation.
Also you mentioned that:
For example there is a vector of {30,30,30,30,30,30,30,30,60,60,60,60,60,60,60,60,90,90,90,90,90,90,90,90}, when you try to find combination of this vector by 8, it does not do it correctly.
The way this algorithm work, it does not check the value of each members. Instead it automatically assume all members are unique. Similar to what a real nCr function would do.
Also some of the other method's mentioned in Creating all possible k combinations of n items in C++ are quite fast as well, especially since I can't find a good way of implementing bitwise calculation yet D: I guess you could have some data structure to separate the number as several bitset<63> object, so you could cast them to unsigned long long to use its bitwise operators. However not sure if that would run faster.
Either way if you are doing nCk ≈ thousands, then the difference for all those methods should be neglectable.

MayI know why this code is not giving any output?

Please help me to solve the query that this code runs infinitely at a particular line.
It does not give any output as at the end of the code I write the code to print the vector. Even after I assign any value to vector "result" manually still it is not giving any output. why is it so?
#include<bits/stdc++.h>
using namespace std;
bool authorize(int strValue, int value, int M)
{
long int newValue = (strValue - (value * 131) % M);
if (newValue >= 48 && newValue <= 57)
return true;
if (newValue > 65 && newValue <= 90)
return true;
if (newValue >= 97 && newValue <= 122)
return true;
return false;
}
int hashingfunct(string str, int M)
{
long int P, F, sum = 0;
int len = str.length();
for (int i = 0; i < len; i++)
{
P = pow(131, len - i - 1);
F = (int)str[i];
sum += (F * P) % M;
}
sum = sum % M;
return sum;
}
int main()
{
int n = 5;
string str1, str2;
vector<vector<string> > events;
for (int i = 0; i < n; i++) {
cin >> str1 >> str2;
vector<string > temp;
temp.push_back(str1);
temp.push_back(str2);
events.push_back(temp);
}
for (int i = 0; i < n; i++) {
cout << events[i][0] << events[i][1];
}
/*
INPUT FORMAT:
setpassword 1
setpassword 2
setpassword 3
authorize 49
authorize 50
*/
vector<int> result;
int j = 0;
long int m = pow(10, 9);
long int M = m + 7;
long int value, strValue;
for (int i = 0; i < events.size(); i++)
{
strValue = stoi(events[i][1]);
if (events[i][0] == "setPassword") {
value = hashingfunct(events[i][1], M);
}
else if (strValue == value)
result[j++] = 1;
else if (authorize(strValue, value, M))
result[j++] = 1;
else
result[j++] = 0;
}
for (int i = 0; i < result.size(); i++) {
cout << result[i];
}
}
Your program has complete Undefined Behaviour.
Let's get started with the first problem. In the following check code
long int value, strValue; // not initialised
for (int i = 0; i < events.size(); i++)
{
// ...
// here it should have been "setpassword" (i.e. all are small letters)
if (events[i][0] == "setPassword")
{
// if the check fails the `value` never get initialised!
value = hashingfunct(events[i][1], M);
}
// If the `value` not been initialised, check happens with any garbage value here!
else if (strValue == value)
// ...other code
}
You are checking whether the string is "setPassword" instead of "setpassword" (i.e. see in the events vector, all the strings are small letters).
If that goes wrong, the value will never get initialized, meaning it holds any garbage value and hence conducting this check else if (strValue == value) can cause any behaviour to your program (aka Undefined Behaviour).
Secondly, the vector<int> result; is empty at the beginning. Therefore accessing elements via std::vector::operator[] later
result[j++] = 1;
// ...
result[j++] = 1;
// ...
result[j++] = 0;
triggers the access out of bounds (UB). There you need just result.emplace_back(/*value*/); or result.push_back(/*value*/);, and no need of redutant variable j.
In short, you need
#include <iostream>
#include <vector>
#include <string>
// ..other functions
int main()
{
std::vector<std::vector<std::string> > events {
{"setpassword", "1"}, // can be also user input, like in your example
{"setpassword", "2"},
{"setpassword", "3"},
{"authorize", "49" },
{"authorize", "50" }
};
std::vector<int> result;
const long int M = pow(10, 9) + 7;
long int value{ 0 }, strValue{ 0 }; // default initialization
for (const std::vector<std::string> row: events) // better use range-based loop
{
strValue = std::stoi(row[1]);
if (row[0] == "setpassword") {
value = hashingfunct(row[1], M);
if (strValue == value)
result.emplace_back(1);
else if (authorize(strValue, value, M))
result.emplace_back(1);
}
else
result.emplace_back(0);
}
}
As a side note,
Please do not use using namespacestd;
Why should I not #include <bits/stdc++.h>?
Corrected code
#include<bits/stdc++.h>
using namespace std;
bool authorize(long int strValue,long int value,int M){
long int value1=value*131;
long int newValue=(strValue-(value1%M))%M;
if(newValue>=48 && newValue<=57)
return true;
if(newValue>=65 && newValue<=90)
return true;
if(newValue>=97 && newValue<=122)
return true;
return false;
}
int hashingfunct(string str,int M){
long int P,F,sum=0;
int len=str.length();
for(int i=0;i<len;i++){
P=pow(131,len-i-1);
F=(int)str[i];
sum+=(F*P)%M;
}
sum=sum%M;
return sum;
}
int main(){
int n=5;
string str1,str2;
vector<vector<string> > events;
for (int i=0;i<n;i++){
cin>>str1>>str2;
vector<string > temp;
temp.push_back(str1);
temp.push_back(str2);
events.push_back(temp);
}
/*
setPassword cAr1
authorize 223691457
authorize 303580761
setPassword d
authorize 100
*/
vector<int> result;
int j=0;
long int m=pow(10,9);
long int M=m+7;
long int value,strValue;
for(int i=0;i<events.size();i++){
if(events[i][0]=="setPassword"){
value=hashingfunct(events[i][1],M);
continue;
}
strValue=stoi(events[i][1]);
if(strValue==value)
result.push_back(1);
else if(authorize(strValue,value,M))
result.push_back(1);
else
result.push_back(0);
}
for(int i=0;i<result.size();i++){
cout<<result[i];
}
}

Can't understand why my program throws error

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.

Rolling dice for an array

What I need this program to do is roll 36000 2d6, output the results of each value and how often it occurs in a table format. Unfortunately I'm unfamiliar with how arrays work. This is what I have so far:
int DiceArray()
{
int rollOne = 0;
int rollTwo = 0;
int countrolls = 0;
int sum = 0;
for (countrolls=1; countrolls<=36000; countrolls++)
{
rollOne = (rand() % 6) + 1;
rollTwo = (rand() % 6) + 1;
sum = rollOne+rollTwo;
}
}
So, I need an array for the dice results which I'm guessing is gonna look like result[11] because it lists 2 through 12 for the sum of the dice. Then I'm gonna have to make the array multidimensional; I'll need a second column for the results.
So, for instance, the result of two would occur we'll say 700 times. So I'd need something like outcome[2]. Is that right? And how would I get the right values for my array, anyways?
I suppose for the result array I just list them like so since they'll always be the same: {2, 3, 4,... 12}
But how do I output my sum to array?
Not sure, what you're asking, but it seems like you need a simple histogram. Like this:
void DiceArray()
{
int rollOne = 0;
int rollTwo = 0;
int sum = 0;
// This array holds histogram. hist[0] and hist[1] are always zero.
int hist[13] = { 0 };
for (int countrolls = 0; countrolls < 36000; ++countrolls)
{
rollOne = (rand() % 6) + 1;
rollTwo = (rand() % 6) + 1;
sum = rollOne+rollTwo;
hist[sum]++;
}
for (int i = 2; i <= 12; ++i)
{
std::cout << i << ": " << hist[i] << std::endl;
}
}
This function prints the following:
2: 949
3: 1974
4: 2898
5: 3987
6: 5133
7: 6088
8: 4944
9: 3976
10: 3075
11: 1991
12: 985
Something like this should work:
#include <iostream>
#include <random>
#include <array>
std::array<std::size_t, 13> DiceArray(const std::size_t count)
{
std::random_device device;
std::mt19937 engine(device());
std::uniform_int_distribution<std::size_t> distribution(1, 6);
std::array<std::size_t, 13> result = {};
for (std::size_t i = 0; i < count; ++i) {
++result[distribution(engine)+distribution(engine)];
}
return result;
}
int main(int argc, char* argv[])
{
auto result = DiceArray(36000);
for (std::size_t i = 0; i < result.size(); ++i) {
std::cout<<i<<" "<<result[i]<<std::endl;
}
return 0;
}
Your idea of result[11]; would work. You would have to zero-initialize it too.
int result[11] = {0};
Keep in mind that arrays are zero-based. So this array would cover the range of 0-10. You can work with that by subtracting off the minimum dice roll. Increment the corresponding array location for each roll in your loop:
++result[sum-2];
Accessing the value again requires subtracting the minimum dice roll:
int numTwos = result[2-2];
int numTens = result[10-2];
This is a C++11 answer. Based off this stack overflow answer
typedef std::mt19937 MyRNG; // the Mersenne Twister with a popular choice of parameters
std::vector< unsigned > DiceArray(
unsigned how_many_rolls, unsigned dice_count,
MyRNG& rng
)
{
// d6!
std::uniform_int_distribution<uint32_t> d6(1,6);
std::vector< unsigned > retval;
retval.resize( dice_count * 6+1 );
for (unsigned count = 0; count < how_many_rolls; ++count)
{
unsigned sum = 0;
for(unsigned i = 0; i < dice_count; ++i) {
sum += d6(rng);
}
retval[sum] += 1;
}
return retval;
}
And next we use it:
int main(int argc, char* argv[])
{
MyRNG rng;
uint32_t seed_val = 0; // populate somehow -- as `0` it will replicate the same sequence each time. A common trick is to grab the current time or some other source of entropy
rng.seed(seed_val); // avoid calling this more than once per experiment. It resets the RNG, if you call it again it will repeat the same sequence of numbers as the first time.
std::vector<unsigned> result = DiceArray(36000, 2, rng);
for (unsigned i = 0; i < result.size(); ++i) {
std::cout << i <<": " << result[i] << "\n";
}
}