How to bind numbers together into an integer without addition? - c++

For example:
If I end up with multiple digits and all of those numbers are generated randomly (1-9) up to 7 digits total and I want them all to end up as a whole integer, how do I go by doing this?
Here is something I have tried:
static void generate_key(std::map<std::string, int>& key, std::string c_user)
{
unsigned int hold[7]{}; // will hold all the random integers seperate to add onto final
int *final = new int; // will store a complete 7 digit integer here later on
for (int i = 0; i < 7; i++)
{
unsigned int num = rand() % 9;
hold[i] = num;
}
*final = hold[0] + hold[1] + hold[2] + hold[3]; // I know this sums everything but how do I get it to just add all the numbers into a single integer?!
key.emplace(c_user, final);
std::cout << "Key created: " << *final << '\n';
delete final;
}
Hold all integers seperate from eachother:
unsigned int hold[7]{};
Create random digits:
for (int i = 0; i < 7; i++)
{
unsigned int num = rand() % 9;
hold[i] = num;
}
Store and add all integers into *final integer
int *final = new int;
I want to generate a 7 digit key and each of every single digit is randomized. I then want to add them all up to make a whole integer that gets put into a map where a string has already been created and that key will represent the string. Do you get what I'm saying here? Sorry if my explanation is terrible I'm just too lost here..
Here is the full code if thats helpful:
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <stdlib.h>
class Account
{
private:
std::string username;
std::string password;
public:
Account(std::string username, std::string password)
{
this->username = username;
this->password = password;
}
~Account() {};
std::string get_username()const { return username; }
std::string get_password()const { return password; }
};
static void create_account(std::string user, std::string pass, std::vector<Account> &acc)
{
Account *account = new Account(user, pass);
acc.push_back(*account);
delete account;
}
static void generate_key(std::map<std::string, int>& key, std::string c_user)
{
unsigned int hold[7]{};
int *final = new int;
for (int i = 0; i < 7; i++)
{
unsigned int num = rand() % 9;
hold[i] = num;
}
*final = hold[0] + hold[1] + hold[2] + hold[3];
key.emplace(c_user, final);
std::cout << "Key created: " << *final << '\n';
delete final;
}
std::vector<Account> accounts;
std::map<std::string, int> keys;
int main()
{
srand(time(NULL));
create_account("random", "triathlon", accounts);
generate_key(keys, accounts[0].get_username());
return 0;
}
static void create_account(std::string, std::string, std::vector<Account> &acc);
static void generate_key(std::map<std::string, int>&, std::string);

If you want to generate a 7 digit number where all of the digits are unique, then you can store the valid digits in a vector and then shuffle that vector and take the first 7 elements as the digit to make the number with. That could be done like:
std::vector<char> digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
std::random_device rd;
std::mt19937 g(rd());
std::suffle(digits.being(), digits.end(), g);
std::string number{digits.begin(), digits.begin() + 7}
and now number is a 7 digit string where each digit only appears once. If you want to not have a leading zero, then you would need to check if the first element is a zero and if so, shuffle again or just takes elements 1 through 7.
If you just want to generate a 7 digit number, but you don't care if there are duplicate digits, then you can do that with a std::string and a simple for loop like:
std::random_device rd;
std::mt19937 g(rd());
std::uniform_int_distribution<> dist(0, 9);
std::string number;
for (int i = 0; i < 7; ++i)
{
number.push_back('0' + dist(g))
}

If you just want a random seven digit number with unique digits you can generate that directly using the typical random shuffle algorithm where you generate a random index into an array take that item, swap the back of the array with it, and pop back of the array.
I forget what this algorithm is called.
In your case you only need to do seven iterations starting with the nine digits. Code below:
#include <vector>
#include <array>
#include <algorithm>
#include <iostream>
int remove_rnd_item( std::vector<int>& digits ) {
int n = rand() % digits.size(); // should use a better RNG...
int rnd_digit = digits[n];
//swap with the last digit and pop...
std::swap(digits[n], digits.back());
digits.pop_back();
return rnd_digit;
}
int random_seven_digit_number_with_unique_digits() {
std::vector<int> digits = { 0,1,2,3,4,5,6,7,8,9 };
std::array<int, 7> rnd_digits;
std::generate(rnd_digits.begin(), rnd_digits.end(),
[&digits]() {
return remove_rnd_item(digits);
}
);
// convert the digits vector to a single int, if that is what you want
int tens_place = 1;
int val = 0;
for (auto digit : rnd_digits) {
val += tens_place * digit;
tens_place *= 10;
}
return val;
}
int main() {
for (int i = 0; i < 10; ++i) {
std::cout << random_seven_digit_number_with_unique_digits() << "\n";
}
}

