Declaring a value to int in arrays - c++

I'm trying to make a deck of cards with only using array and no classes.
How do I declare a value to each and every card? It seems very inefficient trying to write it like this, and then trying to give a value to each index position:
int deckOfcards[52]{ 1,2,3,4,5,6,7,8,9,10.......... };
Also I will then draw 2 random cards and declare a winner. Is it possible to use rand() function in arrays?

You can create a loop to populate your array for you..
int deckOfCards[52]{};
for (int i = 0; i < 52; i++)
{
deckOfCards[i] = i+1;
}
That works just fine for this particular instance, but you may want to use
std::size(deckOfCards) in your loop because the size of the array may not always be known.
int deckOfCards[52]{};
for (int i = 0; i < std::size(deckOfCards); i++)
{
deckOfCards[i] = i+1;
}
Remember that array index's start at 0, so i will go from 0 to 51. That's why we are setting deckOfCards[i] equal to i + 1

There is imo even a nicer way to introduce randomness to cards,
use std::shuffle. By using this function you get code that kind of
explains itself. It will also introduce the deck of cards you are looking for.
#include <algorithm>
#include <array>
#include <random>
#include <iostream>
//-----------------------------------------------------------------------------
struct card_t
{
// each new instance gets a number which is then increased
// ++ at the end is important.
card_t() :
number{ g_card_number++ }
{
}
std::size_t number;
static std::size_t g_card_number;
};
std::size_t card_t::g_card_number = 1;
//-----------------------------------------------------------------------------
int main()
{
// setup random generation c++ style
std::random_device rd;
std::default_random_engine random_generator{ rd() };
// create a deck of 52 cards
// this will call the constructor for each of them so they all get
// a unique number
std::array<card_t, 52> cards;
// shuffle the cards using the random generator
std::shuffle(cards.begin(), cards.end(), random_generator);
std::cout << "first card has number : " << cards[0].number << "\n";
std::cout << "second card has number : " << cards[1].number << "\n";
return 0;
}

