error sliceShiftLeft() function - c

#include <stdio.h>
void sliceShiftLeft(int array[], int start, int end) {
if ( start < end ) {
int temp = array[end];
for ( int i = start + 1; i < end; i++ ) {
array[i] = array[i+1];
}
array[start] = temp;
}
}
int main() {
int start = 2;
int end = 5;
int size = 10;
int array[size];
for ( int i = 0; i < size; i++ ) {
array[i] = i;
}
for ( int i = 0; i < size; i++ ) {
printf("%d ", array[i]);
}
printf("\n");
printf("-------------------------\n");
sliceShiftLeft(array, start, end);
for ( int i = 0; i < size; i++ ) {
printf("%d ", array[i]);
}
printf("\n");
return 0;
}
problem is cycle in sliceShiftLeft() function.
i need 01 2345 6789 to be transformed to 01 5234 6789, but i keep getting 01 5455 6789.
my steps:
1) i put the last number in slice to the temp
2) i run cycle for which puts i+1 to i
3) i put the last number, which is in temp, to the first place.
where's my mistake?

If the desired output is the one you mentioned in your question then you are going the wrong way, you should:
store the last element in temp
move all element from start up to end - 1 to the right
store last element into start
While you are going exactly the opposite way, with the exception of third step. What happens is:
0123456789
0134556789 <- array[i] = array[i+1]
0154556789 <- array[start] = temp

your first error is here for(int i ... ) in the fist part of for you mustn't declare a variable but initialize one

Related

Remove the last comma from c loop

i have the belowo loop in c that print the prime number
for(int i = 2; i<=arraySize; i++)
{
//If arraySize is not 0 then it is prime
if (numbers[i]!=0)
printf("%d,",numbers[i]);
}
the out put after enter 50 for example is
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,
i want to to not print the last comma how i can do it
i tried this code but not working
printf("%d%s", numbers[i], (i !=arraySize-1) ? "," : "");
Instead of printing a comma after each number, print it before. Then you can use a variable to tell if this is the first number being printed, and not print the comma.
first=true;
for(int i = 2; i<=arraySize; i++)
{
//If numbers[i] is not 0 then it is prime
if (numbers[i]!=0) {
printf("%s%d", (first ? "" : ","), numbers[i]);
first = false;
}
}
I like both the other answers but just want to throw in this error prone variant on the same theme.
_Bool first = true;
for (int i = 2; i <= arraySize; i++) {
if (numbers[i] != 0) {
printf(",%d" + first, numbers[i]);
first = false;
}
}
If first is true the actual formatting string will become "%d". If it's false it'll become ",%d".
Simple: Use a pointer to the "prefix" string, printed AHEAD of the next value:
char *sep = "";
for(int i = 2; i <= arraySize; i++ ) {
if( numbers[i] ) {
printf( "%s%d", sep, numbers[i] );
sep = ", "; // I added a SP, too
}
}
Here's an alternative that uses a "limited scope" variable to index a static string. For clarity in this example, the array boundaries have been adjusted.
int main( void ) {
int numbers[] = { 1, 1, 4, 8, 9, 0, 7 };
int arraySize = sizeof numbers/sizeof numbers[0];
for( int i = 0, out = 0; i < arraySize; i++ )
if( numbers[i] )
printf("%s%d", &","[!out++], numbers[i] );
return 0;
}
The negated boolean post-incrementing value of out provides the address of the '\0' to the first instance, then the address of "," in subsequent instances.
1,1,4,8,9,7
The answers already here are fine, but I'd like to add a "simpler" solution. Simpler in that it doesn't require any further logic or extra variables. It does, however, require that you know that the first number is non-zero.
printf("%d", numbers[2]);
for (int i = 3; i < arraySize; i++)
{
if (numbers[i] != 0)
printf(",%d", numbers[i]);
}
I think the other answers overcomplicates things. I don't see any reason to have a test for every iteration in the loop. Instead, I'd simply do the special case first:
printf("%d", numbers[2]);
for (int i = 3; i <= arraySize; i++) {
if (numbers[i]!=0)
printf(",%d", numbers[i]);
}
This will however need some additional code to correctly handle the case where arraySize is lower than 3.
But I would choose another approach from the beginning, and that is writing a good function for printing an array. Could look like this:
void printArray(const int *array, int size) {
putchar('['); // Of course this is optional
if(size > 0) {
printf("%d", array[0]);
for(int i=1; i<size; i++)
printf(",%d", array[i]);
}
putchar(']'); // And this too
}
and then something like this:
int convertArray(const int *numbers, int *array, int size) {
int ret = 0;
for(int i=0; i<size; i++) {
if(number[i] != 0) {
array[ret] = numbers[i];
ret++;
}
}
return ret;
}