I assume that the requirement to have all unique digits in the customer ID is erroneous.
To get a random 7-digit number you only need:
#include <random>
#include <iostream>
int main()
{
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> distrib(0, 9'999'999);
std::cout << distrib(gen) << std::endl;
}
If you want to avoid leading zeroes, use distrib(1'000'000, 9'999'999);

Weeee! Hi!.I'm a beginner too!. and yeah. I think you can do that like this!.
int boop(){
int ding=1000000;
int a[7]={1,4,6,3,4,2,4};
int re=0;
for(int i=0;i<7;i++){
re+=a[i]*ding;
ding/=10;
}
return re;
}
or just make your own function to make a random number ranging from 0 to 1. and multiply it with 9999999. (kinda recommended).
#include <iostream>
#include <math.h>
float boop(int seed){
return abs(sin( cos(seed*3972)*38472));
}
int main(){
float f=boop(34)*9999999;
std::cout<<(int)f;
return 0;
}

Related

How to change each specific char to an int in C++

It might be a really dumb question, but I have tried to look it up, and have googled a bunch, but still can't figure out an easy way...
In C++, saying that using namespace std;:
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
String N;
cin >> N;
}
When user input is 123, N will be "123".
How do I cast '1' to int 1, and '2' to int 2, and '3' to int 3?
I cannot use %.
It would be awesome if I were to use an index approach in the string.
I would like to have a function that receives N and its index as parameters. For instance:
int func(string N, int curr_ind)
{
// change curr_ind of N to a single int
// for instance, "123" and 1, it would return 2.
}
#include <iostream>
#include <string>
int get_digit_from_string(const std::string&s, int idx) {
return static_cast<int>(s[idx] - '0');
}
int main() {
std::string num{"12345"};
for (std::size_t i = 0; i < num.length(); ++i) {
std::cout << get_digit_from_string(num, i) << '\n';
}
}
Just get the character at the index, subtract '0', and cast to int.
The subtraction is necessary, otherwise the character of a digit will be cast to the ASCII value of that character. The ASCII value of '0' is 48.
Output:
❯ ./a.out
1
2
3
4
5
Now, just for fun, let's say you need frequent access to these digits. Ideally, you'd just do the conversion all at once and have these ints available to you. Here's one way of doing that (requires C++20):
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
std::vector<int> get_digits_from_string(const std::string& s) {
std::vector<int> v;
std::ranges::transform(s, std::back_inserter(v),
[](auto c) { return static_cast<int>(c - '0'); });
return v;
}
int main() {
std::string num{"12345"};
std::vector<int> digits = get_digits_from_string(num);
for (auto i : digits) {
std::cout << i << '\n';
}
}
We use the string to create a std::vector where each element is an int of the individual characters. I can then access the vector and get whatever digit I need easily.
Another possibility:
#include <iostream>
#include <string>
int main()
{
std::string input;
std::cin >> input;
// allocate int array for every character in input
int* value = new int[input.size()];
for (int i = 0; i < input.size(); ++i)
{
std::string t(1, input[i]);
value[i] = atoi(t.c_str());
}
// print int array
for (int i = 0; i < input.size(); ++i)
{
std::cout << value[i] << std::endl;
}
delete[] value;
}
Output:
x64/Debug/H1.exe
123
1
2
3
Try this:
int func(string N, int curr_ind)
{
return static_cast<int>(N[curr_ind]-'0');
}
Since the ASCII representation of consecutive digits differs by one, all you need to do to convert a character (char c;) representing a digit to the corresponding integer is: c-'0'

Generate Random 20 Non-repeating numbers in C++

