Related
I'm asked to count the exact number of operations cost for this function. I've used op to keep track of it. The recursive call should be the number of operations performed by that function call (I'm not sure if I'm doing that right in my code). My question is, how do I formulate a mathematical equation to match the number of operations. I've commented beside each line to annotate the cost of operations. From that, i get 2n^2 - n + 6. But this don't match with my output.
// PARAM: arr is array to be sorted, n is size of array, i should initially = 0
int ssort(int arr[], int n, int i)
{
int op = 0;
if (i < n-1) //1
{
// Find and swap smallest remaining
int next = i + 1; //1
int smallest = i; //1
while (next < n) //i+1
{
if (arr[next] < arr[smallest]) //i
{
smallest = next; //i
}
next++; //i
op += 4; altogether 4 ops
}
op++; //while loop terminates
// Swap i with smallest
int temp = arr[i]; //1
arr[i] = arr[smallest]; //1
arr[smallest] = temp; //1
op += ssort(arr, n, i + 1);
}
op+=6;
return op;
}
To find the formula, you can simply test out multiple cases, and interpolate a formula from it.
// set up an empty array of length 10
int arr[10];
// set up a for loop for i = 1, 2, 3...
for(auto i : {1, 2, 3, 4, 5, 6, 7, 8, 9})
{
std::cout << ssort(arr, i, 0) << ", ";
}
This prints:
6, 17, 32, 51, 74, 101, 132, 167, 206, 249,
Now put that data in a polynomial interpolation calculator, you will get:
I have known java for a while and I was trying to translate a java program i wrote to c++ but the copy function gives an odd result:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
long gcd2(long a, long b) {
if ( a == 0 )
return b;
return gcd2(b%a,a);
}
long gcd(long nums[]) {
long ans = nums[0];
int len = sizeof(nums);
for (int i = 1; i < len; i++)
ans = gcd2( nums[i] , ans );
return ans;
}
string com(string s) {
s = s+",";
return (","+s);
}
void printa(long array[]) {
for (int i = 0 ; i < sizeof(array); i++)
cout << array[i] << ", ";
cout << "\n";
}
int main()
{
int length;
cin >> length;
long input[length];
for (int i = 0; i < length; i++)
cin >> input[i];
string possible = "";
int ans = 0;
for (int a = 0; a < length; a++) {
for (int b = length; b > a; b--) {
long arr[b-a];
std::copy(input+a,input+b,arr);
printa(arr);
long gcdans = gcd(arr);
if (possible.find( com(gcdans+"") ) == -1 ) {
possible += com(gcdans+"");
ans++;
}
}
}
cout << (ans);
return 0;
}
I give it the input of:
4
9 6 2 4
and it returns:
9, 6, 2, 4, 140725969483488, 4197851, 9, 6,
9, 6, 2, 4197851, 9, 6, 2, 4,
9, 6, 2, 4197851, 9, 6, 2, 4,
9, 4197851, 9, 6, 2, 4, 140725969483488, 4197766,
6, 2, 4, 4197851, 9, 6, 2, 4,
6, 2, 4, 4197851, 9, 6, 2, 4,
6, 4197851, 9, 6, 2, 4, 140725969483488, 4197766,
2, 4, 6, 4197851, 9, 6, 2, 4,
2, 4197851, 9, 6, 2, 4, 140725969483488, 4197766,
4, 4197851, 9, 6, 2, 4, 140725969483488, 4197766,
1
the number at the very end is what i want the program to output at the end, all the numbers above are me test printing the array to see its contents. Basically I am trying to copy a range of the array(for example (2,3,4) from (1,2,3,4,5,6)) But it gives weird numbers like 140725969483488 and 4197766 when the only numbers I input are 9 6 2 4
Variable length arrays is a C++ extension, not standard C++. If your compiler will allow them, then OK. However standard C++ would use an std::vector container which is dynamically sized at runtime, meaning you can initialise them with any size or numbers at runtime, and add anything you want at runtime.
Also note when passing an array in C++ to functions which take an array argument always (with the exception of explicitly declared sized reference to an array) gets passed as a pointer, so you can't know the size of the array once passed as an argument. So this:
void printa(long array[])
{
for (int i = 0 ; i < sizeof(array); i++) {}
// At this point of the code the sizeof(array) will return the size of
// a pointer, usually 4 or 8 bytes.
// It's a quirk that this happens, and is a holdover from C.
}
By taking an argument of std::vector you can know the size of the array. You can take the argument by value or by reference or pointer.
void printa(const std::vector<long>& array)
{
for (int i = 0 ; i < array.size(); i++)
{
cout << array[i] << ", ";
cout << "\n";
}
}
This is the better way to do it. If you want to use a C array or raw array the way you did, you will have to pass both the array and the size of the array as separate arguments.
Also, about the variable length array extension feature, I'm not sure whether it is reliable or not because I've never used the extension. Again, standard C++ requires that size of arrays are constant values, (known at compile time). Edit: actually (known at compile-time) is a bad description because:
int main()
{
int num = 6;
int myarray[num]; // In standard C++ this won't compile
//but
const int num = 6;
int myarray[num]; // Will
}
And one last thing, as SolutionMill pointed out, even if the sizeof(array) does give the right size and not the size of a pointer, it is the size given in bytes, not the number of elements, which was not you were wanting in:
for (int i = 0 ; i < sizeof(array); i++)
If the array is of 2 elements of 32 bit int, then the sizeof() operator will return size 8. A common but by no means pretty way to get the number of elements in an array is something like sizeof(array) / sizeof(array[0])
I am new to programming and Stack Overflow.So I've been building a simple database for my own enjoyment and to practice my knowledge. It registers a user's username, password and assigns a user ID. To a text file and you can also view the user's information.
My main problem is that I want the program to assign the user an ID that is random from say 1-1000 (ex. 1000 being the maximum employees).
This block of code executes when the user registers a new username and password. The program outputs the username, password, and the user ID in this part. I am able to get the program to output a random number for each user made, but I am not able to make it generate numbers with no duplicates.
The program should output a message that if there are no more user IDs available, then the registration process will not complete.
I created a function that prints a bunch of lines to clear the screen, but everything is at the bottom. If there is a different function I can use I would be glad to know!
if (passwordCheck == password) {
const int minEmp = 1, maxEmp = 10;
srand(time(0));
userID = (rand() % (maxEmp - minEmp + 1)) + minEmp;
ofstream outfile (username + ".txt"); //Creates txt file with user name
outfile << "User ID: " << userID << endl << //Outputs info to txt file
"Account Username: "<< username << endl
<< "Account Password: " << password;
outfile.close();
clearScreen(); //My function to add lines to clear the screen
cout << endl << "Your account has been created." << endl
<< endl << "Returning to main menu.";
clearScreen();
mainMenu(); //Function to return back to menu
Your basic problem is that random number generation does not guarantee uniqueness. It certainly does not guarantee uniqueness between runs of the program (e.g. if you want to modify the database during multiple runs of the program, and maintain consistency). Therefore, you need a way of generating a set of unique IDs, remove any that have been previously used (e.g. are represented in the database), and then shuffle whatever is left.
One approach might be;
Create a list of 1000 (or whatever number you need) unique IDs (e.g. in a vector). This can be done with a simple loop, or using std::generate() with an appropriate generator that returns a different value every time it is called. The method of generating unique IDs need to be consistent (no randomness) to allow the second step to work.
Read the database and remove every ID that is in the database from
the list.
If the remaining list has zero elements, don't allow adding more
users.
Shuffle the list. In C++11 or later, use std::shuffle(). You'll
need to read up on random number generation. Before C++14, you
MIGHT use std::random_shuffle(), but bear in mind it uses rand()
to generate random values, and the quality of that is uncertain -
which is why it has been deprecated in C++14 (flagged for future
removal from the standard).
Every time you need a new unique value (e.g. when creating a user)
obtain the last value from the list, remove that value from the
list, create the user, and save it to the database.
There is a tricky thing to get that: Let's say you want 10 values randomly generated as a permutation and you want to store them in a file.
So you can calculate how to generate the random indexes then use the indexes on the array of values to store data:
I also face some same issue one day when I was developing a game of card with images that each failure the hidden images jump randomly into some positions.
#include <iostream>
#include <fstream>
#include <ctime>
int main(){
srand(time(NULL));
std::ofstream out("data.txt");
// arrays of data whose values will be stored randomly in a text file.
int array[10] = {7, 57, 23, 21, 1,
0, 18, 19, 3, 777};
// array of indexes and initializing it
int indexes[10];
for(int i(0); i < 10; i++)
indexes[i] = rand() % 10;
// indexes are filled with random values from 0 to 9 but it surely contains duplicates eg:
// 3, 0, 7, 5, 2, 8, 0, 1, 0, 0
// Now I use my algorithm to discard duplicates and repeating until I get an array of unique indexes.
for(int i = 0; i < 10; i++){
for(int j(0); j < 10; j++){
if(indexes[i] == indexes[j] && i != j){
indexes[j] = rand() % 10;
i = 0;
}
}
}
// check out that the indexes are unique and no duplicates there:
std::cout << "\n\nThe random indexes: " << std::endl;
for(int i = 0; i < 10; i++)
std::cout << indexes[i] << ", ";
// writing the random values of array using the random indexes array to the file:
for(int i = 0; i < 10; i++)
out << array[indexes[i]] << ", ";
// printing the random values of the array
std::cout << "\n\nThe random values: " << std::endl;
for(int i = 0; i < 10; i++)
std::cout << array[indexes[i]] << ", ";
out.close();
std::cout << std::endl << std::endl << std::endl;
return 0;
}
The output: Try to run the program many times and see the result.
// 1
The random indexes:
3, 9, 5, 1, 7, 6, 0, 4, 8, 2,
The random values:
21, 777, 0, 57, 19, 18, 7, 1, 3, 23,
// 2
The random indexes:
5, 8, 0, 1, 3, 9, 4, 2, 6, 7,
The random values:
0, 3, 7, 57, 21, 777, 1, 23, 18, 19,
// 3
The random indexes:
6, 7, 3, 1, 5, 2, 4, 9, 0, 8,
The random values:
18, 19, 21, 57, 0, 23, 1, 777, 7, 3,
I offered only a small example so in your case if you want 1000 unique values just look at 0-1000 as an array of unique values so you can use the algorithm above:
1// initializing
int randValues[1000];
for(int i(0); i < 1000; i++)
randValues[i] = (rand() % 1000) + 1; // because you want to discard 0
now get the unique values:
for(int i(0); i < 1000; i++){
for(int j(0); j < 1000; j++){
if(randValues[i] == randValues[j] && i != j){
randValues[j] = (rand() % 1000) + 1;
i = 0; // reset
}
}
}
I need to add either +0.25 or -0.25 to all elements within an array. Here is what I have so far. Any help would be appreciated.
int main() {
double i;
// Arrays
double x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
double x2[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(i=1; i<=10; i++) {
const double pM[2] = {-1, 1};
int randoid = rand() % 2;
for(i=1; i<=10; i++){
x2[i] = x[i] + pM[randoid]*0.25; //Error Line
}
}
cout << x;
cout << x2;
}
I get this error at the marked line: "invalid types 'double[10][double] for array subscript"
The problem is that i is a double. Then you write x2[i].
It's not a very good error message; however with the [] operator, one of the operands must be a pointer and the other must be an integer. There is no implicit conversion of floating-point to integer when using this operator.
To fix this change double i; to int i;
Another issue is that your code accesses out of bounds of the arrays. double x2[10] means that there are 10 elements whose indices are 0 through 9. But your loop tries to write to x2[10]. This causes undefined behaviour, which could explain your strange output.
There is also a potential logic error. Maybe you meant to use a different variable for the inner loop than the outer loop. As it stands, the inner loop will take i to 11 (or 10 if you fix the code) and then the outer loop will be complete and not execute any more iterations.
Based on your description though, perhaps you only meant to have one loop in the first place. If so, remove the outer loop and just leave the contents there.
Also you do not need two separate arrays, you could just perform the addition in-place.
Regarding the output, cout << x and cout << x2 will output the number of the memory address at which the array is located. To output the contents of the array instead you will need to write another loop, or use a standard library algorithm that iterates over containers.
I see 3 issues -
Change the type of i to int.
x and x2 are arrays of size 10. You need to loop from i =
0 to i = 9. But you are looping from i = 1 to i = 10. x[10]
is out of bounds since arrays are 0 indexed.
cout << x - This is a wrong way to print an array. You need
to loop through the array and print - e.g. -
for(i = 0; i < 10; i++)
cout << x[i] << " ";
Try this, it works, I converted to C
int main( )
{
int i = 0;
// Arrays
double x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
double x2[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for ( i = 1; i < 10; i++ )
{
const double pM[2] = { -1, 1 };
int randoid = rand( ) % 2;
for ( i = 1; i <= 10; i++ )
{
x2[i] = x[i] + pM[randoid] * 0.25; //Error Line
printf( "\nx[%d]==%2.2f", i, x[i] );
printf( "\nx2[%d]==%2.2f", i, x2[i] );
}
}
}
I am working on a project which need to find a certain number in a two dimensional array(a matrix) .the visiting order of matrix order is like this (4*4 matrix). Now I stand in the position 0. Equivalently, I want to visit the matrix element in diagonal firstly.
0 2 7 14
3 1 5 12
8 6 4 10
15 13 11 9
Besides, how to break two nest loop in c++ while do not use goto statement.
The following code will traverse a square matrix of any size, with priority on the diagonal
#define SIZE 4
static int test[SIZE][SIZE] =
{
{ 0, 2, 7, 14 },
{ 3, 1, 5, 12 },
{ 8, 6, 4, 10 },
{ 15, 13, 11, 9 }
};
int main( void )
{
int diagonal, delta;
for ( diagonal = 0; diagonal < SIZE; diagonal++ )
{
cout << test[diagonal][diagonal] << endl;
for ( delta = 1; delta <= diagonal; delta++ )
{
cout << test[diagonal-delta][diagonal] << endl;
cout << test[diagonal][diagonal-delta] << endl;
}
}
}
Here's one way to break out of a nested loop without a goto
done = false;
for ( i = 0; i < 10; i++ )
{
for ( j = 0; j < 10; j++ )
{
if ( some_condition_is_met )
{
done = true;
break;
}
}
if ( done )
break;
}
Use another array with array indices (since the size of your array is probably constant anyway), for instance, if you stored first array in one dimensional c++ array, then
int actual_arr[16];
int indices[16] = {0, 5, 1, 4, 10, 6, 9, 2, 8, 15, 11, 14, 7, 13, 3, 12 };
So then you can write a loop:
for (int i = 0; i < 16; ++i)
{
actual_arr[indices[i]]++;
}
So every field in indices is an index of actual_arr which will be visited at this point.
You can do it with two dimensional representation, too, if it required. Just replace int indices[16] with std::pair<int, int> indices[16] and you're good to go.
Especially when you have a fixed-size array and visit it many times, this is good solution, since it doesn't involve any computation in the loop.
Btw. As a sidenote, mathematically speaking, the indices array would be called a permutation and can be an operation in permutations group.
To move to the element on the right, you increment a row.
To move to the element on the left, you decrement a row.
To move to the element below, you increment a column.
To move to the element above, you decrement the column.
Now to move diagonally, observe how the row and columns change and apply a combination of the above.