Reduce execution time of a code that uses binary search

The problem is to create an array of player ranks based on 2 other arrays: leaderboard and player scores. More explanations of the problem here: https://www.hackerrank.com/challenges/climbing-the-leaderboard/problem.
The code below is a spaghetti but it's working fine. But, for large size of ranked array(200000 elements for example), it times out. I'm not asking for code to copy/paste. I just wanna know if there is a way to optimize this code.
int* climbingLeaderboard(int ranked_count, int* ranked, int player_count, int* player, int* result_count) {
*result_count=player_count;
// remove duplicates
int removed=0;
for(int i=0, j=1; i<ranked_count-removed; i++, j++){
if(ranked[i]==ranked[j]){
for(int k=j; k<ranked_count-removed; k++)
ranked[k]=ranked[k+1];
removed++;
}
}
int newsize=ranked_count-removed;
// create an array to store ranks then fill it
int* positions=malloc(newsize*sizeof(int));
positions[0]=1;
for(int i=0, j=1; j<newsize; i++, j++){
positions[j]=(ranked[j]<ranked[i])? (positions[i]+1) : positions[i];
}
// create and fill the results array using binary search
int* res = malloc(player_count*sizeof(int));
int start=0, end=newsize-1, middle=(start+end)/2;
int j, k=newsize-1;
for(int i=0; i<player_count; i++){
if(i>0&&player[i]==player[i-1]){
*(res+i)=(*(res+(i-1)));
continue;
}
if(player[i]>=ranked[middle]){
*(res+i)=positions[middle];
j=middle-1;
while(j>=0){
if(player[i]>=ranked[j])
*(res+i)=positions[j];
else if(j==k)
*(res+i)=positions[j]+1;
else break;
--j;
}
start=0; end=middle-1;
}
else{
*(res+i)=positions[newsize-1]+1;
j=newsize-1;
while(j>=middle){
if(player[i]>=ranked[j])
*(res+i)=positions[j];
else if(j==k)
*(res+i)=positions[j]+1;
else break;
--j;
}
start=middle+1; end=newsize-1;
}
middle=(start+end)/2;
}
free(positions);
return res;
}
The initial loop to remove duplicates has a potential quadratic time complexity. You can achieve linear complexity using the 2 finger approach:
int removed = 0;
for (int i = 1, j = 1; j < ranked_count; j++) {
if (ranked[i - 1] != ranked[j])
ranked[i++] = ranked[j];
else
removed++;
}
More generally, the argument arrays should not be changed in spite of the sloppy prototype given:
int *climbingLeaderboard(int ranked_count, int *ranked,
int player_count, int *player,
int *result_count);
Here are simple steps I would recommend to solve this problem:
allocate and initialize a ranking array with the ranking for each of the scores in the ranked array. Be careful to allocate ranked_count + 1 elements.
allocate a result array res of length player_count, set the result_count to player_count.
starting with pos = ranked_count, for each entry i in player:
locate the position pos where the entry would be inserted in the ranking array using binary search between position 0 and the current pos inclusive. Make sure you find the smallest entry in case of duplicate scores.
set res[i] to ranking[pos]
free the ranking array
return the res array.
Here is a simple implementation:
int *climbingLeaderboard(int ranked_count, int *ranked,
int player_count, int *player,
int *result_count)
{
if (player_count <= 0) {
*result_count = 0;
return NULL;
}
int *ranking = malloc(sizeof(*ranking) * (ranked_count + 1));
int rank = 1;
ranking[0] = rank;
for (int i = 1; i < ranked_count; i++) {
if (ranked[i] != ranked[i - 1])
rank++;
ranking[i] = rank;
}
ranking[ranked_count] = rank + 1;
int *res = malloc(sizeof(*res) * player_count);
*result_count = player_count;
int pos = ranked_count;
for (int i = 0; i < player_count; i++) {
int start = 0;
while (start < pos) {
int middle = start + (pos - start) / 2;
if (ranked[middle] > player[i])
start = middle + 1;
else
pos = middle;
}
res[i] = ranking[pos];
}
free(ranking);
return res;
}
Look for ways to use "branchless" to improve execution speed:
positions[0]=1;
for(int i=0, j=1; j<newsize; i++, j++){
positions[j]=(ranked[j]<ranked[i])? (positions[i]+1) : positions[i];
}
becomes
positions[0] = 1;
for( int i = 0, j = 1; j < newsize; i++, j++ )
positions[j] = positions[i] + (ranked[j] < ranked[i]);
Other than this, I don't even want to try to sort out what this code is attempting.

