Four digit random number without digit repetition - c++

Is there any way you can have a 4 digit number without repetition - e.g. not 1130 but 1234? I read std::random_shuffle could do this but it would only swap the numbers in between.
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <random>
unsigned seed = static_cast<size_t>(std::chrono::system_clock::now().time_since_epoch().count());
using namespace std;
class Player {
private:
string playername;
public:
void setName(string b) {
cout << "Please enter your name:" << endl;
getline(cin, b);
playername = b;
}
string getName () {
return playername;
}
};
class PasswordGuessingGame {
private:
std::mt19937 random_engine;
std::uniform_int_distribution<size_t> random_generator;
public:
PasswordGuessingGame():
random_engine(seed),
random_generator(1000,9999)
{
}
int getNumber () {
return random_generator(random_engine);
}
};
int main () {
Player newgame;
PasswordGuessingGame b;
newgame.setName("");
cout << newgame.getName() << " " << "password " << b.getNumber() << endl;
}

One possibility is to generate a string containing the digits, and to use the C++14 function std::experimental::sample()
#include <iostream>
#include <random>
#include <string>
#include <iterator>
#include <experimental/algorithm>
int main() {
std::string in = "0123456789", out;
do {
out="";
std::experimental::sample(in.begin(), in.end(), std::back_inserter(out), 4, std::mt19937{std::random_device{}()});
std::shuffle(out.begin(), out.end(), std::mt19937{std::random_device{}()});
} while (out[0]=='0');
std::cout << "random four-digit number with unique digits:" << out << '\n';
}
Edit:
Changed to prevent a result that starts with a 0. Hat tip to #Bathsheba who indicated that this could be a problem.

I think you need to generate each digit separately. For example you have array from 0 to 9 with 0..9 digits. For first digit you generate number from 0 to 9 and pick up digit from this array. Then you swap this array element t with last element of array. For second digit you generate number form 0 to 8. And so on.

I don't see a problem with std::random_shuffle:
#include <iostream>
#include <string>
#include <algorithm>
#include <random>
#include <chrono>
int main()
{
std::string s;
std::generate_n(std::back_inserter(s), 10,
[]() { static char c = '0'; return c++; });
// s is now "0123456789"
std::mt19937 gen(std::random_device{}());
// if 0 can't be the first digit
std::uniform_int_distribution<size_t> dist(1, 9);
std::swap(s[0], s[dist(gen)]);
// shuffle the remaining range
std::shuffle(s.begin() + 1, s.end(), gen); // non-deprecated version
// convert only first four
auto x = std::stoul(s.substr(0, 4));
std::cout << x << std::endl;
}
Live on Coliru

If you can count how many valid (i.e. acceptable) sequences exist, and you can devise a bijective function that maps from this counter to each valid sequence instance then things become trivial.
If I understand your example correctly, you want to generate a random 4 digit sequence ABCD (representing an integer in the range [0,9999]) where digits A, B, C and D are different from one another.
There are 5040 such valid sequences: 10 * 9 * 8 * 7.
Given any integer in the range [0, 5039], the following function will return a valid sequence (i.e. one in which each digit is unique), represented as an integer:
int counter2sequence(int u) {
int m = u/504;
u %= 504;
int h = u/56;
u %= 56;
int t = u/7;
u %= 7;
const int ih = h;
const int it = t;
if (ih >= m) ++h;
if (it >= ih) ++t;
if (t >= m) ++t;
if (u >= it) ++u;
if (u >= ih) ++u;
if (u >= m) ++u;
return ((m*10 + h)*10 + t)*10 + u;
}
E.g.
counter2sequence(0) => 0123
counter2sequence(5039) => 9876

