I'm building a set of arrays where each element depends on the previous element, and I'm having a hard time coming up with an elegant solution for setting the initial value. The code looks something like this:
int A[1024];
int B[1024];
/* ... more arrays... */
int i;
for (i = 0; i < 1024; i++) {
/* do some work */
A[i] = A[i-1] + some_value();
B[i] = B[i-1] + some_other_value();
/* ... and so on... */
}
But of course this is an invalid memory access when i is 0. I know that the initial values of all arrays should be 0.
There are several ways to solve this problem. I could put a giant if statement in the loop to check if i is 0. Seems clunky since it will only evaluate to true once. I could keep a temporary variable, initialized to 0, for each array, called prev_val_of_A, etc, that holds the value of the last iteration. I'd have to update it to the current value at the end of every iteration. This seems a little silly since, most of the time, the value I want is sitting right there in the array's previous element. I could fiddle with the meaning of the array, and adopt the convention that the second element in the array contains the value for the first iteration of the loop; that is, allocate for A[1025], initialize A[0], then in the loop, do
A[i+1] = A[i] + some_value();
This seems confusing and might invite errors on further use of A.
I'm looking for clean, elegant suggestions to solve this issue.
The easiest way to solve this is to initialise A[0], B[0] etc and then start the loop from i = 1. i.e.
int A[1024];
int B[1024];
/* ... more arrays... */
int i;
A[0] = stuff();
B[0] = other_stuff();
/* etc */
for (i = 1; i < 1024; i++) {
/* do some work */
A[i] = A[i-1] + some_value();
B[i] = B[i-1] + some_other_value();
/* ... and so on... */
}
EDIT: And this is reasonably elegent, as it mirrors the mathematics: sequences are often defined by f(0) = x, f(n) = <stuff with f(n-1)> if n > 0)
What about the following:
int AX[1024+1];
int BX[1024+1];
int *A = AX+1, *B = BX+1;
AX[0] = 0;
BX[0] = 0;
/* ... more arrays... */
int i;
for (i = 0; i < 1024; i++) {
/* do some work */
A[i] = A[i-1] + some_value();
B[i] = B[i-1] + some_other_value();
/* ... and so on... */
}
Conceptually, your array is defined as an initial value and a reccurence relation. So just initialize your first element outside the loop, and then compute the next values with a loop. I don't see why it will not be pretty.
Related
I got this question on a job interview, and i could't solve it.
i think i was just really nervous because it doesn't look this hard.
Arr is a given integer array, size n. Sol is a given empty array,
size n.
for each i (i goes from 0 to n-1 ) you have to put in Sol[i] the index
in Arr of the closest elemnt appears on the left side, that is smaller
than Arr[i]. meaning: Sol[i]=max{ j | j < i; Arr[j] < Arr[i] }. if
the is no such index, put -1.
for example: Arr is [5,7,9,2,8,11,16,10,12] Sol is
[-1,0,1,-1,3,4,5,4,7]
time complexity: o(n) space complexity: o(n)
I tried to scan the array from the end to the start, but I didn't know how to continue.
I was asked to use only array and linked list.
I had 10 minutes to solve it, so guess it is not that hard.
thanks a lot!!
Note that for Arr[] with length < 2 there are trivial solutions. This pseudo code assumes that Arr[] has a length >= 2.
int Arr[] = {5,7,9,2,8,11,16,10,12};
int Sol[] = new int[9];
Stack<int> undecided; // or a stack implemented using a linked list
Sol[0] = -1; // this is a given
for(int i = Arr.length() - 1; i != 0; --i) {
undecided.push(i); // we haven't found a smaller value for this Arr[i] item yet
// note that all the items already on the stack (if any)
// are smaller than the value of Arr[i] or they would have
// been popped off in a previous iteration of the loop
// below
while (!undecided.empty() && (Arr[i-1] < Arr[undecided.peek()])) {
// the value for the item on the undecided stack is
// larger than Arr[i-1], so that's the index for
// the item on the undecided stack
Sol[undecided.peek()] = i-1;
undecided.pop();
}
}
// We've filled in Sol[] for all the items have lesser values to
// the left of them. Whatever is still on the undecided stack
// needs to be set to -1 in Sol
while (!undecided.empty()) {
Sol[undecided.peek()] = -1;
undecided.pop();
}
To be honest, I'm not sure I would have come up with this in an interview situation given a 10 minute time limit.
A C++ version of this can be found on ideone.com: https://ideone.com/VXC0yq
int Arr[] = {5,7,9,2,8,11,16,10,12};
int Sol[] = new int[9];
for(int i = 0; i < Arr.length; i++) {
int element = Arr[i];
int tmp = -1;
for(int j = 0 ;j < i; j++) {
int other = Arr[j];
if (other < element) {
tmp = j;
}
}
Sol[i] = tmp;
}
so my requirements are
REQUIRES: n >= 1. Elements a[0] ... a[n-1] exist.
PROMISES
The return value is 1 if n == 1.
If n > 1, the return value is 1 if a[0] ... a[n-1] form
an arithmetic sequence.
PROMISES
Otherwise, the return value is 0.
my function so far is
int is_arith_seq(const int *a, int n)
{
assert(n >= 1);
if (n == 1)
return 1;
int i;
int initaldif = a[1]-a[0];
int currentdif,result;
for (i=0;i<n;i++)
{
currentdif = a[i+1]-a[i];
if(initaldif!=currentdif)
return 0;
}
return 1;
}
My code does not work,as I am completely stuck now, what can I do to correct it.
If array has n elements your for loop will cause a segmentation fault. It goes all the way to n-1 but you are accessing a[i+1]. a[n] is out of bounds. Modify like this :
for (i = 0; i < n - 1; i++)
{
currentdif = a[i+1]-a[i];
if (initaldif != currentdif)
return 0;
}
Problem is here
currentdif = a[i+1]-a[i];
What do you think will happen to this code during n-1 th iteration?
i = n-1 + 1 = n
Therefore the function either returns 1 if n=1 or returns 0 due to the error!
Off-by-one errors are one of the most common programming mistakes. A good way to quickly track many of these down is to look at the very first and last iterations of your loops.
Your intent is that your loop computes the differences
a[1]-a[0] a[2]-a[1] ... a[n-1]-a[n-2]
The first iteration has i=0 and computes a[1]-a[0], and the last iteration has i=n-1 and computes a[n]-a[n-1]. Whoops, that's wrong! Need to adjust the loop.
Your arithmetic sequence test should set the initialdif as you have done, but then predict what the next element is throughout the sequence. If any term fails, the string of numbers is not an arithmetic sequence:
int initaldif = a[1]-a[0];
for (i = 2; i < n; i++)
if (a[i] != a[i-1] + initaldif)
return 0;
return 1;
I've created an array named a that can hold 100 double values,
double a[100];
I set the first element of the array a to NUM, which is a symbolic constant defined early in my code.
a[0] = NUM
I'm curious as to how I would write a for loop that sets each remaining value of a to the value of the preceding element plus 0.1. For example, the second element in the array is the first plus 0.1. I've tried doing
for(i=1; i<=99; i=+0.1)
But I think something is wrong with my initialization of i
Use i to index the array, not to store the value you should put on the array. Remember you can use expressions to access the array, like a[i - 1]
for (i = 1; i < 100; i++)
a[i] = a[i - 1] + 0.1;
int i;
for(i = 0; i < 100; i++)
a[i] = NUM + 0.1 * i;
dont forget to tell the type int !
int i = 0;
for(i = 0; i < 100; i++){
if (i == 0)
a[i] = NUM;
else
a[i] = a[i - 1] + .1;
}
Your array definition includes the step. So your array would run about 1000 times, at 1, 1.1, 1.2, but a[1.1] isn't a valid index of your array. Use i to index the array, and then retrieve the previous value to set the next.
From your question I can understand that this is one of your first program in C/C++, so I think that you need to start from basic things and learn how to do it properly, before doing it elegantly.
http://ideone.com/RGZgXL
for(i = 0; i < ARRAY_SIZE; i++) {
if(i == 0) { // if we are on the first element, set it to NUM
array[i] = NUM;
} else { // otherwise make the sum
array[i] = array[i-1] + STEP;
}
}
In the link you'll find the code and some comments that I hope will help you in understanding it.
Cheers
We are given a 2-dimensional array A[n,m] with n rows and m columns and an element of that array chosen at random R.
Think of the array as being circular in that when we visit A[n-1, m-1] the next element we visit would be A[0, 0].
Starting with element R, we want to visit each element exactly once and call function foo() before moving to the next element.
The following is my first implementation but there is a bug. The bug being that if we start at row x somewhere between 0 and n-1, we will not visit element from 0 to x-1 in that column.
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
// Look at each column once
for (int i = 0; i < m; ++i)
{
for (; curr_row < n; ++curr_row)
{
foo(A[curr_row][curr_col]);
}
curr_row = 0;
curr_col = (curr_col + 1) % m;
}
What is a clean way to do this traversal such that we meet the above requirements?
Just move to the next index, and check whether you are back at the start, in which case, stop:
// should be something that guarantees in-range indices
curr_row = rand();
curr_col = rand();
int i = curr_row, j = curr_col;
do {
foo(A[i][j]);
++j;
if (j == n) {
j = 0;
++i;
if (i == m) {
i = 0;
}
}
}while(i != curr_row || j != curr_col);
This doesn't do what your implementation does, but what the question title asks for.
quite rusty with c , but it should be the same:
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
//first row
for(int j=curr_col;j<m;++j)
foo(A[curr_row][j]);
//rest of the rows
for(int i=(curr_row+1)%n;i!=curr_row;i=(i+1)%n)
for(int j=0;j<m;++j)
foo(A[i][j]);
//first row , going over missed cells
for(int j=0;j<curr_col;++j)
foo(A[curr_row][j]);
if you care a lot about performance , you can also divide the second loop so that there won't be a "%" at all .
another alternative , since C has 2d arrays in a simple array:
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
int start=curr_row*m+curr_col;
int maxCell=n*m;
int end=(start-1)%maxCell;
for(int i=start;i!=end;i=(i+1)%maxCell)
foo(A[i]);
foo(A[end]);
could have a tiny math bug here and there ,but the idea is ok.
A[curr_row, curr_col] is not the syntax used to access a member of a multidimensional array; instead, you want A[curr_row][curr_col], assuming the array was declared correctly. A[curr_row, curr_col] will invoke the comma operator, which effectively computes the first value, then throws it away and calculates the second value, then indexes the array with that value.
say we are going to insert an element into an array on malloc. I know where and how to insert, but I'm having trouble shuffling every succeeding element down by 1. What would be the technical approach for this? Thanks
| x x x x x x x x x x x | original array
| x x x x x 0 x x x x x x | new array
Suppose the "memmove" function is not available to us...
Yes, if you need to do this without memmove, you can do it with a simple loop. Note that you might also need to use realloc first, to expand the size of the allocated array so that it can fit the new element.
The trick to this is having the loop move each element one forward, starting from the last one. A moment's reflection should tell you why this is necessary.
The basic principle is the same whether the array is dynamically allocated, statically allocated or automatically allocated. The main difference is that if there is insufficient room in a dynamically allocated array, you can reallocate it with more space (subject to some system-imposed limits. Assuming there is enough space in the array, you could use memmove() to copy the section of the array after target location up one space, and then set the target location to the inserted value. Or you could write a loop to do the job.
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
Now insert at position n = 2:
memmove(&dynarr[n+1], &dynarr[n], (idx - n) * sizeof(int));
dynarr[n] = 19;
idx++;
That's a bulk move, an assignment, and increment the counter because there's one more element in the array.
Since the question was edited to disallow memmove(), here is a solution with simple array indexing, assuming that the same initialization sequence is used:
int i;
int n = 2;
for (i = idx; i > n; i--)
{
dynarr[i] = dynarr[i-1];
}
dynarr[n] = 19;
idx++;
Complete example code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void print_array(int *a, int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("a[%d] = %d\n", i, a[i]);
}
}
int main()
{
{
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
printf("Before insert\n");
print_array(dynarr, idx);
int n = 2;
memmove(&dynarr[n+1], &dynarr[n], (idx - n) * sizeof(int));
dynarr[n] = 19;
idx++;
printf("After insert\n");
print_array(dynarr, idx);
free(dynarr);
}
{
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
printf("Before insert\n");
print_array(dynarr, idx);
int n = 2;
int i;
for (i = idx; i > n; i--)
{
dynarr[i] = dynarr[i-1];
}
dynarr[n] = 19;
idx++;
printf("After insert\n");
print_array(dynarr, idx);
free(dynarr);
}
return(0);
}
As Don suggested, memmove() will allow moving part of this array, in order to make room for the new element.
Depending on the size of the elements in the array, you may also consider storing only pointers, in the array, allowing easier/faster re-shuffling of the array, at the cost of a extra indirection when accessing individual elements. (and also at the cost of having to manage individual element-sized memory blocks). Deciding on this type of approach depends on the amount of reorganization of the array elements, as well as their size.
Alert: in view of the added "picture" in the question, memmove(), or indeed any operation, may be impossible, if the memory move implies writing past the size of memory originally allocated!
If this is really what is desired, the idea of an array of pointers may be more appropriate as this allows allocating an over-sized memory block initially (for the array proper) and to allocate (or dispose of) individual elements as needed.
Edit: "We're not allowed to use memmove()" indicates some form of homework. (BTW do tag it as such !!!)
To better help you we need to understand the particular premise of the question. Here's what appears to be the situtation:
1) we readily have an array, containing say N elements.
2) the array on the heap, i.e. it was allocated using malloc() (or related
functions)
3) the effective size of the malloc-ated block of memory is bigger than that of
the array.
Is #3 true ?
4) Depending on #3 we need to either allocate a new memory block (a bigger one)
and copy the array. We expect this copy would be done in 3 steps
- copy the elements that precede the new element
- copy the new element
- copy the elements that are after the new element
or... (if we have enough room), we'd require two steps
- "shift" the elements that are supposed to be after the new element
This can be done one element at a time, if we wish to avoid memcopy
- copy the new element.