Printing array as sub blocks

I have array and I am trying to print this array as sub blocks, where each block has size = 5.
the out put of this code not as I expected it just print the first 5 values. How to print the array as sub blocks?
int arr[298] = {some int values};
int in = 0;
int siz = 298;
int ii;
int rang = 5;
for (int i = 0; i < siz; i++) {
if (in <= siz) {
for (ii = in; ii < 5; ii++) {
printf("arr=%d \n", arr[ii]);
}
printf("------------\n");
}
ind = ind + rang;
}
Following your request for clarification in the comment section, there are a few problems with your code, for me the biggest one is that it's needlessly complicated, but the one you are looking for is in this line:
ind = ind + rang;
ind is is not declared in your code but I assume you mean in, the first time the inner loop runs in(ind) is 0 so it all goes well, after that in will be 5, you assign it to ii and the condition ii < 5 will never be true again, the body of the loop will never be executed.
I suppose you could fix it by using in as index for the array and scrap rang since it isn't needed, something like this:
int arr[298] = {some int values};
int in = 0;
int siz = 298;
for (int i = 0; i < siz; i++) {
//if (in < siz) { moving this into the for loop
for (int ii = 0; ii < 5 && in < siz; ii++, in++) {
printf("arr=%d \n", arr[in]);
}
printf("------------\n");
//}
}
Live demo: https://godbolt.org/z/YzG9sno1n
But you don't need a nested loop, there are a few ways you can do this, a simple one is to have a variable that controls the block size:
int arr[298] = {some int values};
int siz = 298;
int count = 5;
for (int i = 0; i < siz; i++) {
printf("arr=%d \n", arr[i]);
count--;
if (count == 0) {
printf("------------\n");
count = 5;
}
}
Live demo: https://godbolt.org/z/b4e8vWfhM
In the above code count serves as the control variable, the value in the index is printed 5 times and when it reaches 0 a separator is printed and it resets and starts the new block.
Another possible option is to use the index itself to separate the blocks, you know the remainder of a division is 0 when the numerator is divisible by the denominator, you can use that to your advantage:
int arr[298] = {some int values};
int siz = 298;
for (int i = 0; i < siz; i++) {
if (i % 5 == 0) { // && i != 0 if you want to skip the initial separator
printf("------------\n");
}
printf("arr=%d \n", arr[i]);
}
Live demo : https://godbolt.org/z/nne3z38rY
Finally you can/should use a constant value for size:
#include <stdio.h>
#define SIZE 298
int main() {
int arr[SIZE] = {some int values};
for (int i = 0; i < SIZE; i++) {
if (i % 5 == 0 && i != 0) { // skipping the initial separator
printf("------------\n");
}
printf("arr=%d \n", arr[i]);
}
}
Live demo: https://godbolt.org/z/Mc4Yh4cav
Instead of several for loops, you can use a single while loop.
int arr[298 ]={Some int Values};
int ind =0;
int siz= 298 ;
printf("------------\n");
while(ind<=siz-1){
printf("arr=%d \n",arr[ind]);
ind++;
if(ind%5==0){
printf("------------\n");
}
}
In this, you print the elements through 0 to 297, with a line of dashes printed if the index is divisible by 5, that is after every fifth element.

How to use a for loop index outside of for loop in C (selection sort)

