I am currently trying to teach myself C++ and programming in general. So as a beginner project i'm making a genetic algorithm that creates an optimal AI for a Tic-Tac-Toe game. I am not enrolled in any programming classes so this is not homework. I'm just really interested in AI.
So i am trying to create a multidimensional array of a factorial, in my case 9! . For example if you made one of 3! it would be array[3][6] = { {1, 2, 3}, {1, 3, 2}, {2, 3, 1}, {2, 1, 3}, {3, 2, 1}, {3, 1, 2}}. Basically 3! or 3*2*1 would be the amount of ways you could arrange 3 numbers in order.
I think that the solution should be simple yet im stuck trying to find out how to come up with a simple solution. I have tried to swap them, tried to shift them right, increment ect.. the methods that work are the obvious ones and i don't know how to code them.
So if you know how to solve it that's great. If you can give a coding format that's better . Any help is appreciated.
Also i'm coding this in c++.
You can use next_permutation function of STL
http://www.cplusplus.com/reference/algorithm/next_permutation/
I actually wrote an algorithm for this by hand once. Here it is:
bool incr(int z[NUM_INDICES]){
int a=NUM_INDICES-1;
for(int i=NUM_INDICES-2;i>=0;i--)
if(z[i]>z[i+1]) a--;
else break;
if(a==0) return false;
int b=2147483647,c;
for(int i=a;i<=NUM_INDICES-1;i++)
if(z[i]>z[a-1]&&z[i]-z[a-1]<b){
b=z[i]-z[a-1];
c=i;
}
int temp=z[a-1]; z[a-1]=z[c]; z[c]=temp;
qsort(z+a,NUM_INDICES-a,sizeof(int),comp);
return true;
}
This is the increment function (i.e. you have an array like [3,2,4,1], you pass it to this, and it modifies it to [3,4,1,2]). It works off the fact that if the last d elements of the array are in descending order, then the next array (in "alphabetical" order) should satisfy the following conditions: 1) the last d+1 elements are a permutation among themselves; 2) the d+1-th to last element is the next highest element in the last d+1 elements; 3) the last d elements should be in ascending order. You can see this intuitively when you have something like [2,5,3, 8,7,6,4,1]: d = 5 in this case; the 3 turns into the next highest of the last d+1 = 6 elements; and the last d = 5 are arranged in ascending order, so it becomes [2,5,4, 1,3,6,7,8].
The first loop basically determines d. It loops over the array backwards, comparing consecutive elements, to determine the number of elements at the end that are in descending order. At the end of the loop, a becomes the first element that is in the descending order sequence. If a==0, then the whole array is in descending order and nothing more can be done.
The next loop determines what the d+1-th-to-last element should be. We specified that it should be the next highest element in the last d+1 elements, so this loop determines what that is. (Note that z[a-1] is the d+1-th-to-last element.) By the end of that loop, b contains the lowest z[i]-z[a-1] that is positive; that is, z[i] should be greater than z[a-1], but as low as possible (so that z[a-1] becomes the next highest element). c contains the index of the corresponding element. We discard b because we only need the index.
The next three lines swap z[a-1] and z[c], so that the d+1-th-to-last element gets the element next in line, and the other element (z[c]) gets to keep z[a-1]. Finally, we sort the last d elements using qsort (comp must be declared elsewhere; see C++ documentation on qsort).
If you want a hand crafted function for generating all permutations, you can use
#include <cstdio>
#define REP(i,n) FOR(i,0,n)
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define GI ({int t;scanf("%d",&t);t;})
int a[22], n;
void swap(int & a, int & b) {
int t = a; a = b; b = t;
}
void perm(int pos) {
if(pos==n) {
REP(i,n) printf("%d ",a[i]); printf("\n");
return;
}
FOR(i,pos,n) {
swap(a[i],a[pos]);
perm(pos+1);
swap(a[pos],a[i]);
}
return;
}
int main (int argc, char const* argv[]) {
n = GI;
REP(i,n) a[i] = GI;
perm(0);
return 0;
}
Related
I was trying to implement a sorting code so i tried something completely without looking at any other reference codes or anything. Please tell me why my code doesnt show any output? It just runs for sometime and then stops suddenly.
I want to know where i am going wrong. I wanted to take any array as an input and sort the numbers in it in ascending order. So i just iterated throughput the array and compared adjacent elements and swaped them. Then i tried printing the numbers using their indices but it did not print anything on the screen.
#include <iostream>
using namespace std;
int main() {
int arr[6]={1,23,2,32,4,12};
int i=0;
while(i<6)
{
if(arr[i]>arr[i+1])
{
int x = arr[i];
arr[i]=arr[i+1];
arr[i+1]=x;
}
else
continue;
i++;
}
cout<<arr[0];
cout<<arr[1];
cout<<arr[2];
cout<<arr[3];
cout<<arr[4];
cout<<arr[5];
return 0;
}
I expected that the numbers will be printed in ascending order but nothing happened. And also tell me how to print an array all at once.
Thank you
Your sorting algorithm doesn't work because it performs only one pass of a variant of Bubble Sort or Insertion Sort. There has to be one more loop wrapped around your loop to repeat the operation N-1 times.
There are a number of ways to explain why multiple passes are required. Here is one explanation. Whenever we perform this step:
if (arr[i] > arr[i+1])
{
int x = arr[i];
arr[i] = arr[i+1];
arr[i+1] = x;
}
we transfer the arr[i+1] element into the arr[i] position. By doing so, we effectively skip the arr[i+1] element.
Here is what I mean. Suppose arr[i] is called x, arr[i+1] is called y and arr[i+2] is called z. We start with xyz, and exchange x and y to make yxz. But then on the next iteration of the loop, we compare x and z and have forgotten about y; x has moved forward in the array, pushing down y. Why is that a problem? Because y and z have not been compared; and those two are not necessarily in sorted order!
Suppose we have { 3, 2, 0 }. We compare 3 and 2, and swap them, giving us { 2, 3, 0}. Then we move on to comparing 3 and 0: we swap those and get { 2, 0, 3 }. See the problem? We neglected to deal with 2 and 0. That requires another pass through the array.
There is a family of algorithms which work by repeatedly scanning through an array and exchanging items. I suggest studying the following of the common algorithms in this family: insertion sort, selection sort and Shell sort. Also look at bubble sort, in order to understand why it's a poor algorithm compared to either insertion or selection sort that it is closely related to.
your loop condition is incorrect - the last iteration will compare arr[5] and arr[6] which gives index out of bound.
you update your iterator "i" only if you swap, so if your loop encounters the case where arr[i] <= arr[i+1], your iterator will never get updated and your program will run infinitely.
your algorithm implements just a first iteration of bubble sort i.e. it bubbles up (from left to right) the largest number and stops. so the final array looks like [1, 2, 23, 4, 12, 32]
I have been trying a sorting method in which I subtract each number stored in an array by other elements in the same array. Then, I saw a pattern that the number of differences which come to be negative, is the rank or position of element in the Sorted one. But, things go wrong when I am using repeated entries.
My basic method is :
Take every element of the SampleArray.
subtract it from every element of the SampleArray
check if the difference comes to be negative.
if it is then, increase a variable called counter.
And use this counter as the position of element in sorted array.
For example: lets take (5,2,6,4)
first take 5, subtract it from each of the numbers which will give results (0,-3,1,-1), so counter will become 2, which will be the index of 5 in the sorted Array. And repeat it for each of the elements.
for 5, counter will be 2.
for 2, counter will be 0.
for 6, counter will be 3.
for 4, counter will be 1.
And hence the sorted Array will be {2,4,5,6}.
First, see the code :
#include <iostream>
using namespace std;
void sorting(int myArray[], int sizeofArray);
int main()
{
int checkArray[] = {5,4,2,20,12,13,8,6,10,15,0}; //my sample Arry
int sized;
sized=sizeof checkArray/sizeof(int);//to know the size
cout << sized << endl;
sorting(checkArray, sized);
}
void sorting(int myArray[], int sizeofArray)
{
int tempArray[sizeofArray];
for (int i=0; i<sizeofArray; i++)
{
int counter=0;
for (int j=0;j<sizeofArray; j++ )
{
int checkNum = myArray[j]-myArray[i];
if (checkNum<0)
counter++; //to know the numbers of negatives
else
counter+=0;
}
tempArray[counter]=myArray[i];
}
for (int x=0;x<sizeofArray; x++)
{
cout << tempArray[x] << " " ;
}
}
Now, if we run this program with entries with no repetitions then, it sorts out the array, But if we use repeated entries like
int checkArray[] = {8,2,4,4,6}
the tempArray gets its first element as 2 as counter will be zero.
the tempArray gets its second element as 4 as counter will be 1.
but, the tempArray can't get its third one as counter will be still 1, and thus prints some randomNo in place of this. (here the things go wrong).
Can you please suggest a method to solve this?
This is an odd way of writing insertion sort, https://en.wikipedia.org/wiki/Insertion_sort
I would assume you can change your condition to:
if (checkNum<0 || (checkNum==0 && j<i))
But I would suggest using a proper sorting routine instead
The idea is to separate duplicates by saying that if the values are the same we sort according to their order in the sequence; as if the sequence was a pair of the value and the sequence number (0, 1, 2, 3, 4, 5, ...).
The issue here is that for any 2 equally sized numbers the nested loop will return the same counter value. Thus for such a counter value tempArray[counter + 1] will never be initialized.
The way to solve this would be to maintain a vector<bool> denoting what each position had been written and write to the next valid position if that is the case.
But supporting a second vector is just going to make your O(n2) code slower. Consider using sort instead:
sort(begin(checkArray), end(checkArray))
I have two integer arrays
int A[] = {2, 4, 3, 5, 6, 7};
int B[] = {9, 2, 7, 6};
And i have to get intersection of these array.
i.e. output will be - 2,6,7
I am thinking to sove it by saving array A in a data strcture and then i want to compare all the element till size A or B and then i will get intersection.
Now i have a problem i need to first store the element of Array A in a container.
shall i follow like -
int size = sizeof(A)/sizeof(int);
To get the size but by doing this i will get size after that i want to access all the elemts too and store in a container.
Here i the code which i am using to find Intersection ->
#include"iostream"
using namespace std;
int A[] = {2, 4, 3, 5, 6, 7};
int B[] = {9, 2, 7, 6};
int main()
{
int sizeA = sizeof(A)/sizeof(int);
int sizeB = sizeof(B)/sizeof(int);
int big = (sizeA > sizeB) ? sizeA : sizeB;
int small = (sizeA > sizeB) ? sizeB : sizeA;
for (int i = 0; i <big ;++i)
{
for (int j = 0; j <small ; ++j)
{
if(A[i] == B[j])
{
cout<<"Element is -->"<<A[i]<<endl;
}
}
}
return 0;
}
Just use a hash table:
#include <unordered_set> // needs C++11 or TR1
// ...
unordered_set<int> setOfA(A, A + sizeA);
Then you can just check for every element in B, whether it's also in A:
for (int i = 0; i < sizeB; ++i) {
if (setOfA.find(B[i]) != setOfA.end()) {
cout << B[i] << endl;
}
}
Runtime is expected O(sizeA + sizeB).
You can sort the two arrays
sort(A, A+sizeA);
sort(B, B+sizeB);
and use a merge-like algorithm to find their intersection:
#include <vector>
...
std::vector<int> intersection;
int idA=0, idB=0;
while(idA < sizeA && idB < sizeB) {
if (A[idA] < B[idB]) idA ++;
else if (B[idB] < A[idA]) idB ++;
else { // => A[idA] = B[idB], we have a common element
intersection.push_back(A[idA]);
idA ++;
idB ++;
}
}
The time complexity of this part of the code is linear. However, due to the sorting of the arrays, the overall complexity becomes O(n * log n), where n = max(sizeA, sizeB).
The additional memory required for this algorithm is optimal (equal to the size of the intersection).
saving array A in a data strcture
Arrays are data structures; there's no need to save A into one.
i want to compare all the element till size A or B and then i will get intersection
This is extremely vague but isn't likely to yield the intersection; notice that you must examine every element in both A and B but "till size A or B" will ignore elements.
What approach i should follow to get size of an unkown size array and store it in a container??
It isn't possible to deal with arrays of unknown size in C unless they have some end-of-array sentinel that allows counting the number of elements (as is the case with NUL-terminated character arrays, commonly referred to in C as "strings"). However, the sizes of your arrays are known because their compile-time sizes are known. You can calculate the number of elements in such arrays with a macro:
#define ARRAY_ELEMENT_COUNT(a) (sizeof(a)/sizeof *(a))
...
int *ptr = new sizeof(A);
[Your question was originally tagged [C], and my comments below refer to that]
This isn't valid C -- new is a C++ keyword.
If you wanted to make copies of your arrays, you could simply do it with, e.g.,
int Acopy[ARRAY_ELEMENT_COUNT(A)];
memcpy(Acopy, A, sizeof A);
or, if for some reason you want to put the copy on the heap,
int* pa = malloc(sizeof A);
if (!pa) /* handle out-of-memory */
memcpy(pa, A, sizeof A);
/* After you're done using pa: */
free(pa);
[In C++ you would used new and delete]
However, there's no need to make copies of your arrays in order to find the intersection, unless you need to sort them (see below) but also need to preserve the original order.
There are a few ways to find the intersection of two arrays. If the values fall within the range of 0-63, you can use two unsigned longs and set the bits corresponding to the values in each array, then use & (bitwise "and") to find the intersection. If the values aren't in that range but the difference between the largest and smallest is < 64, you can use the same method but subtract the smallest value from each value to get the bit number. If the range is not that small but the number of distinct values is <= 64, you can maintain a lookup table (array, binary tree, hash table, etc.) that maps the values to bit numbers and a 64-element array that maps bit numbers back to values.
If your arrays may contain more than 64 distinct values, there are two effective approaches:
1) Sort each array and then compare them element by element to find the common values -- this algorithm resembles a merge sort.
2) Insert the elements of one array into a fast lookup table (hash table, balanced binary tree, etc.), and then look up each element of the other array in the lookup table.
Sort both arrays (e.g., qsort()) and then walk through both arrays one element at a time.
Where there is a match, add it to a third array, which is sized to match the larger of the two input arrays (your result array can be no larger than the largest of the two arrays). Use a negative or other "dummy" value as your terminator.
When walking through input arrays, where one value in the first array is larger than the other, move the index of the second array, and vice versa.
When you're done walking through both arrays, your third array has your answer, up to the terminator value.
I have found a code for LIS in a book, I am not quite able to work out the proof for correctness . Can some one help me out with that. All the code is doing is deleting the element next to new inserted element in the set if the new element is not the max else just inserting the new element.
set<int> s;
set<int>::iterator it;
for(int i=0;i<n;i++)
{
s.insert(arr[i]);
it=s.find(arr[i]);
it++;
if(it!=s.end())
s.erase(it);
}
cout<<s.size()<<endl;
n is the size of sequence and arr is the sequence. I dont think the following code will work if we dont have to find "strictly" increasing sequences . Can we modify the code to find increasing sequences in which equality is allowed.
EDIT: the algorithm works only when the input are distinct.
There are several solutions to LIS.
The most typical is O(N^2) algorithm using dynamic programming, where for every index i you calculate "longest increasing sequence ending at index i".
You can speed this up to O(N log N) using clever data structures or binary search.
Your code bypasses this and only calculated the length of the LIS.
Consider input "1 3 4 5 6 7 2", the contents of the set at the end will be "1 2 4 5 6 7", which is not the LIS, but the length is correct.
Proof should go using induction as follows:
After i-th iteration the j-th smallest element is the smallest possible end of increasing sequence of the length j in the first i elements of the array.
Consider input "1 3 2". After second iteration we have set "1 3", so 1 is smallest possible end of increasing sequence of length 1 and 3 is smallest possible end of increasing sequence of length 2.
After third iteration we have set "1 2", where now the 2 is smallest possible end of increasing sequence of length 2.
I hope you can do induction step by yourself :)
The proof is relatively straightforward: consider set s as a sorted list. We can prove it with a loop invariant. After each iteration of the algorithm, s[k] contains the smallest element of arr that ends an ascending subsequence of length k in the sub-array from zero to the last element of arr that we have considered so far. We can prove this by induction:
After the first iteration, this statement is true, because s will contain exactly one element, which is a trivial ascending sequence of one element.
Each iteration can change the set in one of two ways: it could expand it by one in cases when arr[i] is the largest element found so far, or replace an existing element with arr[i], which is smaller than the element that has been there before.
When an extension of the set occurs, it happens because the current element arr[i] can be appended to the current LIS. When a replacement happens at position k, the index of arr[i], it happens because arr[i] ends an ascending subsequence of length k, and is smaller than or is equal to the old s[i] that used to end the previous "best" ascending subsequence of length k.
With this invariant in hand, it's easy to see that s contains as many elements as the longest ascending subsequence of arr after the entire arr has been exhausted.
The code is a O(nlogn) solution for LIS, but you want to find the non-strictly increasing sequence, the implementation has a problem because the std::set doesn't allow duplicate element. Here is the code that works.
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
int main()
{
int arr[] = {4, 4, 5, 7, 6};
int n = 5;
multiset<int> s;
multiset<int>::iterator it;
for(int i=0;i<n;i++)
{
s.insert(arr[i]);
it = upper_bound(s.begin(), s.end(), arr[i]);
if(it!=s.end())
s.erase(it);
}
cout<<s.size()<<endl;
return 0;
}
Problem Statement:
For A(n) :a0, a1,….an-1 we need to find LIS
Find all elements in A(n) such that, ai<aj and i<j.
For example: 10, 11, 12, 9, 8, 7, 5, 6
LIS will be 10,11,12
This is O(N^2) solution based on DP.
1 Finding SubProblems
Consider D(i): LIS of (a0 to ai) that includes ai as a part of LIS.
2 Recurrence Relation
D(i) = 1 + max(D(j) for all j<i) if ai > aj
3 Base Case
D(0) = 1;
Check out link for the code:
https://innosamcodes.wordpress.com/2013/07/06/longest-increasing-subsequence/
For example:
array[] = {3, 9, 10, **12**,1,4,**7**,2,**6**,***5***}
First, I need maximum value=12 then I need maximum value among the rest of array (1,4,7,2,6,5), so value=7, then maxiumum value of the rest of array 6, then 5, After that, i will need series of this values. This gives back (12,7,6,5).
How to get these numbers?
I have tried the following code, but it seems to infinite
I think I'll need a recursive function but how can I do this?
max=0; max2=0;...
for(i=0; i<array_length; i++){
if (matrix[i] >= max)
max=matrix[i];
else {
for (j=i; j<array_length; j++){
if (matrix[j] >= max2)
max2=matrix[j];
else{
...
...for if else for if else
...??
}
}
}
}
This is how you would do that in C++11 by using the std::max_element() standard algorithm:
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
int arr[] = {3,5,4,12,1,4,7,2,6,5};
auto m = std::begin(arr);
while (m != std::end(arr))
{
m = std::max_element(m, std::end(arr));
std::cout << *(m++) << std::endl;
}
}
Here is a live example.
This is an excellent spot to use the Cartesian tree data structure. A Cartesian tree is a data structure built out of a sequence of elements with these properties:
The Cartesian tree is a binary tree.
The Cartesian tree obeys the heap property: every node in the Cartesian tree is greater than or equal to all its descendants.
An inorder traversal of a Cartesian tree gives back the original sequence.
For example, given the sequence
4 1 0 3 2
The Cartesian tree would be
4
\
3
/ \
1 2
\
0
Notice that this obeys the heap property, and an inorder walk gives back the sequence 4 1 0 3 2, which was the original sequence.
But here's the key observation: notice that if you start at the root of this Cartesian tree and start walking down to the right, you get back the number 4 (the biggest element in the sequence), then 3 (the biggest element in what comes after that 4), and the number 2 (the biggest element in what comes after the 3). More generally, if you create a Cartesian tree for the sequence, then start at the root and keep walking to the right, you'll get back the sequence of elements that you're looking for!
The beauty of this is that a Cartesian tree can be constructed in time Θ(n), which is very fast, and walking down the spine takes time only O(n). Therefore, the total amount of time required to find the sequence you're looking for is Θ(n). Note that the approach of "find the largest element, then find the largest element in the subarray that appears after that, etc." would run in time Θ(n2) in the worst case if the input was sorted in descending order, so this solution is much faster.
Hope this helps!
If you can modify the array, your code will become simpler. Whenever you find a max, output that and change its value inside the original array to some small number, for example -MAXINT. Once you have output the number of elements in the array, you can stop your iterations.
std::vector<int> output;
for (auto i : array)
{
auto pos = std::find_if(output.rbegin(), output.rend(), [i](int n) { return n > i; }).base();
output.erase(pos,output.end());
output.push_back(i);
}
Hopefully you can understand that code. I'm much better at writing algorithms in C++ than describing them in English, but here's an attempt.
Before we start scanning, output is empty. This is the correct state for an empty input.
We start by looking at the first unlooked at element I of the input array. We scan backwards through the output until we find an element G which is greater than I. Then we erase starting at the position after G. If we find none, that means that I is the greatest element so far of the elements we've searched, so we erase the entire output. Otherwise, we erase every element after G, because I is the greatest starting from G through what we've searched so far. Then we append I to output. Repeat until the input array is exhausted.