C program circular array rotation terminated due to timeout - c

So i´m trying to solve a hackerrank problem (C language) where you perform k array[n] rotations, and at the end, ask for a m and print array[m].
My program is probably correct (it runs perfectly for most of tests, but some of them terminate due to timeout) , but inefficient, don´t know how to improve it.
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int main(){
int n;
int k;
int q;
scanf("%d %d %d",&n,&k,&q);
int *a = malloc(sizeof(int) * n);
int *b = malloc(sizeof(int) * n);
for(int a_i = 0; a_i < n; a_i++){
scanf("%d",&a[a_i]);
}
for(int i = 0; i < k; i++){
b[0] = a[n-1];
for(int a_i = 1; a_i < n; a_i++){
b[a_i] = a[a_i-1];
}
for(int a_i = 0; a_i < n; a_i++) a[a_i] = b[a_i];
}
for(int a0 = 0; a0 < q; a0++){
int m;
scanf("%d",&m);
printf("%d\n", b[m]);
}
return 0;
}

This looks more like an algorithms question. From what I gather, your program:
reads an array of size n;
rotates the array k positions to the right;
prints q positions from the resulting array.
The complexity is O(kn + q) because each of the k rotations is done in linear time.
You can do step 2 with just one rotation. Copy the last k elements from a to the beginning of b and the first n-k elements from a to the end of b. This decreases the complexity to O(n + q).
You can further optimize the program by skipping step 2 altogether. When looking up position m in step 3, just look at a[k - m] (and wrap around if k < m). This decreases the complexity to O(q).

Related

Why a wrong number of 1 is printed?

My function should randomly insert a user-chosen number of 1 into my matrix. The difficulty lies in the fact that if a cell contains a 1 the cells around it must be set to 0. Why my code print a wrong number of 1? In the code below I had thought to first set the entire matrix to 0, then randomly generate a cell to be set to 1, after having checked it contains 0 and the distance between this cell and other cells containing 1 is >= 1. All this is done until the number m entered by the user becomes 0.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void initialize(int n, int a[n][n]);
void createMap(int n, int a[n][n], int m);
int check (int i, int j, int v, int w);
void print(int n, int a[n][n]);
int main(){
int n;
printf("Insert square matrix size: ");
scanf("%d", &n);
int m;
printf("Insert 1s number: ");
scanf("%d", &m);
int a[n][n];
initialize(n,a);
createMap(n,a,m);
}
//Filling the matrix with 0
void initialize(int n, int a[n][n]){
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
a[i][j] = 0;
}
}
}
//Setting in random position 1 value
void createMap(int n, int a[n][n], int m){
int x1; int x2;
int b[0][0];
while (m > 0){
int i = rand() % n;
int j = rand() % n;
if (a[i][j] == 0 && (check(i,j,x1,x2) == 1)){
a[i][j] = 1;
m--;
//I have to fill b array with coordinates and then to pass
//b array to check function to do the check in the whole b array
}
}
print(n,a);
}
//checking if I can set the value to 1
int check (int x1, int y1, int x2, int y2){
if (sqrt(pow((x1-x2),2) + pow((y1-y2),2)) >= 1){
return 1;
} else {
return 0;
}
}
//Printing the matrix
void print(int n, int a[n][n]){
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
printf("\t%d",a[i][j]);
}
puts("");
}
}
After generating the coordinates i and j, you should calculate the distance between that cell and the other cells set to 1. You can use the Manhattan formula to do that.
If the distance between the newly generated cell and the other cells set to 1 is grater than or equal to 1, you can go ahead and generate the other ones, otherwise you should set it back to zero and generate new coordinates.
This is homework right?
A few issues:
You have a variable matrix that you don't use.
You set a[k][l] = 1; before you know what the old value was, and therefore can't tell if m should be incremented or not.
Your bounds checking is messy, it is difficult to see if it is correct, and if you update m and all array elements around a[k][l] correctly. Nobody wants to look at messy code, unless they get paid. They will just assume that it is wrong. So that part of the code is by definition wrong, and nobody can tell you why.
Your bounds checking assumes you have a 4x4 array.
... and a few others.
Point 1 is easy to fix, and it is not important. It just adds to the ugliness of your code.
Point 2 is solved by only updating a[k][l] and m if a[k][l] was zero:
if (a[k][l] == 0)
{
a[k][l] = 1;
m--;
}
Point 3 can be most easily fixed by creating a separate function that does resetting of single array elements with bounds checking. Since I assume this is homework, I am not going to write this for you, unless you have made an honest try yourself first. The function signature could look like this:
/*
Set value of `a[line][column]` to zero and increment `*m` if value
was changed.
Nothing is done if `line` or `column` are out of bounds.
*/
void matrix_element_reset(int n, a[n][n], int line, int column, int *m);
You can then easily reset array elements around a[k][l] like this:
/* This can be simplified with loops */
matrix_element_reset(n, a, k-1, l, &m);
matrix_element_reset(n, a, k, l, &m);
matrix_element_reset(n, a, k+1, l, &m);
.....
Point 4: Your variable n stores the dimension of your matrix. Use it.