So I have a program where I generate a 8x8 matrix which are rooms. So we have 64 rooms. Now I have to generate 20 random rooms to be dirty. I'm trying to figure out how I can generate 20 non repeating numbers to use as the dirty rooms. This is my code so far:
//generate the 20 random dirty rooms
int col;
int row;
for (int i = 0; i < 20; i++)
{
col = ranNumber();
row = ranNumber();
cout << "\t" << col << " " << row << endl;
if (room[row][col] == 'D')
{
cout << "Duplicate" << endl;
col = ranNumber();
row = ranNumber();
cout << "New number " << row << col << endl;
room[row][col] = 'D';
}
else
//set the room as dirty
room[row][col] = 'D';
}
*ranNumber():
int ranNumber() {
return rand() % 8;
}
Since you're not dealing with a particularly large data set, I'd suggest using std::shuffle. You'll want to initialize your rooms with 20 dirty (the positions don't matter, so do whatever is easiest), then let std::shuffle rearrange the rooms. This avoids you having to write your own loop in case you get poor luck with your random generator, and better expresses your intent.
Sample code:
int main() {
char rooms[8][8];
for(auto i = 0; i < 8; ++i) {
for(auto j = 0; j < 8; ++j) {
rooms[i][j] = (i == 0) ? 'D' : ' ';
}
}
printRooms(rooms);
std::random_device rd{};
std::default_random_engine re{rd()};
auto b = (char *) rooms;
std::shuffle(b, b + (8 * 8), re);
std::cout << "----------------------\n";
printRooms(rooms);
return 0;
}
You can create an array of room numbers (0-63) and use as a picking basket. Whenever a room has been picked, you swap that room out of the selectable range.
Example:
#include <algorithm> // fill_n
#include <iostream>
#include <numeric> // iota
#include <random> // mt19937, random_device, uniform_int_distribution
int main() {
std::mt19937 prng(std::random_device{}());
char room[8][8];
constexpr int room_count = 8 * 8;
std::fill_n(&room[0][0], room_count, '.'); // fill rooms with an initial value.
char numbers[room_count];
std::iota(std::begin(numbers), std::end(numbers), 0); // 0 - 63
for(int i = 1; i <= 20; ++i) {
int last_selectable_room = room_count - i;
std::uniform_int_distribution<int> dist(0, last_selectable_room);
auto& selected = numbers[dist(prng)];
*(&room[0][0] + selected) = 'D';
// swap the selected room number with the last selecable room number
// to make sure that the selected room can't be selected again
std::swap(selected, numbers[last_selectable_room]);
}
}
Demo
This is likely going to be 2.3 - 2.4 times faster than the std::shuffle approach if you use g++ or clang++. Benchmark
If selecting the dirty rooms uniformly at random is truly important, you could build a random permutation of the rooms using Knuth's shuffle (be careful, it is easy to blunder!) and picking e.g. the first 20 ones of the result as dirty.
You could do it using std::shuffle() and a single-dimension array, exploiting the fact that an m x n matrix can be represented as an array containing m*n elements
#include <vector>
#include <random>
#include <algorithm>
class random_room_generator {
public:
random_room_generator(const size_t matrixRows, const size_t matrixColumns) :
m_matrixRows(matrixRows),
m_randomRoomList(),
m_nextRoom(0)
{
// Create a list of all the room numbers.
const size_t totalRooms = matrixRows * matrixColumns;
for (size_t i = 0; i < totalRooms; ++i) {
m_randomRoomList.push_back(i);
}
// Shuffle the list.
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(m_randomRoomList.begin(), m_randomRoomList.end(), g);
}
std::pair<size_t, size_t> next() {
// Get the room number:
const size_t roomNumber = m_randomRoomList[m_nextRoom++];
if (m_nextRoom == m_randomRoomList.size()) {
// Loop back round to the start if we get to the end of the shuffled list.
m_nextRoom = 0;
}
// Convert the room number into a row and column using the modulus/division operators:
return std::pair<size_t, size_t>(roomNumber % m_matrixRows, roomNumber / m_matrixRows);
}
private:
size_t m_matrixRows;
std::vector<size_t> m_randomRoomList;
size_t m_nextRoom;
};
Then, in your function, instead of calling ranNumber(), you can use an instance of random_room_generator to save a list of random rooms and then get 20 rooms from that list:
random_room_generator gen(8, 8);
for (int i = 0; i < 20; i++)
{
std::pair<size_t, size_t> roomCoords = gen.next();
const size_t row = roomCoords.first;
const size_t col = roomCoords.second;
cout << "\t" << col << " " << row << endl;
//set the room as dirty
room[row][col] = 'D';
}
You can find a working example here: https://godbolt.org/z/xKLmjm

