How to implement infinite multidimensional array? - c++

I want to use the code below and I want to use it for "unknown size of input". For example there is an array int cac[1000][1000]. I can use vector<vector<int> > array;, then how can i initialize it with -1 ? Any suggestions?
#include <sstream>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <memory.h>
using namespace std;
int cac[1000][1000];
string res[1000][1000];
vector<string> words;
int M;
int go(int a, int b){
if(cac[a][b]>= 0) return cac[a][b];
if(a == b) return 0;
int csum = -1;
for(int i=a; i<b; ++i){
csum += words[i].size() + 1;
}
if(csum <= M || a == b-1){
string sep = "";
for(int i=a; i<b; ++i){
res[a][b].append(sep);
res[a][b].append(words[i]);
sep = " ";
}
return cac[a][b] = (M-csum)*(M-csum);
}
int ret = 1000000000;
int best_sp = -1;
for(int sp=a+1; sp<b; ++sp){
int cur = go(a, sp) + go(sp,b);
if(cur <= ret){
ret = cur;
best_sp = sp;
}
}
res[a][b] = res[a][best_sp] + "\n" + res[best_sp][b];
return cac[a][b] = ret;
}
int main(int argc, char ** argv){
memset(cac, -1, sizeof(cac));
M = atoi(argv[1]);
string word;
while(cin >> word) words.push_back(word);
go(0, words.size());
cout << res[0][words.size()] << endl;
}

What you can do is to use a associative array, where the key is a pair (rowPosition, ColumnPosition). When you want to set array[i][j] you just add or update the value assoArray[Pair(i,j)]. You can assume that any element which is not in the associative array has the initial value.
In general infinite multidimensional arrays are used for theoretical purpose.I hope i didn't misunderstood the question.

Using std::vector from the STL is much more straightforward than the following solution, which was pointed out in the comments for this post. I find that this site explains that topic effectively: http://www.learncpp.com/cpp-programming/16-2-stl-containers-overview/
An array of infinite size is not actually possible. However, you can achieve basically that effect using dynamic allocation. Here's some sample code:
int counter = 0;
int* myArray = new int[1000];
Fill the array with data, incrementing counter each time you add a value. When counter reaches 1000, do the following:
int* largerArray = new int[2000];
for( int i = 0; i < 1000; i++ )
{
largerArray[i] = myArray[i];
}
delete[] myArray;
myArray = largerArray;
With this method, you create the closest thing possible to an infinitely sized array, and I don't believe performance will be an issue with the copy piece

Related

How to find the minimun of an array?

I was trying to solve this question
but codechef.com says the answer is wrong.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int t, n, diff, mindiff;
cin >> t;
cin >> n;
int val[n];
while(t--)
{
mindiff = 1000000000;
for(int i = 0; i<n; i++)
{
cin >> val[i];
}
int a = 0;
for(a = 0; a<n ; a++)
{
for(int b=a+1; b<n ; b++)
{
diff = abs(val[a] - val[b]);
if(diff <= mindiff)
{
mindiff = diff;
}
}
}
cout << mindiff << endl;
}
return 0;
}
The results are as expected (for at least the tests I did) buts the website says its wrong.
There are a few things in your code that you should change:
Use std::vector<int> and not variable-length arrays (VLA's):
Reasons:
Variable length arrays are not standard C++. A std::vector is standard C++.
Variable length arrays may exhaust stack memory if the number of entries is large. A std::vector gets its memory from the heap, not the stack.
Variable length arrays suffer from the same problem as regular arrays -- going beyond the bounds of the array leads to undefined
behavior. A std::array has an at() function that can check boundary access when desired.
Use the maximum int to get the maximum integer value.
Instead of
mindif = 1000000000;
it should be:
#include <climits>
//...
int mindiff = std::numeric_limits<int>::max();
As to the solution you chose, the comments in the main section about the nested loop should be addressed.
Instead of a nested for loop, you should sort the data first. Thus finding the minimum value between two values is much easier and with less time complexity.
The program can look something like this (using the data provided at the link):
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
int main()
{
int n = 5;
std::vector<int> val = {4, 9, 1, 32, 13};
int mindiff = std::numeric_limits<int>::max();
std::sort(val.begin(), val.end());
for(int a = 0; a < n-1 ; a++)
mindiff = std::min(val[a+1] - val[a], mindiff);
std::cout << mindiff;
}
Output:
3
To do this you can use a simple for():
// you already have an array called "arr" which contains some numbers.
int biggestNumber = 0;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] > biggestNumber) {
biggestNumber = arr[i];
}
}
arr.size will get the array's length so that you can check every value from the position 0 to the last one which is arr.size() - 1 (because arrays are 0 based in c++).
Hope this helps.