Hackerrank circular array rotation segmentation faults

My following code sucessfully runs in sample input but gives segmentation faults in 13 test cases.
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int main(){
int n;
int k;
int q;
int index[q];
scanf("%d %d %d",&n,&k,&q);
int *a = (malloc(sizeof(int) * n));
for(int a_i = 0; a_i < n; a_i++){
scanf("%d",&a[a_i]);
}
for(int a0 = 0; a0 < q; a0++){
int m;
scanf("%d",&m);
index[a0] = m;
}
for(int i=0; i<k; i++){
int ap = a[n-2];
for(int p=1; p<n-1; p++){
a[p] = a[p-1];
}
a[0] = a[n-1];
a[n-1] = ap;
}
for(int j=0; j<q;j++){
printf("%d\n", a[index[j]]);
}
return 0;
}
I am unable to find where the segmentation fault is. Also check out this:where I asked about declaring a as a pointer using malloc
There might have been chances that using malloc() to declare a would have lead to segmentation faults since it does not check for allocation error, but even when i defined a as an array the problem still remained.
q is not initialized, but is used as the argument to the declaration of an array.
You should use malloc to allocate the index array, after reading the value of q.

QuickSort doesnt sort .... C

Why doesn't my QuickSort work properly? Meaning it doesn't sort out the values from the array. Here's is my output for a simple 5-elements array:
unsorted array, it's OK then:
A[0] = 8
A[1] = 1
A[2] = 45
A[3] = 78
A[4] = 234
but this is a sorted array, at least according to my code :
A[0] = 8
A[1] = 234
A[2] = 45
A[3] = 78
A[4] = 1
and the code
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <math.h>
void printOutAnArray(int *A, int n)
{
int i;
for(i=0; i<n; i++)
{
printf("A[%d] = %d\n", i, A[i]);
}
}
void swap(int *i, int *j)
{
int t = *i;
*i = *j;
*j = t;
}
int partition(int A[], int p, int r)
{
int x = A[p];
int i = p;
int j = r+1;
while (true)
{
do j --; while (A[j] <= x);
do i ++; while(A[i] >= x);
if (i < j)
swap(&A[i], &A[j]);
else
return j;
}
}
void Quicksort(int A[], int p, int r)
{
if (p < r)
{
int q = partition(A,p,r);
Quicksort(A, p, q-1);
Quicksort(A, q+1, r);
}
}
int main(int argc, char **argv)
{
int A[] = {8, 1, 45, 78, 234};
int n = 5;
printOutAnArray(A, n);
printf("\n");
Quicksort(A, 0, n-1);
printOutAnArray(A, n);
return 0;
}
Well, it does not sort because it is implemented incorrectly. Some obvious issues with partition
The partitioning element has to be moved to the position between the partitions eventually. You never do that. I see that you use the very first element of the subarray (i.e. A[p]) as partitioning element. And it remains in the very first position. You never move it anywhere else.
For example, in the very first call to partition you use 8 as partitioning element. But you never relocate that 8 from A[0] position. A typical implementation would usually swap that element into its final position between partitions.
The conditions in those small do/while cycles seem to be tailored to descending sort. Were you planning to do a descending sort? Or did you simply mix up the conditions?
Those small do/while cycles seem to be prone to array bounds overrun. Just think what will happen if your original array consists of identical elements.

Moving parts right in two - dimensional matrix