How to convert numbers into vector of integers?

I want my program to ask the user to input any number and then store it into a std::vector where every single digit is allocated to a separate vector index:
input: 142
output vector: [1, 4, 2]
I tried this:
int main()
{
std::vector<int> v;
int number;
cin >> number;
for(unsigned int i = 100; i > 0; i/=10)
{
v.push_back(number/i);
number -= (number/i)*i;
}
for(size_t i = 0; i < v.size(); ++i)
{
std::cout<<v[i]<<std::endl;
}
}
It works. But what should I do when the input-length is unknown?
Use simply std::string and for each char(which is actually integers) of string convert to integer as follows: SEE LIVE HERE
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<int> v;
std::string number = "123456789987654321";
for(auto& Integer: number)
v.emplace_back(static_cast<int>(Integer - '0'));
for(const auto& it: v) std::cout << it << " ";
}
Output:
1 2 3 4 5 6 7 8 9 9 8 7 6 5 4 3 2 1
In case of entering unwanted characters/ user inputs(for example some negative numbers or even this: +-1234567), you can go for something with try-catch. try to convert the char to int, otherwise skip in the catch block as follows. SEE LIVE HERE
#include <iostream>
#include <vector>
#include <string>
#include <exception>
int main()
{
std::vector<int> v;
std::string number = "+-1234567";
for(auto& Integer: number)
{
std::string Char(1, Integer); // convert to string
try { v.emplace_back(std::stoi(Char)); }
catch(...) { continue; } // any case of exceptions
/* or using much simpler std::isdigit from <cctype>
by which conversion to std::string and try-catch can be avoided.
if(std::isdigit(Integer))
v.emplace_back(static_cast<int>(Integer - '0'));
*/
}
for(const auto& it: v) std::cout << it << " ";
}
Output:
1 2 3 4 5 6 7
Edte: As per #Aconcagua suggested, included the solution with std::isdigit
while(number) {
v.push_back(number%10);
number /= 10;
}
std::reverse(v.begin(), v.end());
Change the for initilization unsigned int i = number rather than unsigned int i = 100. The re-written for statement will be:
for(unsigned int i = number; i > 0; i/=10)
I you want to stay with digits and std::deque is an option you could do the following:
int main()
{
std::deque<int> v;
int number;
cin >> number;
while(number != 0)
{
v.push_front(number%10);
number = number/10;
}
for(size_t i = 0; i < v.size(); ++i)
{
std::cout<<v[i]<<std::endl;
}
return 0;
}
With the modulo operator you simply take the last digit and insert it in the front of the deque. Afterwards you "cut off" that digit with /10.
I used a deque, because you can't push front with vectors.

Unique Random Number between 0 and 9