The requirements are that you want to emulate a standard deck of playing cards, and comments indicate that you want to track the suit and the value. You also claim that you want to do this with just an array of integers.
It is possible, but probably not what you're really after. Simpler solutions have already been posted as answers, but I will attempt to provide an answer that meets the stated requirements.
I'll just say up front that this is likely an XY problem, meaning the problem you stated is not the real problem you're having. You'll see as much with the code.
To uniquely encode two pieces of information into a single int, you'll need a way to encode and decode. The simplest way to do this is with prime number multiplication. This is because the only two dividends can be the prime numbers. Just for kicks, this is also the basis of a lot of modern cryptography.
You'll need 17 prime numbers (4 suits and 13 values). I'm choosing the 'first' 17, starting from 3. They are: 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, and 61.
I will arbitrarily use the last 4 to represent the suits. So for me, clubs is 47, spades is 53, then hearts then diamonds.
So for example, a 3 of clubs would have a value of 235 (5 * 47). A 3 of hearts would have a value of 295 (5 * 59). Every card is uniquely identifiable, and you can know the value and the suit.
You could probably get away with just prime numbers for the suits, but I know that if we use two primes, the uniqueness is guaranteed.
To randomly pick two cards, you'll actually shuffle the entire deck and just look at the first two elements of the array. This is because if you try to just pick two random numbers in the range [0, 51], (the [] means it's inclusive), there is the possibility that you pick the same number twice, which is impossible in a real deck.
Here's the code, which I tried to keep as simple as possible (i.e., trying to keep my Standard Library use to a minimum with sanity exceptions)
#include <algorithm>
#include <iostream>
#include <iterator>
#include <random>
void create_deck(int deck[], int deckSize) {
// cl sp he di
int suits[]{47, 53, 59, 61};
// 2 3 4 5 6 7 8 9 10 J Q K A
int values[]{3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
int idx = 0;
for (std::size_t s = 0; s < sizeof(suits) / sizeof(suits[0]); ++s) {
for (std::size_t v = 0;
v < sizeof(values) / sizeof(values[0]) && idx < deckSize; ++v) {
deck[idx] = suits[s] * values[v];
++idx;
}
}
}
// Prints the name of the card and returns the value
int decode_card(int val) {
// cl sp he di
int suits[]{47, 53, 59, 61};
std::string suitNames[]{"clubs", "spades", "hearts", "diamonds"};
// 2 3 4 5 6 7 8 9 10 J Q K A
int values[]{3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
std::string valueNames[]{"two", "three", "four", "five", "six",
"seven", "eight", "nine", "ten", "jack",
"queen", "king", "ace"};
int realValues[]{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
std::string suit;
std::string value;
for (std::size_t i = 0; i < sizeof(suits) / sizeof(suits[0]); ++i) {
if (val % suits[i] == 0) {
suit = suitNames[i];
val /= suits[i];
for (std::size_t v = 0; v < sizeof(values) / sizeof(values[0]); ++v) {
if (values[v] == val) {
value = valueNames[v];
std::cout << value << " of " << suit << ".\n";
return realValues[v];
}
}
}
}
return -1;
}
int main() {
const int deckSize = 52;
int deck[deckSize];
create_deck(deck, deckSize);
std::shuffle(std::begin(deck), std::end(deck),
std::mt19937(std::random_device{}()));
int playerOneDraw = deck[0];
int playerTwoDraw = deck[1];
std::cout << "Player 1: ";
int playerOneValue = decode_card(playerOneDraw);
std::cout << "Player 2: ";
int playerTwoValue = decode_card(playerTwoDraw);
if (playerOneValue > playerTwoValue) {
std::cout << "Player 1 wins.\n";
} else if (playerOneValue == playerTwoValue) {
std::cout << "It's a draw.\n";
} else {
std::cout << "Player Two wins.\n";
}
}
One run's output:
Player 1: ace of spades.
Player 2: three of diamonds.
Player 1 wins.
Right away, I hope you see that is code a lot longer and a lot more complex than the other solutions that use classes. That makes this code harder to maintain in the long run.
This is exactly because the requirements you've given are making the task harder than it needs to be. I opted to not use global variables because you really shouldn't, but I also opted out of a namespace because I'm assuming if you don't want classes you probably don't want a namespace.

Related

How do I change the odd numbers to even in an array? C++

For this assignment, I have to write a program that removes the odd numbers from an array
and replaces them with even numbers. The array must have 10 elements and be initialized with the
following numbers: 42, 9, 23, 101, 99, 22, 13, 5, 77, 28.
These are the requirements:
Must use the values provided in my array.
Print the original array to the console.
Identify any odd values in the array and replace them with even values.
Display the updated array to the console.
This is the output I am going for:
The original array is: 42 9 23 101 99 22 13 5 77 28
Your even number array is: 42 18 46 202 198 22 26 10 154 28
I'm super new to programming, so this concept is difficult for me to grasp, so if someone could give guidance that would mean the world.
This is what I have so far
#include <iostream>
using namespace std;
int main()
{
int const size = 10;
int values[size] = { 42, 9, 23, 101, 99, 22, 13, 5, 77, 28 };
for (int i = 0; i < size; i++)
{
if (values[i] % 2 != 0)
{
cout << (values[i] * 2) << endl;
}
}
return 0;
}
output
It's multiplying the odd numbers, which is want I want, but not each one in their own line. Also the new even numbers need to be along with the original even numbers.
You mentioned that you are somehow new to programming. So, we need to adapt our answer to that fact. You will not yet know all the existing functions in the standard library. So, let us come up with a very easy solution.
Obviously we need to frist print the original unmodified date from the array. So, we will output the initial text and then iterate over all the slements in the array and output them as is.
Next, we show the second label string and then iterate again over all elements in the array. We the check for each value, if it is odd. If it is, then we print the double of this value, else, we show to unmodified value.
Please have a look at the below for one potential solution approach:
#include <iostream>
using namespace std;
int main() {
// Size of our array
int const size = 10;
// Arry with some random sample data
int values[size] = { 42, 9, 23, 101, 99, 22, 13, 5, 77, 28 };
// Show the original array
cout << "\nThe original array is: ";
for (int i = 0; i < size; ++i) cout << values[i] << ' ';
// Now show check for odd numbers
cout << "\nYour even number array is: ";
// Show result
for (int i = 0; i < size; ++i)
if (values[i] % 2 != 0)
cout << (values[i] * 2) << ' ';
else
cout << values[i] << ' ';
cout << '\n';
}
The transformation itself seems pretty simple. There are a number of ways to do the job. Here's one possibility:
std::transform(b, e, b, [](auto v) { return v * ((v & 1) + 1); });
Just as a fair warning: if you turn that in for homework, whoever's teaching the class is probably going to ask some deep and searching questions about how it works, and start to get really suspicious if you don't have answers showing equally deep understanding.

Trying to write a C++ program that lists all the polite numbers in the upper value

For example, if the user enters the number 21, I want all the polite numbers listed. so for 21, the output would be 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21. I am new for loops and I am having a difficult time trying to get this to work. I cant include any global variables for this assignment. Any help would be greatly appreciated. Thank you.
Seems like you are just excluding the numbers which are squares, which would not produce the right answer.
You can either create an array upto upValue with initial value set to 0 and mark all the powers of 2 as 1 using this for loop:
for(int j=1;j<=upValue;j*=2){
arr[j]=1;
}
now you have flagged all the powers of two and then iterate over the all values from 1 to upValue and print the ones that are set to 0;
The following program does what you want it to do.
#include <iostream>
#include <math.h>
void politeNo(int input)
{
// Print all initial input Polite number
for (int n = 1; n <= input; ++n)
{
// Calculate nth Polite number
int result = (int)(n +
(log((n + (log(n) /
log(2))))) /
log(2));
// Display calculated result
std::cout << " " << result;
if (result == input){break; }
}
}
int main()
{
int upValue = 0;
std::cout<<" What is the upper value ?";
std::cin >> upValue; //Stores user input into upValue
while (upValue < 1) //Validate user input of upper limit
{
std::cout << "What is the upper value? (must be an integer > 0) ";
std::cin >> upValue;
}
politeNo(upValue);
return 0;
}
Output:
1 3 5 6 7 9 10 11 12 13 14 15 17 18 19 20 21

randomly increment through an array, c++

I am struggling to understand the concept of randomly reading numbers from an array of integers using 'rand()'. I have created a random number generator between 1-3 and want to output an index of an array, then for the generator to randomly output the next generated number from the previous index, until it reaches the end of the array. For example:
'rand()'= 3, 'array[2]'
'rand()' = 2, 'array[4]'
'rand()' = 3, 'array[7]'
if that makes sense?? etc, etc.
The code I'm currently using just outputs a sequence of random numbers. I have place a 'seed' so I can look at the same sequence.
int main()
{
int arrayTest[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20};
srand(4);
for(int i = 0; i < 20; i++)
{
arrayTest[i] = (rand() % 3);
cout << arrayTest[i] << endl;
}
}
I am somewhat guessing at what you really want. But it seems to want to make random increments to an index, and use that index to read from the array in a loop.
So this code just doesn't do anything like you want
arrayTest[i] = (rand() % 3);
It writes (not reads) a random value to an array using a sequential (i.e. non-random) index.
Here's what I think you want
int main()
{
int arrayTest[20] = { ... };
srand(4);
int index = -1;
for(int i = 0; i < 20; i++)
{
index += (rand() % 3) + 1; // add random number from 1 to 3 to index
if (index >= 20) // if index too big for array
index -= 20; // wrap around to beginning of array
cout << arrayTest[index] << endl; // read array at random index, and output
}
}
But I'm not completely sure, in particular the way your testArray has the numbers 1 to 20 in order is making me a bit suspicious. Maybe if you explain why you want to do whatever you want to do it would be a bit clearer.

dividing duplicates by the counter of duplicates

the program i'm trying to write gets info from user, check duplicate in weight and count those duplicates.
For example,
{10, 40, 30, 40, 30} each 40 and 30 is duplicated 2 times
so it should be {10, 20, 15, 20, 15}
and this is my code:
struct Data {
int id;
double weight
}
std::sort(p, p + num, acompare);
for (int i = 0; i < num; i += counter) {
for (counter = 1; i + counter<num&& p[i + counter].weight== p[i].weight; )
counter++; // count consecutives dups
if (counter>1) { // if more than one, process the dups.
cntArr[i] = counter;
cntArr[counter] = counter;
} else
cntArr[i] = 1;
}
for (int i = 0; i < num; i++) {
cout << p[i].id << ":" << p[i].weight/ (double) cntArr[i] << endl;
}
and the result is like this
input :
1 100
2 100
3 100
4 80
5 80
output :
4 40
5 -9.79969e-08
1 33.3333
2 33.3333
3 -1.18744e-07
How do i fix this?
It's a bit hard to debug the specific problem in your code, as it isn't complete (can't copy-paste it to an editor and build it). In particular, not sure what are p, cntArray, and how they are initialized.
However, fundamentally, this code could be made shorter and more efficient. Instead of sorting (immediate Θ(n log(n)) complexity), use an std::unordered_map to store the multiplicity of each element. Shorter, fewer potential bugs, and (expected) linear complexity.
#include <vector>
#include <unordered_map>
#include <iostream>
#include <algorithm>
int main() {
const std::vector<int> a{10, 40, 30, 40, 30};
std::unordered_map<int, std::size_t> counts;
std::for_each(std::begin(a), std::end(a), [&](int e){ ++counts[e]; });
std::for_each(std::begin(a), std::end(a),
[&](int e){ std::cout << e / static_cast<double>(counts[e]) << std::endl; });
}
Outputs:
$ ./a.out
10
20
15
20
15

How do I parse arrays in C++ for duplicates

Please help me use C++ to parse an array and only display numbers that are unique. I have written a program which answers most of the question below.
Question:
Use a one-demensional array to solve the following problem. Read in 20 numbers, each of which is between 10 and 100, inclusive. As each number is read, validate and store it in the array only if it isn't a duplicate of a number already read. After reading all the values, display only the unique values that the user entered. Provide for the "worst case" in which all 20 number are different. Use the smallest possible array to solve this problem.
What I've done:
My program creates a 20 item array. Prompts user for data, validates it and displays it. I have tried several way to only display unique data, however I have not accomplished what the question asks.
Sample User Input:
11, 12, 12, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27
My Program Output:
{ 11, 12, 12, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }
Correct Program Output:
{ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }
Any advice where to go with this. See below for code. Thank you for your help!
#include <iostream>
#include <array> // needed for c++11 arrays
using namespace std;
int main()
{
const int arraySize = 20; // limit array length to 20
array <int, arraySize userArray> = {};
//Populate array with user input and validate it to be between 10 and 100
for (int i = 0; i < userArray.size(); i++)
{
cout << "Enter a number between 10 and 100" << endl;
cin >> userArray[i]; // get user input assign it to proper array subscript
while(userArray[i] > 100 || userArray[i] < 10)//validate user input to be between 10 and 100
{
cout << "Number needs to be between 10 and 100. Enter a new number" << endl;
cin >> userArray[i]; //reassign the proper array subscript if needed
}
}
cout << endl;
//display the information to look like an array
//result looks like [ v, w, x, y, z ]
cout << "[ ";
//display array values
for (int i = 0; i < userArray.size() - 1; i++)
{
cout << userArray[i] << ", ";
}
//properly display last array item
cout << userArray[(userArray.size() - 1)] << " ]" << endl;
return 0; }
If you can use std::vector, then you can use following solution.
template <typename Type>
std::vector<Type> unique_entries (std::vector<Type> vec) {
for (auto iter = vec.begin (); iter != vec.end (); ++iter) {
auto f = std::find_if (iter+1, vec.end (), [&] (const Type& val) {
return *iter == val; // (X)
});
if (f != vec.end ()) {
vec.erase (std::remove (iter+1, vec.end (), *iter), vec.end ());
}
}
return vec;
}
template <typename T>
void show (std::vector<T> vec) {
for (const auto& v : vec) {
std::cout << v << " ";
}
std::cout << std::endl;
}
And example would be like that:
std::vector<int> vec {11, 12, 12, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27};
std::vector<short> vec2 {1, 1, 1, 2, 3, 2, 1, 2, 1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 10};
std::vector<std::string> vec3 {"a", "a", "a", "aa", "b", "b", "bb", "c"};
show (vec);
show (unique_entries (vec));
show (vec2);
show (unique_entries (vec2));
show (vec3);
show (unique_entries (vec3));
And the output:
11 12 12 12 13 14 15 15 16 17 18 19 20 21 22 23 24 25 26 27
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
1 1 1 2 3 2 1 2 1 2 3 2 1 2 3 2 1 2 10
1 2 3 10
a a a aa b b bb c
a aa b bb c
Look at the line (X), basically you can use this unique_entries for all types which offer operator==, but you have to keep in mind that this will probably fail if you use this function for floating point types.
Hope this is what you are looking for........... Basically I use an another array to store the elements already entered by the user. So when the user enters a number it checks whether it is already in the array of 'entered elements' or not.
#include<iostream>
#define MAX 20
using namespace std;
int main()
{
int list[MAX],visitedElements[MAX];
int noElements,element,currentIndex;
bool flag=false;
cout<<"Enter total no. of elements(MAX=20):"<<endl;
cin>>noElements;
for(int i=0; i<noElements; i++)
{
visitedElements[i] = -1;
}
for(int i=0;i<noElements;i++)
{
currentIndex=i;
cout<<"Enter Element:"<<endl;
cin>>element;
for(i=0;i<currentIndex;i++)
{
if(visitedElements[i] == element)
{
flag==true;
break;
}
}
if(flag == false)
{
list[i]=element;
visitedElements[i] = element;
}
flag = false;
}
cout<<"Elements in list are"<<endl;
for(int i=0 ; i<noElements ;i++)
cout<<list[i]<<endl;
return 0;
}
#include <iostream>
using namespace std;
int main(){
int tab[10];
int i=0,j;
int number=0;
int counter=1;
bool flag=true;
int tries=0;
while(tries<10){
do{
cin>>number;
tries++;
if((number>100)||(number<10)){
cout<<"Wrong number, has to be between 10 and 100"<<endl;
}
}
while((number>100)||(number<10));
flag=true;
if(i==0){
tab[i]=number;
}
else{
for(j=0; j<counter; j++){
if(tab[j]==number){
flag=false;
i--;
break;
}
}
}
if(flag==true){
tab[i]=number;
counter++;
}
i++;
}
for(i=0; i<counter-1; i++){
cout<<tab[i]<<", ";
}
}
I kinda meesed it up probably. I'm new to programing but this is my solution.
So. You said it has to take 20 digits, mine takes 10, after 10 inputs it will list the array. So if my input is "10, 10, 10, 12, 13, 15, 15, 18, 22, 22"
the output is: "10, 12, 13, 15, 18, 22"
I could probably erase half of the code but like i said I'm a beginner and i was writing it in a hurry.
EDIT: Ups, small mistake in the array declaration. I was testing it for 5 elements and forgot to make a bigger array.
The question asked to use one array, so I would loop over the numbers already in the array after reading in each number and check for duplicates. It would look something like this:
#include <iostream>
constexpr int ARRAY_SIZE = 20;
int main()
{
int userArray[ARRAY_SIZE], validNumbers = 0;
for(int i = 0; i < ARRAY_SIZE; i++)
{
int num;
bool isGood = true;
std::cin >> num;
//code to check if input is in range here
for(int j = 0; j < validNumbers; j++)
{
if(userArray[j] == num)
{
isGood = false;
break;
}
}
if(isGood)
{
userArray[validNumbers] = num;
validNumbers++;
}
}
//userArray now contains all unique numbers in the order that they were entered
for(int i = 0; i < validNumbers; i++)
{
std::cout << userArray[i];
if(i < validNumbers - 1)
{
std::cout << ' ';
}
}
std::cout << '\n';
}
inside of your for loop, instead of makign the cin go directly into the array, add another int variable and set it to equal the input
cin >> variable
then make a for loop that iterates through your current array to make sure its not a duplicate; use the line below as your for loop
for(int j = 0; j < i; j++)
if the number is already in the array, just continue. Else, add it in.
Also, instead of using a for loop in the beginning, I would use a while loop with
while(i < arraysize)
Then deincrement array size every time you see a duplicate and only increment i when you add an element