Another method, using only standard data and numeric algorithms.
#include <random>
#include <array>
#include <iostream>
#include <numeric>
template<class Engine>
int unrepeated_digits(int ndigits, Engine &eng) {
std::array<int, 10> digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto add_digit = [](auto x, auto digit) {
return x * 10 + digit;
};
std::shuffle(std::begin(digits), std::end(digits), eng);
return std::accumulate(std::begin(digits), std::next(std::begin(digits), ndigits), 0, add_digit);
}
int main() {
std::random_device rnd;
std::default_random_engine eng(rnd());
for (int i = 0; i < 10; ++i)
std::cout << unrepeated_digits(4, eng) << std::endl;
}
example output:
7623
3860
9563
9150
3219
8652
4789
2457
1826
9745

Related

c++ conversion from decimal to binary

i am writing program for conversion of decimal to binary but answer i am getting is not correct i had checked it multiple times but couldn't make it.
`
#include<iostream>
#include<math.h>
using namespace std;
int decitobin(int n){
int ans=0;
int i=0;
while(n!=0){
int bit=n&1;
ans=((bit * pow(10,i))+ans);
n=n>>1;
i++;
}
return ans;
}
int main(){
int n;
cin>>n;
if(n<0){
n=n*(-1);
int newans=decitobin(n);
//1stcomp
newans=(~newans);
newans=newans+1;
cout<<newans<<endl;
}
else{
cout<<decitobin(n);
}
}
`
i am getting output
100 for 5,99 for 4
and -109 for -6
i had checked each line make it match with the solution but could not figure it out
Note in C++ there is an easier way (though that probably will not be what your teacher asked for)
#include <bitset>
#include <iostream>
int main()
{
std::size_t value{ 112ul };
std::bitset<8> bits{ value };
std::cout << bits;
return 0;
}
Another way of doing it in code without even needing base 10 logic.
Just to show you numbers in memory are already in binary format.
Often in dealing with binary data you will need masks and shift operations.
#include <array>
#include <iostream>
auto get_number_of_bits(int value)
{
std::size_t n{ 1ul };
value >>= 1;
while (value != 0)
{
++n;
value >>= 1;
}
return n;
}
// note value will already be a binary number in memory
// we just need to "walk" over all the bits and
// insert a '0' or '1' to the string
std::string to_bin(const int value)
{
// calculate the number of bits present in the number
const auto number_of_bits{ get_number_of_bits(value) };
// allocate a string to hold the correct/minimal number of bits in the output
std::string string(number_of_bits,0);
int mask{ 0x01 << (number_of_bits - 1ul) }; // select which bit we want from number
// loop over the bits
for (std::size_t n{ 0ul }; n < number_of_bits; ++n)
{
string[n] = (value & mask) ? '1' : '0'; // test if bit is set if so insert a 1 otherwise a 0
mask >>= 1;
}
return string;
}
int main()
{
std::cout << to_bin(5) << "\n";
std::cout << to_bin(12345) << "\n";
return 0;
}

Combining elements of an integer array into a single integer variable