I am trying to generate a unique random number between 0 and 9. The same number cannot be generated twice and the function will be ran 9 time (until all the 9 numbers are used.) Here is the latest way I have been trying to do this:
int uniqueRandomInt(int x) {
std::vector<int> usedRandoms;
int random = x;
//Iterate vector
for (unsigned int i = 0; i < usedRandoms.size(); i++) {
//if passed value is in vector
if (random = usedRandoms[i]) {
uniqueRandomInt(random);
}
else {
//If unique rand found put into vector
usedRandoms.push_back(random);
return random;
}
}
}
Calling it in another function using:
cout << uniqueRandomInt(-1) << endl;
Result I am getting is:
17801152 (Changes every time the function is called)
Am I going about this totally wrong? I did try other ways but with no luck and this is where I'm currently at. Thanks in advance.
I prefer to use shuffle.
#include <algorithm>
#include <iostream>
#include <random>
#include <vector>
#include <cassert>
class T455_t
{
private:
// data
std::vector<int> m_iVec ;
public:
T455_t() {}
int exec()
{
std::vector<int> iVec;
gen10();
for (int i=0; i<10; ++i)
{
int nxtRandom = uniqueRandomInt();
std::cout << nxtRandom << std::endl;
}
return(0);
}
private: // methods
void gen10() // fills data attribute with 10 digits
{
for (int i=0; i<=9; ++i)
m_iVec.push_back(i);
std::random_device rd;
std::mt19937_64 gen(rd());
std::shuffle (m_iVec.begin(), m_iVec.end(), gen);
// m_iVec now contains 10 unique numbers,
// range 0..9, in random order
}
int uniqueRandomInt()
{
assert(m_iVec.size());
int retVal = m_iVec.back(); // gets last element in vector
m_iVec.pop_back(); // removes last element
return(retVal);
}
}; // class T455_t
int main(int argc, char* argv[])
{
setlocale(LC_ALL, "");
std::ios::sync_with_stdio(false);
std::chrono::high_resolution_clock::time_point m_start_us =
std::chrono::high_resolution_clock::now();
int retVal = -1;
{
T455_t t455;
retVal = t455.exec();
}
std::chrono::microseconds chrono_duration_us =
std::chrono::duration_cast <std::chrono::microseconds>
(std::chrono::high_resolution_clock::now() - m_start_us);
std::cout << " FINI " << chrono_duration_us.count()
<< " us" << std::endl;
return(retVal);
}
Your function doesn't appear to return a value if usedRandoms.size() is zero, which it will be the first time you call the function
int uniqueRandomInt(int x) {
std::vector<int> usedRandoms; // vector.size() = 0
int random = x;
// for loop won't be entered
for (unsigned int i = 0; i < usedRandoms.size(); i++)
{
}
// function doesn't return a value
}
It's worth noting that it's undefined behaviour to declare a function to return a value, and then not return a value. That's why the random values you're getting.
From the C++ standard, 6.6.3 (emphasis mine):
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
vector<int> initVector(){
vector<int> ret;
ret.clear();
for(int i = 0 ; i < 10 ; ++i){
ret.push_back(i);
}
return ret;
}
int uniqueRendom(){
static vector<int> randomNumbers = initVector();
int randomSize = randomNumbers.size() - 1;
if(randomSize <= 0){
return -1;
}
double randomeNum = (double)rand() / INT_MAX;
int randomIndex = (int) (randomeNum * randomSize + 0.5) ;
int returnValue = randomNumbers[randomIndex];
randomNumbers.erase(randomNumbers.begin() + randomIndex);
return returnValue;
}
include limits.h for INT_MAX.

Return value from string function

i have a string array that contains 20 words. I made a function that take 1 random word from the array. But i want to know how can i return that word from array. Right now i am using void function, i had used char type but it wont work. Little help here ? Need to make word guessing game.
CODE:
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <stdlib.h>
#include <algorithm>///lai izmantotu random shuffle funckiju
#include <string>
using namespace std;
void random(string names[]);
int main() {
char a;
string names[] = {"vergs", "rokas", "metrs", "zebra", "uguns", "tiesa", "bumba",
"kakls", "kalns", "skola", "siers", "svari", "lelle", "cimdi",
"saule", "parks", "svece", "diegs", "migla", "virve"};
random(names);
cout<<"VARDU MINESANAS SPELE"<<endl;
cin>>a;
return 0;
}
void random(string names[]){
int randNum;
for (int i = 0; i < 20; i++) { /// makes this program iterate 20 times; giving you 20 random names.
srand( time(NULL) ); /// seed for the random number generator.
randNum = rand() % 20 + 1; /// gets a random number between 1, and 20.
names[i] = names[randNum];
}
//for (int i = 0; i < 1; i++) {
//cout << names[i] << endl; /// outputs one name.
//}
}
Make random return string. You also only need to seed the number generator once. Since you only want to get 1 random word from the array, you don't need a for loop.
string random(string names[]){
int randNum = 0;
randNum = rand() % 20 + 1;
return names[randNum];
}
Then, in the main function, assign a string variable to the return value of the random function.
int main() {
srand( time(NULL) ); // seed number generator once
char a;
string names[] = {"vergs", "rokas", "metrs", "zebra", "uguns", "tiesa", "bumba",
"kakls", "kalns", "skola", "siers", "svari", "lelle", "cimdi",
"saule", "parks", "svece", "diegs", "migla", "virve"};
string randomWord = random(names);
cout<<"VARDU MINESANAS SPELE"<<endl;
cin>>a;
return 0;
}
In your question as well as in the previous answer, you are running out of bounds accessing the names array:
int randNum = rand() % 20 + 1;
return names[randNum];
You are never accessing names[0] but instead reach behind the array when addressing names[20].
Additionally srand(time(NULL)) should be called only one time, on the beginning of main() function.
I'm not super familiar with strings, but you should be able to just declare random() as a string function.
Ex:
string random (string names[]);