I would like to get your help to understand and finish my program.
This is what I have to do:
"You must exercise program that:
First. An absorbing two - dimensional integer arr [M] [N]. M - number of rows N - number of columns. (Matrix size was received from the user)
Two. The program uses auxiliary functions "shift" moves the values ​​of the matrix to the right one place, as shown in the picture (2 entered instead of 1, 3 instead of 2, 4 instead of 3, ... 20 instead of 19, first place 20).
Shift have to write a function and call her three times in the sample matrix loop .."
Example
My problems are:
I don't know how to do the matrix two - dimensional integer arrays that there size is entered by the user. I only know by DEFINE SIZE of the row and the cols
My function isn't close to the real deal so I would like to get help finish my function.
My output:
My code:
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#define M 4
#define N 5
void shift (int arr[M][N], int length);
void main()
{
int arr[M][N];
int i,j,length;
printf("Enter %d rows \n",M);
for (i=0 ; i<M ; i++ )
{
printf("Enter %d numbers:\n",N);
for(j=0 ; j<N ; j++ )
{
scanf("%d" , &arr[i][j] );
}
length=N+M;
}
shift (arr,length);
system("pause");
return ;
}
void shift (int arr[M][N], int length)
{
int i,j,temp;
temp=arr[0][0];
for(i=0; i<M; i++)
{
for(j=0; j<N-1 ; j++)
{
printf("%d ",arr[i][j]);
}
arr[i][j]=temp;
printf("\n");
}
}
Edit: pictures resized
Shifts all columns to the right.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void shift_columns_right(int M[100][100], int rows, int cols) {
int tmp_lastcol;
int j, k;
for (j = 0; j<rows; j++){
tmp_lastcol = M[j][cols-1];
for (k = cols-1; k > 0; k-- ){
M[j][k] = M[j][k-1];
}
M[j][0] = tmp_lastcol;
}
}
int main(void){
int B[100] [100] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16},
{17,18,19,20},
};
shift_columns_right(B,5,4);
return 0;
}
I will you give a hint as how to shift the elements. The logic is to swap the elements between the current and last element in the row as you iterate. I will show you a working example on 1D array.
#include <stdio.h>
#define ARRAY_SIZE 5
int main()
{
int a[ARRAY_SIZE] = {11,22,33,44,55};
int i;
for (i=0; i<ARRAY_SIZE; ++i)
{
int temp = a[i];
a[i] = a[ARRAY_SIZE-1];
a[ARRAY_SIZE-1] = temp;
}
for(i=0; i<ARRAY_SIZE; ++i)
{
printf("%d\t",a[i]);
}
return 0;
}
Output: 55 11 22 33 44
To dynamically allocate the memory for array, use malloc. Hope it helps !

Segmentaion fault in C when doing matrix multiplication

I use gsl random generator to generate 2 big matrices, and use gsl cblas to multiply them, but I always got Segmentation fault when the cblas operation begins. When I can't solve this, I then write the code below, using the very basic idea to do matrix multiplication, and I still got Segmentation Fault, but all the two can work all right when matrix is really a small one, I'm really puzzled about this.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#define PI 3.1415926
void GenerateKey(int m, int n, int l, int q, float alpha)
{
// initialization
int i;
int j;
int k;
float *A;
float *S;
float *E;
float *B;
float sigma = (alpha * q ) / sqrt(2 * PI);
A=(float*)malloc(sizeof(float)*(m*n));
S=(float*)malloc(sizeof(float)*(n*l));
B=(float*)malloc(sizeof(float)*(m*l));
E=(float*)malloc(sizeof(float)*(m*l));
// init A
for(i = 0; i < m*n; i++)
{
A[i]=0;
}
printf("\n");
// init S
for(i = 0; i < n*l; i++)
{
S[i]=0;
}
printf("\n");
// init E
for(i = 0; i < m*l; i++)
{
E[i]=0;
}
printf("\n");
float po;
for(i = 0; i < m; i++)
{
for(j=0; j<l; j++)
{
po=0;
for(k=0; k<n; k++)
{
po +=A[i*m+k]*S[k*n+j];
}
po += E[i*m +j];
B[i*m+j]=((int)po) % q;
}
}
printf("Game over");
printf("\n");
free(A);
free(B);
free(S);
free(E);
}
int main()
{
GenerateKey(2680,191,64,72973,0.000551);
return 0;
}
When you're doing i*m+j, shouldn't that be i*l+j ? Similarly with i*m+k should be i*l+k and k*n+j should be k*l+j
The reason being, take for example E = (float*)malloc(sizeof(float)*(m*l)), so you have m rows and l columns (or vise versa), so if you are iterating over the m dimension you need to be multiplying your m iterator (i in this case) by the stride of your matrix in that dimension, which is l.
You don't check the malloc() return values, so my guess is that one or more allocation is failing and you're dereferencing NULL. Another possibility is of course an indexing error, so you acccess out of bounds.
You incorrectly compute an element index for all the matrices.
When you have an MxN matrix which is allocated as an 1-dimensional array, the index for an element (i,j) is i*N+j. Instead, you're computing it as i*M+j.

Resources