I want to delete multiple elements from array using index array,this is my code:
// b is an index array, n is size of b,
// player is the array need to be delete elements,
// size is the size of player
void play_cards(int b[],int n,int player[],int *size){
int i;
for(i = 0; i < n; i++)
delete_cards(b[i],player,size);
}
void delete_cards(int n,int player[],int *size){
int i;
for(i = n; i < *size; i++)
player[i] = player[i+1];
*size -= 1;
}
int main(void){
int player[10] = {1,2,3,3,4,4,5,5,6,7};
int index[6] = {2,3,4,5,6,7};
int size = 10;
play_cards(index,6,player,&size);
for(int i = 0; i < size; i++)
printf("%d|",player[i]);
puts("");
return 0;
}
I expect print the player should be 1,2,6,7 instead of 1,2,3,4. How should I fix it?
First I would not call the function delete_cards as it suggests that it deletes multiple cards which it does not - just delete_card would make things more clear.
Anyway - when you change the player array before you have played all cards in the index array, you change the meaning of the indexes. This is why your current code doesn't work.
So you can do two things:
a) Play all cards first and then delete the cards played. This could be done by first marking played card with -1 and then have a loop where you removed all element being -1
or
b) Play a card, delete it and adjust the remaining elements in index by decrementing them by one. Note: This solution requires that index is sorted (lowest first).
Solution a) could look something like this:
void delete_played_cards(int player[],int *size)
{
int i;
int next_pos = 0;
int deleted = 0;
for(i = 0; i < *size; i++)
{
if (player[i] != -1)
{
player[next_pos] = player[i];
if (i != next_pos)
{
player[i] = -1;
}
++next_pos;
}
else
{
++deleted;
}
}
*size -= deleted;
}
void play_cards(int b[],int n,int player[],int *size)
{
int i;
for(i = 0; i < n; i++)
{
player[b[i]] = -1; // Mark card as played
}
delete_played_cards(player,size);
}
int main(void)
{
int player[10] = {1,2,3,3,4,4,5,5,6,7};
int index[6] = {2,3,4,5,6,7};
int size = 10;
play_cards(index,6,player,&size);
for(int i = 0; i < size; i++)
printf("%d|",player[i]);
puts("");
return 0;
}
Modify play_cards:
void play_cards(int b[], int n, int player[], int *size)
{
int i;
for(i = n-1; i >= 0; i--)
delete_cards(b[i],player,size);
}
This will start deleting from the end of array.
As BLUEPIXY mentioned.
here is a pseudocode that you can work with:
given a sorted list, 1..n
for i = 2 up to length of list:
if list[i] is equal to list[i-1]:
shift the sublist [2..] 1 position to the left
else
increment i by 1
If you want to delete easily and efficiently without using loop you can use memcpy
#include <stdio.h>
#include <string.h>
#define INDEX_MAX 6
int main ()
{
int size = 10;
int src[] = {1,2,3,3,4,4,5,5,6,7};
int index[] = {2,3,4,5,6,7};
int x;
size = size - INDEX_MAX;
memcpy(src+2, src+8, sizeof(int)*(size-2));// - 2 since index 1 and 2 remains in the array
for(x = 0; x < size; x++){
printf("%d",src[x]);
}
return(0);
}
Related
For my studies, I have to write a C function GetEvenNumber:
parameters: array with n integers + array size;
returns tr array which contains even integers from td.
I don't know a priori the length of the array tr.
My below code returns errors:
#include <stdio.h> // define the header file
int *GetEvenNumber(int t[], int size)
{
int tr[];
int j = 0;
for (int i = 0; i < size; i++)
{
if (t[i] % 2 == 0)
{
printf("%d is even \n", t[i]);
tr[j] = t[i];
j++;
}
}
return tr;
}
int main() // define the main function
{
int *t; // = {4, 3, 1, 8, 6 };
int *tr = GetEvenNumber(t, 5);
for (int i = 0; i < 5; i++)
printf("%d \n", tr[i]);
}
I get error:
error: array size missing in 'tr'
int tr[];
warning: function returns address of local variable [-Wreturn-local-addr]
return tr;
How do I fix that? Thanks.
You mentioned that you could not use malloc() to dynamically create tr within GetEvenNumber() to address the two issues raised by your copmiler. This leaves making tr a global variable, or as here pass in the result array tr to be filled out:
#include <stdio.h>
#include <stdlib.h>
void GetEvenNumber(size_t size, const int *td, size_t *size2, int *tr) {
*size2 = 0;
for(size_t i=0; i<size; i++)
if(td[i] % 2 == 0)
tr[(*size2)++] = td[i];
}
int main() {
int td[] = {4, 3, 1, 8, 6 };
size_t size = sizeof(td) / sizeof(*td);
int tr[size];
size_t size2;
GetEvenNumber(size, td, &size2, tr);
for (size_t i=0; i < size2; i++)
printf("%d \n", tr[i]);
}
If the input array td contains uneven elements, then the result array tr have fewer valid elements than the input. I used size2 here to tell caller how many elements are valid in tr. Your code did not assign any values to, in this example, last 3 elements. You don't tell us what should happen with those last elements.
In modern C, if you specify the size before the array in the argument, then you can use the size in array specification which help document what is going on.
The error is due to
int tr[];
because you have to specify the size of your array during its creation.
I suggest trying to add a function that returns the number of even numbers in the array:
int getEvenNum(int t[], int lent){
int numEven = 0; // initialize counter to zero
for(int i = 0; i < lent; i++){ // for each element of the array
if ((t[i] % 2) == 0){ // if it's even,
numEven++; // add 1 to counter
}
}
return(numEven); // finaly returns the value of the counter
}
and then you replace the int tr[]; by int tr[getEvenNum(t, size)]; (maybe there's a ; after the getEvenNum(t, size) but I'm not sure)
Since the array tr can have AT MOST the same number of elements as the original integer array, it would be safe to declare the array with the same size as the array 't[]'.
I have made some changes to your code. Try the following:
#include<stdio.h> // define the header file
void GetEvenNumber(int *t, int* tr, int size, int *pCountEven)
{
int i, j=0;
for (i=0; i < size; i++)
{
if(t[i]%2==0)
{
printf("%d is even \n", t[i]);
tr[j++] = t[i];
}
}
*pCountEven = j;
}
int main() // define the main function
{
int t[] = {4, 3, 1, 8, 6 };
int tr[5], countEven = 0, i;
GetEvenNumber(t, tr, 5, &countEven);
for (i=0; i < countEven; i++)
printf("%d\n", tr[i]);
return 0;
}
Edit: As #chqrlie (who is an experienced coder) pointed out, we can simply return the length of the array instead of taking the address of a variable.
So alternatively, you can try this:
#include <stdio.h> // define the header file
int GetEvenNumber(int *t, int *tr, int size) {
int i, j = 0;
for (i = 0; i < size; i++) {
if (t[i] % 2 == 0) {
printf("%d is even \n", t[i]);
tr[j++] = t[i];
}
}
return j;
}
int main() // define the main function
{
int t[] = { 4, 3, 1, 8, 6 };
int tr[5], countEven = 0, i;
countEven = GetEvenNumber(t, tr, 5);
for (i = 0; i < countEven; i++)
printf("%d\n", tr[i]);
return 0;
}
So based in the following problem from cumulative sum query I created the solution. But is any other way to solve the problem in C with linear complexity O(N)?
Problem description:
William Macfarlane wants to look at an array.
You are given a list of N numbers and Q queries. Each query is
specified by two numbers i and j; the answer to each query is the sum
of every number between the range [i, j] (inclusive).
Note: the query ranges are specified using 0-based indexing.
Input
The first line contains N, the number of integers in our list (N <=
100,000). The next line holds N numbers that are guaranteed to fit
inside an integer. Following the list is a number Q (Q <= 10,000). The
next Q lines each contain two numbers i and j which specify a query
you must answer (0 <= i, j <= N-1). Output
Output
For each query, output the answer to that query on its own line in the
order the queries were made.
Here is the solution:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct node {
int first;
int last;
};
int sum_array(int *array, int first, int last) {
int sum = 0;
for (int i = first; i <= last; i++) {
sum += array[i];
}
return sum;
}
int main() {
FILE* input = fopen("share.in","r");
int N = 0;
fscanf(input,"%d",&N);
int *array = (int*)malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {
fscanf(input,"%d",&array[i]);
}
int Q = 0;
fscanf(input,"%d",&Q);
struct node query[Q];
for (int i=0; i < Q; i++) {
fscanf(input,"%d",&query[i].first);
fscanf(input,"%d",&query[i].last);
}
fclose(input);
int sum = 0;
for ( int i = 0; i < Q ; i++) {
int first = query[i].first;
int last = query[i].last;
sum = sum_array(array,first,last);
printf("Number of queries : %d , sum is %d\n",i ,sum);
}
free(array);
return 0;
}
Update:
The answer given is good. But for some reason I couldn't make it work.
So here is the code rewritten and if someone can explain me what I do wrong I will be happy! Keep in mind we want the range to be [first,last]
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct node {
int first;
int last;
};
int sum_array(int *array, int first, int last) {
int sum = 0;
for (int i = first; i <= last; i++) {
sum += array[i];
}
return sum;
}
int main() {
FILE* input = fopen("share.in","r");
int N = 0;
fscanf(input,"%d",&N);
int *array = (int*)malloc(N * sizeof(int));
int *integralArray = (int*)malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {
fscanf(input,"%d",&array[i]);
integralArray[i] = array[i] + ((i > 0) ? array[i-1] : 0);
}
int Q = 0;
fscanf(input,"%d",&Q);
struct node query[Q];
for (int i=0; i < Q; i++) {
fscanf(input,"%d",&query[i].first);
fscanf(input,"%d",&query[i].last);
}
fclose(input);
int sum = 0;
for (int i = 0; i < Q ; i++) {
int first = query[i].first;
int last = query[i].last;
sum = integralArray[last] - integralArray[first - 1];
printf("Number of queries : %d , sum is %d\n",i ,sum);
}
free(array);
return 0;
}
You'd form the integral array. Modify to something like:
int *array = (int*)malloc(N * sizeof(int));
int *integralArray = (int*)malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {
fscanf(input,"%d",&array[i]);
integralArray[i] = array[i] + ((i > 0) ? integralArray[i-1] : 0);
}
So the element at integralArray[i] is the sum of all elements in array from 0 to i.
Then, to get the sum from a to b, where a > b, integralArray[b] is the sum from 0 to b and integralArray[a] is the sum from 0 to a so you can just compute integralArray[b] - integralArray[a] to get the total from a to b. Intuitively, integralArray[b] includes the numbers you want but it also includes the numbers up to and including a. You don't want those so you take them off again.
Vary appropriately for inclusion or exclusion of the number at a and the number at b. That as given will include the number at b but not that at a. You could adjust your integralArray to be one earlier (so integralArray[b] is the sum from 0 to b-1) or adjust your indices.
I want to create a table with keys from an array. Is there an easy way to do it.
int array1[] = {1,5,3,8,9,11};
// table[1]
// table[5]
// table[3]
int count(int a)
{
//a is one of the values in array. array1[] = {1,5,3,8,9,11};
// for ex 3.
// I have to figure out how many times this function was called with what values 1/5/3/8/9/11
table[3]++;
}
A simple code
#include<stdio.h>
int n = 6; //number of elements in array1
int array1[] = {1,3,5,8,9,11};
int *funCount;//Count of elements in array1
int count(int a)
{
int i;
for(i = 0; i < n; i++)
if(a == array1[i])
break;
funCount[i]++;
}
int main()
{
funCount = (int*)calloc(n, sizeof(int));
int i;
count(1);
count(3);
count(5);
count(8);
count(9);
count(11);
for(i = 0; i < n; i++)
printf("%d ",funCount[i]);
return 0;
}
This approach is okay if your array1 is going to be small!
Otherwise I would recommend you to use hashing
I have developed this knapsack algorithm based on pseudo-code found on wikipedia. It works fine for small number of items and capacity (n=6, v=2014), but it crashes for large numbers (n=5, v=123456789).
Additional problem is, that my program is tested by makefile with time limit set at 1 second.
What can i do to save time and memory?
v - Knapsack capacity
n - Number of items
weight[] - Weights
value[] - Values
int knapSack(int v, int weight[], int value[], int n){
int a, i, j;
int **ks;
ks = (int **)calloc(n+1, sizeof(int*));
for(a = 0; a < (n+1); a++) {
ks[a] = (int *)calloc(v+1, sizeof(int));
}
for (i = 1; i <= n; i++){
for (j = 0; j <= v; j++){
if (weight[i-1] <= j){
ks[i][j] = max(value[i-1] + ks[i-1][j-weight[i-1]], ks[i-1][j]);
} else {
ks[i][j] = ks[i-1][j];
}
}
}
int result = ks[n][v];
for(i = 0; i < (n+1); i++) {
free(ks[i]);
}
free(ks);
return result;
}
An array of 123456789 integer elements declared on the stack will crash many implementations of C. Sounds like this is your problem. Did you declare your arrays inside of a function (on the stack)?
// on heap
static int v[123456789]={0};
// on the stack (inside a function like main() )
int foo()
{
int v[123456789]={0};
}
I'm using a for loop to create an 100 element array of char. I on the first run, I want to change all of its values to 1, the second run, I want its every second values to 0
char array[ 100 ] = { 0 };
int toggle_swith(char a[]) {
for (i = 0; i < 100; i++) {
printf(array[i] + "1 ");
}
}
int main( void ) {
int i;
for (i = 0; i < 100; i++) {
printf(array[i] + "0 ");
toggle_switch();
}
}
You need a function which initializes the array:
void InitializeArray(char Array[], int Length) {
int i;
for (i = 0; i < Length; i++) {
Array[i] = '1';
}
}
You need a function which changes every 2nd element:
void ChangeEverySecondElement(char Array[], int Length) {
int i;
for (i = 1; i < Length; i += 2) {
Array[i] = '0';
}
}
You need a function to print the array :
void PrintArray(char Array[], int Length) {
int i;
for (i = 0; i < Length; i++) {
putchar(Array[i]);
putchar(' ');
}
putchar('\n');
}
Then you need to put them together
int main() {
char Array[100];
InitializeArray(Array, 100);
PrintArray(Array, 100);
ChangeEverySecondElement(Array, 100);
PrintArray(Array, 100);
return 0;
}
If you are trying to learn C, I recommend the book I learned it from, C by Example written by Greg Perry.
you can do it all at once
for (i=0; i<100; i++) array[i]=(i%2)+'0';
a typical attempt at optimization could look like:
#define BUFSZ 100
int main(){
char buf[BUFSZ];
int *bp=(int *)&buf, i=(BUFSZ/sizeof(int));
/* handle aligned words 4 bytes at a time */
while (i) bp[--i]='0101'; /* for 64 bit use '0101'|('0101' <<32) */
/* handle unaligned bytes */
for(i=(BUFSZ/sizeof(int))*sizeof(int);i<BUFSZ;i++)buf[i]=1-i%2+'0';
write(1,buf,BUFSZ);
}
Initially you want to make all your array elements as 1
You can use memset
memset(array,1,100)
This will clear all elements. But if you insist on using a loop then,
#define ARRAY_SIZE 100
char array[ARRAY_SIZE] = {0};
for(int count = 0; count < ARRAY_SIZE; count++)
{
array[count] = 1;
//If you want to print it, use:
printf("%d",array[count]; // You can also use %c
}
To make alternate element 0,
for(int count = 0; count < ARRAY_SIZE; (count = count + 2)) //Count + 2 will hop every alternate element
{
array[count] = 0;
}
Again, You can add printf() if you want.
Print statement should look something like this.
printf("%c0",array[i]);
I suggest you look up Beginner C tutorial for more info.