I am trying to do a selection sort where I am going through a list of integers, picking out the smallest number, and swapping it with a bigger number earlier in the list. This code is just practicing with a short string of 4 integers. What I am struggling with is getting through the whole list of integers to find the smallest number before moving on. I found that this works great as its own nested for loop, but then I can't 'remember' at which index that smallest number was at when trying to swap integers (this would be the line of code that is commented out, as it will not know what 'j' is). If I attempt doing this within the for loop then I prematurely swap the first integer that is smaller than the one I am swapping with before seeing if there are any other smaller integers. Any tips in the right direction would be much appreciated. Thank you!
int main (void)
{
int tmp;
int n = 4;
int values[] = {5,3,4,1};
for (int i=0; i < n; i++)
{
int minimum = values[i];
for (int j=1; j < n; j++)
{
if (values[j]<minimum)
{
minimum=values[j];
}
}
tmp = values[i];
values[i] = minimum;
//values[j] = tmp;
}
}
You need to add a variable minimumIndex which is the index of the minimum value. Set it to j when you update the value of minimum, and it will give you the index of the minimum at the end of the loop. Make also to initialize it with a correct value: Since mimimum is initialized to values[i], minimumIndex should be initialized to i.
Note also that you have a bug: You start the inner loop at j=1, but it should start with i or i+1 so that you skip over the elements which have already been placed.
Just keep the index of the element with the minimal value. For example
#include <stdio.h>
int main ( void )
{
int values[] = { 5, 3, 4, 1 };
size_t n = sizeof( values ) / sizeof( *values );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", values[i] );
}
putchar( '\n' );
for ( size_t i = 0; i < n; i++ )
{
size_t minimum = i;
for ( size_t j = i + 1; j < n; j++ )
{
if ( values[j] < values[minimum] )
{
minimum = j;
}
}
if ( minimum != i )
{
int tmp = values[i];
values[i] = values[minimum];
values[minimum] = tmp;
}
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", values[i] );
}
putchar( '\n' );
}
Pay attention to that the index of the inner loop should start with the value i + 1.
for ( size_t j = i + 1; j < n; j++ )
^^^^^

Getting segmentation fault while implementing quick sort

I want to implement heap sort. For the purpose, I went through this http://faculty.simpson.edu/lydia.sinapova/www/cmsc250/LN250_Tremblay/L06-QuickSort.htm#basic tutorial and wrote the following code:
#include <stdio.h>
int quick_sort(int a[],int first,int last);
int main()
{
int a[]= {12,3,4,23,1,7,9,34,89,45};
int i;
printf("Enter 10 integers: \n");
for ( i = 0 ; i < 10 ; i++ )
{
scanf("%d",&a[i]);
printf("\t%d\n",a[i]);
}
for ( i = 0 ; i < 10 ; i++ )
{
printf("\n%d ",a[i]);
}
quick_sort(a,0,9);
for ( i = 0 ; i < 10 ; i++ )
{
printf("%d ",a[i]);
}
return 0;
}
int quick_sort(int a[],int first,int last)
{
int i,j,pivot,temp ;
if ( first - last <= 1 && first - last >= -1 )
{
return 0;
}
else
{
i = first ;
j = last ;
pivot = a[(i+j) / 2 ] ;
while ( i != j )
{
while ( a[i] < pivot )
{
i++;
}
while( a[j] > pivot )
{
j--;
}
temp = a[i] ;
a[i] = a[j] ;
a[j] = temp ;
}
}
quick_sort(a,0,i-1);
quick_sort(a,j+1,9);
return 0;
}
While running it using gcc compiler I am getting segmentation fault. Please help me to solve it.
There are several thing that in the question's quick_sort() function that are a mystery to me. Not that they are wrong; it's just that the purpose of various manipulations escapes me.
After working on it for a while, here is my version:
void quick_sort(int *a, int first, int last)
{
int i,j,pivot,temp;
if(last <= 1)
return;
pivot = a[first + last/2];
j = first + last/2;
temp = a[first];
a[first] = a[j];
a[j] = temp;
j = first;
for(i = first+1; i < first+last; i++)
{
if(a[i] < pivot)
{
j++;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
temp = a[first];
a[first] = a[j];
a[j] = temp;
quick_sort(a, first, j-first);
quick_sort(a, j+1, first+last-j-1);
return;
}
Working spoiler testcase here.
I'd try:
quick_sort(a,first,i-1);
quick_sort(a,j+1,last);
Instead of:
quick_sort(a,0,i-1);
quick_sort(a,j+1,9);
It at least allows the sort to work for lists different than 10 values....
You also need to check if i != j after every change, so I think that's problematic in your code as well. Or at least use i than j and the while would NEVER end.

Resources