How do I delete a particular element in an integer array given an if condition?

I'm trying to delete all elements of an array that match a particular case.
for example..
if(ar[i]==0)
delete all elements which are 0 in the array
print out the number of elements of the remaining array after deletion
what i tried:
if (ar[i]==0)
{
x++;
}
b=N-x;
cout<<b<<endl;
this works only if i want to delete a single element every time and i can't figure out how to delete in my required case.
Im assuming that i need to traverse the array and select All instances of the element found and delete All instances of occurrences.
Instead of incrementing the 'x' variable only once for one occurence, is it possible to increment it a certain number of times for a certain number of occurrences?
edit(someone requested that i paste all of my code):
int N;
cin>>N;
int ar[N];
int i=0;
while (i<N) {
cin>>ar[i];
i++;
}//array was created and we looped through the array, inputting each element.
int a=0;
int b=N;
cout<<b; //this is for the first case (no element is deleted)
int x=0;
i=0; //now we need to subtract every other element from the array from this selected element.
while (i<N) {
if (a>ar[i]) { //we selected the smallest element.
a=ar[i];
}
i=0;
while (i<N) {
ar[i]=ar[i]-a;
i++;
//this is applied to every single element.
}
if (ar[i]==0) //in this particular case, we need to delete the ith element. fix this step.
{
x++;
}
b=N-x;
cout<<b<<endl;
i++;
}
return 0; }
the entire question is found here:
Cut-the-sticks
You could use the std::remove function.
I was going to write out an example to go with the link, but the example form the link is pretty much verbatim what I was going to post, so here's the example from the link:
// remove algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::remove
int main () {
int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20
// bounds of range:
int* pbegin = myints; // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
pend = std::remove (pbegin, pend, 20); // 10 30 30 10 10 ? ? ?
// ^ ^
std::cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n';
return 0;
}
Strictly speaking, the posted example code could be optimized to not need the pointers (especially if you're using any standard container types like a std::vector), and there's also the std::remove_if function which allows for additional parameters to be passed for more complex predicate logic.
To that however, you made mention of the Cut the sticks challenge, which I don't believe you actually need to make use of any remove functions (beyond normal container/array remove functionality). Instead, you could use something like the following code to 'cut' and 'remove' according to the conditions set in the challenge (i.e. cut X from stick, then remove if < 0 and print how many cuts made on each pass):
#include <iostream>
#include <vector>
int main () {
// this is just here to push some numbers on the vector (non-C++11)
int arr[] = {10,20,30,30,20,10,10,20}; // 8 entries
int arsz = sizeof(arr) / sizeof(int);
std::vector<int> vals;
for (int i = 0; i < arsz; ++i) { vals.push_back(arr[i]); }
std::vector<int>::iterator beg = vals.begin();
unsigned int cut_len = 2;
unsigned int cut = 0;
std::cout << cut_len << std::endl;
while (vals.size() > 0) {
cut = 0;
beg = vals.begin();
while (beg != vals.end()) {
*beg -= cut_len;
if (*beg <= 0) {
vals.erase(beg--);
++cut;
}
++beg;
}
std::cout << cut << std::endl;
}
return 0;
}
Hope that can help.
If you have no space bound try something like that,
lets array is A and number is number.
create a new array B
traverse full A and add element A[i] to B[j] only if A[i] != number
assign B to A
Now A have no number element and valid size is j.
Check this:
#define N 5
int main()
{
int ar[N] = {0,1,2,1,0};
int tar[N];
int keyEle = 0;
int newN = 0;
for(int i=0;i<N;i++){
if (ar[i] != keyEle) {
tar[newN] = ar[i];
newN++;
}
}
cout<<"Elements after deleteing key element 0: ";
for(int i=0;i<newN;i++){
ar[i] = tar[i];
cout << ar[i]<<"\t" ;
}
}
Unless there is a need to use ordinary int arrays, I'd suggest using either a std::vector or std::array, then using std::remove_if. See similar.
untested example (with c++11 lambda):
#include <algorithm>
#include <vector>
// ...
std::vector<int> arr;
// populate array somehow
arr.erase(
std::remove_if(arr.begin(), arr.end()
,[](int x){ return (x == 0); } )
, arr.end());
Solution to Cut the sticks problem:
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
// Cuts the sticks by size of stick with minimum length.
void cut(vector<int> &arr) {
// Calculate length of smallest stick.
int min_length = INT_MAX;
for (size_t i = 0; i < arr.size(); i++)
{
if (min_length > arr[i])
min_length = arr[i];
}
// source_i: Index of stick in existing vector.
// target_i: Index of same stick in new vector.
size_t target_i = 0;
for (size_t source_i = 0; source_i < arr.size(); source_i++)
{
arr[source_i] -= min_length;
if (arr[source_i] > 0)
arr[target_i++] = arr[source_i];
}
// Remove superfluous elements from the vector.
arr.resize(target_i);
}
int main() {
// Read the input.
int n;
cin >> n;
vector<int> arr(n);
for (int arr_i = 0; arr_i < n; arr_i++) {
cin >> arr[arr_i];
}
// Loop until vector is non-empty.
do {
cout << arr.size() << endl;
cut(arr);
} while (!arr.empty());
return 0;
}
With a single loop:
if(condition)
{
for(loop through array)
{
if(array[i] == 0)
{
array[i] = array[i+1]; // Check if array[i+1] is not 0
print (array[i]);
}
else
{
print (array[i]);
}
}
}

copying elements from one array to another

I am getting a crash error at run time and not sure what exactly to do with the function or how to get the data for it.
FUNCTION DETAILS
Write a function that accepts an int array and size as arguments, then create a new array that is one element bigger than the given. Setting the first element to 0, then copying over what is in the argument array to the new array.
MAIN DETAILS
Use in a program reading int n from input, then read int n from file data name data
passing it to element shifter, then printing it to output (one per line).
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int element_shift(int elmts[], int size) {
int new_size = size + 1;
int shifter[new_size];
int *elmt_sft;
shifter[0] = 0;
for (int i = 1; i >= new_size; i++) {
shifter[i + 1] = elmts[i];
}
return *elmt_sft;
}
int main() {
fstream infile;
infile.open("D:\\data.txt");
int n, x;
infile >> x;
cout << "size of array: ";
cin >> n;
const int ARRAY_SIZE = n + x;
int elements[ARRAY_SIZE];
element_shift(elements, ARRAY_SIZE);
system("PAUSE");
return EXIT_SUCCESS;
}
First of all ARRAY_SIZE declared in the main function is not a constant variable but defined at run-time depending on user inputs. This means that the array elements should be created dynamically. On the other hand you read some x variable which is only used to define the size of the array and didn't initialized the array at all. I guess that the problem statement is to read the size of the array from the input, then the data of the array from the file.
There are also lot of mistakes in element_shift function.
Your code should look like something similar to this:
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
void element_shift(int* elmts, int size)
{
int new_size = size + 1;
int* shifter = new int[new_size];
shifter[0] = 0;
for(int i = 0; i < size; ++i)
{
shifter[i + 1] = elmts[i];
}
delete [] elmts;
elmts = shifter;
}
int main()
{
fstream infile;
infile.open("D:\\data.txt");
int n;
cout << "size of array: ";
cin >> n;
int* elements = new int[n];
for (int i = 0; i < n; ++i) {
infile >> elements[i];
}
element_shift(elements, n);
for (int i = 0; i < n; ++i) {
std::cout << elements[i] << std::endl;
}
return EXIT_SUCCESS;
}
First off, you spend alot of time creating the shifted array but don't return it back.
int element_shift(int elmts[], int size) {
int new_size = size + 1;
int shifter[new_size];
int *elmt_sft;
shifter[0] = 0;
for (int i = 1; i >= new_size; i++) {
shifter[i + 1] = elmts[i];
}
return *elmt_sft;
}
The elmt_sft pointer is never assigned. You are trying to access memory that is not there by using *elmt_sft. This may be causing your error. Also this function has no way of returning the new array shifter because that variable is locally declared and will disappear once the function exits. If you want to create something new in the function and still have it in memory once the function exits, I recommend creating the array dynamically and returning a pointer to it.
This is untested but should start you in the right direction. It will return a separate dynamically allocated array that will not override your other one.
int* element_shift(int elmts[], int size) {
int *result_array = new int[size + 1]; //dynamically create new array MAKE SURE TO DELETE
result_array[0] = 0; //set 0 index to 0
for (int i = 1; i < size + 1; i++)//start at 1 of the result and put value in
{
result_array[i] = elmts[i - 1];
}
return result_array; //returning pointer
}

vector subscript out of range error in c++

I am trying to write a program that takes an input of of n integers, and finds out the one that occurs the maximum number of times in the given input. I am trying to run the program for t cases.
For this, I have implemented a counting sort like algorithm (perhaps a bit naiive), that counts the number of occurrences of each number in the input. In case there are multiple numbers with the same maximum occurrence, I need to return the smaller among those. For this, I implemented sorting.
The issue I am facing is, that every time I run the program on Visual C++, I am getting an error that tells "vector subscript out of range". Under Netbeans, it is generating a return value of 1 and exiting. Please help me find the problem
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int findmax(vector<int> a, int n)
{
int i,ret;
ret = 0;
for ( i = 0; i <n; i++)
{
if (a[i] > ret) {
ret = a[i];
}
}
return ret;
}
int main() {
int i = 0, j = 0, k = 0, n,m,r1,r2;
vector<int> a;
int t;
vector<int> buff;
cin>>t;
while(t--) {
cin>>n;
a.clear();
buff.clear();
for ( i = 0; i < n; i++) {
cin>>a[i];
}
sort(a.begin(),a.end());
m = findmax(a,n);
for ( j = 0; j < m+1; j++) {
buff[a[j]] = buff[a[j]] + 1;
}
k = findmax(buff,m+1);
for ( i = 0; i < m+1; i++) {
if (buff[i] == k) {
r1 = i;
r2 = buff[i];
break;
}
}
cout<<r1<<" "<<r2<<endl;
}
return 0;
}
After a.clear() the vector doesn't have any members, and its size is 0.
Add a call to a.resize(n) to make it the proper size. You also need to resize buff to whatever size it needs to be.
this line it's the culprit:
cin>>a[i];
you must use push_back:
cin >> temp;
a.push_back(temp);
or resize(n) before:
cin>>n;
a.resize(n);
for ( i = 0; i < n; i++) {
cin>>a[i];
}
then you should pass you vector by reference to findmax
int findmax(vector<int> &a, int n)
...
This isn't how you populate an array.
cin>>a[i];
You need to use the push_back() method or pre-allocate the appropriate size.
The problem is that you're illegally using indexes of your vector that don't exist (you never add any items to the vector). Since you know the size, you can resize it after you clear it:
a.clear();
a.resize(n);
buff.clear();
buff.resize(n);
for ( i = 0; i < n; i++) {
cin>>a[i];
}
will be out of range. The vector, as you construct it, has zero size.

Better way to use a pointer?

I'm trying to create a program that will display bar graphs with * the maximum number of * can be 40. I have everything working but had a question with the code. Is there a better way as you can see I have to go back to the original address twice using:
p_bar_length = p_bar_length - size;
Is there a better way to do this?
#include <iostream>
using namespace std;
const int MAX_SPLATS = 40;
void bar_chart(double values[], int size)
{
double largest = values[0]; //assign first element to be the largest
//Find the largest value
for (int i = 1; i < size; i++)
{
if (largest < values[i]) // check to see if there is something larger
{
largest = values[i];
}
}
// Find the number of spalts to use
// with the precent based on the largest value
int* p_bar_length = new (nothrow) int[size];
for (int i = 0; i < size; i++)
{
*p_bar_length = (values[i] / largest) * MAX_SPLATS;
p_bar_length++; // Go to next memory address
}
// Go back to the orignal memory address
p_bar_length = p_bar_length - size;
// Pritnt the correct number of splats
for (int i = 0; i < size; i++)
{
for (int j = 0; j < *p_bar_length; j++)
{
cout << "*";
}
p_bar_length++;
cout << endl;
}
// Go back to the orignal memory address
p_bar_length = p_bar_length - size;
delete[] p_bar_length;
}
int main()
{
double values[6] = { 22, 40, 28, 26, 14, 46};
int val_size = 6;
bar_chart(values, val_size);
system("pause");
return 0;
}
Since this is C++, the best way is not to use pointers; instead, use a std::vector.
That said, you can also always treat a pointer as an array and just access p_bar_length[i] for a given position 0 <= i < length instead of incrementing the pointer.
Rather than incrementing the pointer, use the array index:
p_bar_length[i] = (values[i] / largest) * MAX_SPLATS;
or use pointer arithmetic:
*(p_bar_length + i) = (values[i] / largest) * MAX_SPLATS;
You do not need the first for loop if you use std::max_element from <algorithm>.
You do not need the second for loop if you calculate the bar length in the third for loop.
Something like this:
void bar_chart(double values[], int size)
{
//Find the largest value
double largest = *std::max_element(values, values + size);
// Print the correct number of splats
for (int i = 0; i < size; i++)
{
int p_bar_length = (values[i] / largest) * MAX_SPLATS;
cout << string(p_bar_length, '*') << endl;
}
}
That way you don't need the p_bar_length array at all. It is only a simple int.
Edit: And you could even replace the inner for loop (example modified)
Since you tagged this as C++ I would recommend using the standard library.
Your program is more C than C++, but if c is ok for you there is not much to improve.
On the other hand, using vector and algorithm you don't need to mess around with pointers. And using C++11 it removes the rough edges previously associated with templates and iterators.
A quick shot:
#include <iostream>
#include <vector>
#include <algorithm>
const int MAX_SPLATS = 40;
template <typename C>
void bar_chart(const C& values)
{
if (std::distance(values.begin(), values.end())<1)
return; // do some error handling
auto largest = *std::max_element(values.begin(), values.end());
// Find the number of splats to use with the percent based on
// the largest value
std::vector<int> bars(values.size());
std::transform(values.begin(), values.end(), bars.begin(),
[=] (double d) { return (d/largest)*MAX_SPLATS; });
// Print the correct number of splats
std::for_each(bars.begin(), bars.end(),
[](int val){ std::cout << std::string(val, '*') << std::endl; });
}
int main()
{
std::vector<double> values = { 22, 40, 28, 26, 14, 46 };
bar_chart(values);
std::cin.get();
return 0;
}
Make another copy of the pointer to use within your loop. Much less error prone.
int* p_bar_length = new (nothrow) int[size];
int* p = p_bar_length;
for (int i = 0; i < size; i++)
{
*p = (values[i] / largest) * MAX_SPLATS;
p++; // Go to next memory address
}
P.S. Why are you using nothrow? Since you're not checking the value you get back from new, an exception will be much nicer than the mess you'll have when you get back a NULL pointer.
You could treat p_bar_length as an array and just use consistent notation
int* p_bar_length = new (nothrow) int[size];
for (int i = 0; i < size; i++)
{
p_bar_length[i] = (values[i] / largest) * MAX_SPLATS;
}
How about two in one?
int* p_bar_length = new (nothrow) int[size];
for (int i = 0; i < size; i++)
{
*p_bar_length = (values[i] / largest) * MAX_SPLATS;
for (int j = 0; j < *p_bar_length; j++) cout << "*";
cout << endl;
p_bar_length++; // Go to next memory address
}
This is rather similar to the post from #mkaes, but goes one step further. Instead of using std::transform to create a vector of the proper lengths, then std::for_each to create a string the proper length from each of those, this creates a string directly from the input, and writes the strings directly from std::transform:
#include <iostream>
#include <array>
#include <algorithm>
#include <string>
#include <iterator>
const int MAX_SPLATS = 40;
template <typename C>
void bar_chart(const C& values)
{
if (std::distance(values.begin(), values.end())<1)
return; // do some error handling
auto largest = *std::max_element(values.begin(), values.end());
std::transform(values.begin(), values.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
[=](double d) { return std::string((d/largest)*MAX_SPLATS, '*');} );
}
int main() {
std::array<double, 6> values = {22, 40, 28, 26, 14, 46};
bar_chart(values);
return 0;
}
Since it's using C++11 anyway, I decided to also use an std::array since it seems to fit nicely for the job at hand.