I am writing a simple C++ program that should combine all elements of an integer array to form one number. Eg. {4,5,6} --> should be 456. But my output is one less than the original number. i.e instead of 456, I am getting 455. Sometimes my program works fine and sometimes not. Can someone please explain to me what is causing this unpredictible behaviour? Thank You!!
Please take a look at my code:
#include <bits/stdc++.h>
#include <cmath>
using namespace std;
int main()
{
int A[5] = {4,5,6,7,8};
int lengthA = 5;
int num = 0;
for(int x = 0; x < lengthA; x++)
{
num = A[x]*pow(10,lengthA-1-x) + num;
}
printf("%d\n", num ); // My O/P is 45677
}
As mentioned by Bob__, pow is a function for doubles and other floating-point types. For this specific algorithm, instead, we can do this:
int A[5] = {4,5,6,7,8};
int lengthA = 5;
int num = 0;
for(int x = 0; x < lengthA; x++)
{
num = num*10 + A[x];
}
At each step, this multiplies the previous number by 10, and makes the digit correct at that place.
E.g.
Step 1: num = 0*10 + 4 == 4
Step 2: num = 4 * 10 + 5 == 40 + 5 == 45
Step 3: num = 45 * 10 + 6 == 450 + 6 == 456
Step 4: num = 456 * 10 + 7 == 4560 + 7 == 4567
Step 5: num == 4567 * 10 + 8 == 45670 + 8 == 45678
From this simple problem you can already learn quite a bit to improve your C++ code.
Example :
// #include <bits/stdc++.h> // NO : https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h
// using namespace std // NO : https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
#include <iostream> // include only what you need for std::cout
int main()
{
int values[]{ 4,5,6,7,8 }; // no need for an =
int num{ 0 };
// prefer range based for loops
// they will not run out of bounds
// https://en.cppreference.com/w/cpp/language/range-for
for (const int value : values)
{
num *= 10;
num += value;
}
// avoid printf, use std::cout with C++20 std::format for formatting
// https://stackoverflow.com/questions/64042652/is-printf-unsafe-to-use-in-c
// https://en.cppreference.com/w/cpp/utility/format/format
std::cout << "num = " << num << "\n";
return 0;
}
Here is another way for this problem. You can use string to convert this numbers as you need.
With this loop, we convert each number to string and pase it to end of the num string. At the end, you have the number as you need as string. If you need that number as integer, you can conver it back at the end of the loop. To conver string to int you can check this :Converting String to Numbers
#include <iostream> //include to use cout
#include <string> // include to use string
using namespace std;
int main() {
int A[5] = {4,5,6,7,8}; // input array
int lengthA = sizeof(A) / sizeof(A[0]); // size of array
std::string num = "";
for(int i=0; i<lengthA; i++){
num += std::to_string(A[i]);
}
std::cout << "Number : " << num;
}
In addition to jh316's solution;
#include <iostream>
using namespace std;
int A[] = {4,5,6,7,8};
int num = 0;
int main()
{
for(int i: A){
num = num * 10 + i;
}
cout << num;
}
Description of the code:
Initial state of the variable: num = 0
For each iteration the num variable is:
1. num = 0 * 10 + 4 = 4
2. num = 4 * 10 + 5 = 45
3. num = 45 * 10 + 6 = 456
4. num = 456 * 10 + 7 = 4567
5. num = 4567 * 10 + 8 = 45678
Here when you call pow;
pow(10,lengthA-1-x)
your code is probably calling the following overload of std::pow:
double pow ( double base, int iexp );
And as can be seen, it returns a floating-point value which might have a rounding error. I ran your code on my system and the results were correct. However, your code might generate different results on different platforms. And it seems that this is the case in your system.
Instead, you can do this:
#include <cstdio>
#include <array>
#include <span>
constexpr int convertDigitsToNumber( const std::span<const int> digits )
{
int resultNum { };
for ( const auto digit : digits )
{
resultNum = resultNum * 10 + digit;
}
return resultNum;
}
int main( )
{
constexpr std::size_t arraySize { 5 };
// use std::array instead of raw arrays
constexpr std::array<int, arraySize> arrayOfDigits { 4, 5, 6, 7, 8 };
constexpr int num { convertDigitsToNumber( arrayOfDigits ) };
std::printf( "%d\n", num );
return 0;
}
As a result of using constexpr keyword, the above function will be evaluated at compile-time (whenever possible, which is the case in the above code).
Note regarding constexpr: Use const and constexpr keywords wherever possible. It's a very good practice. Read about it here constexpr (C++).
Note: If you are not familiar with std::span then check it out here.

Int from byte representation in vector c++

I have a vector<int> of length n which contains only 0 and 1's. For example we can have the following vector of length 10:
0 1 1 0 1 0 0 1 0 0
Now I use the number represented by that vector to access a location in an array with 2^n entries (so in this case an array of 2^10 = 1024). I'm not sure how I can obtain one integer from the byte representation stored in this vector<int>.
Simply run through the vector and collect powers of 2.
It depends on which end of the vector you want as most significant digit but e.g.
auto to_int( const vector<int>& digits )
-> int
{
int result = 0;
for( int const digit : digits )
{
result += 2*result + digit;
}
return result;
}
Or the other way,
auto to_int( const vector<int>& digits )
-> int
{
int result = 0;
for( int i = (int)digits.size(); i --> 0; )
{
result += 2*result + digits[i];
}
return result;
}
Disclaimer: code not reviewed by compiler.
use a std::bitset (http://en.cppreference.com/w/cpp/utility/bitset) which has a to_ulong() method
Something like this:
int integer=0;
int c=0;
for(int i : intVector){
integer+=i<<c;
c++;
}
return integer;
A simply way using a for loop:
size_t val{0};
for (const auto i : vec)
val = (val << 1) + i;
You can keep the std::vector and use std::bitset:
#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>
#include <climits>
template <typename IterType>
unsigned long getValue(IterType i1, IterType i2)
{
unsigned long i = 0;
std::bitset<CHAR_BIT * sizeof(unsigned long)> b;
std::for_each(i1, i2, [&](auto n) { b.set(i++, n);});
return b.to_ulong();
}
int main()
{
std::vector<int> v = {0, 1, 1, 0, 1, 0, 0, 1, 0, 0};
auto val = getValue(v.rbegin(), v.rend());
std::cout << val << "\n";;
auto val2 = getValue(v.begin(), v.end());
std::cout << val2;
}
Note that depending on which bit is the most significant bit, you supply the iterators accordingly. For right-to-left, supply reverse iterators, otherwise supply forward iterators.
Live Example

Using `transform` to create an increasing vector

I am trying to make an increasing vector using transform and must not be doing it correctly. I want to use transform. What am I doing wrong?
PS - I will be using the c++ 11 standard and g++.
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<double> x(10);
x.front() = 0.0;
double h = 0.1;
std::transform(x.begin(), x.end() - 1, x.begin() + 1, [h](unsigned int xn) {return xn + h;});
std::cout << x.at(3) << " " << x.at(9) << std::endl;
}
The conversion to unsigned int is truncating each value when it is used to calculate the next
std::transform - Using an unary operator
std::transform applies the given function to a range and stores the
result in another range, beginning at d_first.
Via std::transform and a closure you can initialize your std::vector:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<double> v(10);
const double step = 0.1;
std::transform(begin(v), end(v), begin(v),
[step](const double value) { return value + step; });
for (const auto value : v) {
std::cout << value << ' ';
}
}
std::generate - Increment via a callable
Assigns each element in range [first, last) a value generated by the
given function object
If you want a custom increment, you can use std::generate:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<double> v(10);
double seed = 0.0;
std::generate(begin(v), end(v), [&seed]() {
const auto ret = seed;
seed += 0.1;
return ret;
});
for (const auto value : v) {
std::cout << value << ' ';
} // outputs: 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
}
std::iota - Increment via ++value
Slightly off topic. You can provide a type with a operator++ for an increment of 0.1 but it is not intuitive for the reader.
You can use std::iota which relies on operator++.
Fills the range [first, last) with sequentially increasing values, starting with value and repetitively evaluating ++value.
The code in your case will be:
#include <numeric>
#include <iostream>
#include <vector>
int main() {
std::vector<double> v(10);
std::iota(begin(v), end(v), 0.0);
for (const auto value : v) {
std::cout << value << ' ';
} // outputs: 0 1 2 3 4 5 6 7 8 9
}
The lambda declares a wrong type of the parameter
[h](unsigned int xn) {return xn + h;});
^^^^^^^^^^^^^^^
There should be
[h]( double xn ) {return xn + h;});
^^^^^^^^^^^
Here are some other ways to write this. You may find them more expressive.
#include <vector>
#include <algorithm>
#include <numeric>
std::vector<double> create1(double i, double h)
{
std::vector<double> v(10);
std::generate(std::begin(v), std::end(v),
[&]() mutable
{
auto result = i;
i += h;
return i;
});
return v;
}
std::vector<double> create2(double i, double h)
{
std::vector<double> v(10);
for (std::size_t x = 0 ; v.size() ; ++x) {
v[x] = i + h * x;
}
return v;
}
std::vector<double> create3(double i, double h)
{
struct emitter
{
emitter& operator++() {
i += h;
}
operator double() const { return i; }
double i, h;
};
std::vector<double> v(10);
std::iota(v.begin(), v.end(), emitter { i, h });
return v;
}
int main()
{
auto v1 = create1(0, 0.1);
auto v2 = create2(0, 0.1);
auto v3 = create3(0, 0.1);
}
Regardless of any other problems it might have, your implementation has a subtle flaw: it relies on each preceding value in the vector having been already set.
This is not guaranteed to work, because std::transform() does not guarantee in-order application of the operator.

Convert vector<bool> to binary

I have a vector<bool> that contains 10 elements. How can I convert it to a binary type;
vector<bool> a={0,1,1,1,1,0,1,1,1,0}
I want to get binary values, something like this:
long long int x = convert2bin(s)
cout << "x = " << x << endl
x = 0b0111101110
Note: the size of vector will be change during run time, max size = 400.
0b is important, I want to use the gcc extension, or some literal type.
As I understood of comment
Yes it can even hold 400 values
And in question
0b is important
You need to have string, not int.
std::string convert2bin(const std::vector<bool>& v)
{
std::string out("0b");
out.reserve(v.size() + 2);
for (bool b : v)
{
out += b ? '1' : '0';
}
return i;
}
std::vector<bool> a = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 0 };
std::string s = "";
for (bool b : a)
{
s += std::to_string(b);
}
int result = std::stoi(s);
If you really want to do this, you start from the end. Although I support Marius Bancila and advise to use a bitset instead.
int mValue = 0
for(int i=a.size()-1, pos=0; i>=0; i--, pos++)
{
// Here we create the bitmask for this value
if(a[i] == 1)
{
mask = 1;
mask << pos;
myValue |= mask;
}
}
Your x is just an integer form from a, so can use std::accumulate like following
long long x = accumulate(a.begin(), a.end(), 0,
[](long long p, long long q)
{ return (p << 1) + q; }
);
For a 400 size, you need a std::string though
First of all the result of the conversion is not a literal. So you may not use prefix 0b applied to variable x.
Here is an example
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <vector>
#include <iterator>
#include <limits>
int main()
{
std::vector<bool> v = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 0 };
typedef std::vector<bool>::size_type size_type;
size_type n = std::min<size_type>( v.size(),
std::numeric_limits<long long>::digits + 1 );
long long x = std::accumulate( v.begin(), std::next( v.begin(), n ), 0ll,
[]( long long acc, int value )
{
return acc << 1 | value;
} );
for ( int i : v ) std::cout << i;
std::cout << std::endl;
std::cout << std::hex << x << std::endl;
return 0;
}
The output is
0111101110
1ee
vector<bool> is already a "binary" type.
Converting to an int is not possible for more bits than available in an int. However if you want to be able to print in that format, you can use a facet and attach it to the locale then imbue() before you print your vector<bool>. Ideally you will "store" the locale once.
I don't know the GNU extension for printing an int with 0b prefix but you can get your print facet to do that.
A simpler way is to create a "wrapper" for your vector<bool> and print that.
Although vector<bool> is always internally implemented as a "bitset" there is no public method to extract the raw data out nor necessarily a standard representation for it.
You can of course convert it to a different type by iterating through it, although I guess you may have been looking for something else?
If the number of bits is known in advance and by some reason you need to start from an std::array rather than from an std::bitset directly, consider this option (inspired by this book):
#include <sstream>
#include <iostream>
#include <bitset>
#include <array>
#include <iterator>
/**
* #brief Converts an array of bools to a bitset
* #tparam nBits the size of the array
* #param bits the array of bools
* #return a bitset with size nBits
* #see https://www.linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_192.html
*/
template <size_t nBits>
std::bitset<nBits> BitsToBitset(const std::array<bool, nBits> bits)
{
std::ostringstream oss;
std::copy(std::begin(bits), std::end(bits), std::ostream_iterator<bool>(oss, ""));
return std::bitset<nBits>(oss.str());
}
int main()
{
std::array<bool, 10> a = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 0 };
unsigned long int x = BitsToBitset(a).to_ulong();
std::cout << x << std::endl;
return x;
}