C. recursion initializing a variable - c

my work:
#define SIZE 9
#include <stdbool.h>
bool arrayCheck(int arr[], int counter, int array_size);
void main() {
int arr[SIZE] = { 1,2,5,1,5,1,2,3,4},num1=5;
bool check= arrayCheck(arr, num1, SIZE - 1);
}
bool arrayCheck(int const arr[], int counter, int array_size) {
if (counter == 0) {
return true;
}
if (array_size < 0) {
return false;
}
if (arr[array_size] - arr[array_size - 1] == 1) {
counter -= 1;
array_size -= 1;
}
else {
counter = 5;
array_size -= 1;
}
arrayCheck(arr, counter, array_size);
}
im writing a recursion function that should read an array and if there is a requested number of follow up numbers (defined by counter) the function will return "true" other wise the function will return "falls"
in my code the function works only if the the request amount of follow up numbers is 5 (cuz that was the number i was testing the function with) now im thinking if i can create and initiate a variable that wont re-initiate itself each time that would be the way. is it possible?

To initialize a variable once and only once within the scope of a function, use the static keyword when declaring the variable.
For example, the counter variable below will only set to its initial value (0) once if defined within a function. Each subsequent call to foo will result in counter incrementing by 1. The first call will make counter = 1, 2nd call will make counter = 2, etc.
void foo( void )
{
static int counter = 0;
counter++;
}

Related

C - Passing a local variable in a function without initializing

so I'm really new at this, and I was wondering how I would go about passing a local variable in a function (in terms of the initialization). For example, I have one function (move) that declares and initializes two variables (t_row and t_column) to be used in a for loop, and within that loop, I have another functions (swap), that is called if certain conditions are met. How do I go about using those variables in the swap function. I know I need to declare them, but their initialization in the swap function depends on what iteration of the for loop swap was called. Thanks in advance for any help!
bool move(int tile)
{
for (int t_row = 0; t_row < d; t_row++)
{
for (int t_column = 0; t_column < d; t_column++)
{
if (tile == board[t_row][t_column])
{
if (0 < t_row && board[t_row - 1][t_column] == 0)
{
swap(t_row - 1, t_column);
return true;
}
}
}
}
return false;
}
void swap(int row_new, int column_new)
{
int t_row;
int t_column;
int hold = board[t_row][t_column];
board[t_row][t_column] = 0;
board[row_new][column_new] = hold;
}
The easiest way I can see to do this would be to pass in the values of the old row and column.
void swap(int row_new, int col_new, int row_old, int col_old) {
int hold = board[row_old][col_old];
board[row_old][column_old] = 0;
board[row_new][column_new] = hold;
}

Checking array for identical numbers and their value

As part of a program that I have to make, one of the function that I need to program should check if the array has any identical numbers that are the same, and if one of them is bigger/equals to a given number.
The given number is also the amount of numbers in the array
This is what I have so far:
int checkarray(int *arr, int num)
{
int check = num;
int check2 = num;
int *lor;
int *poi;
int *another;
another = arr;
lor = arr;
poi = arr;
int check3 = num;
for ( ; num > 1; num--) {
for ( ; check3 >= 0; check3--) {
if (*arr == *poi)
return 0;
poi++;
}
arr++;
poi = another;
}
for ( ; check2 > 0; check2--) {
if (*lor >= check)
return 0;
lor++;
}
return 1;
}
I know that I made too many pointers/int for the function, but that's not the problem..
The part of checking for a given value works fine if I'm not mistaken so I think you can ignore that part (that's the last 'for' loop)
I know it should be easy but for some reason I just can't get it to work...
Edit:
I'll give an example: If the array is 0 1 2 3 1 the function will return 0, cause the second and the last number are identical. The function will also return 0 if the given number is 5, and one of the numbers is bigger or equals to 5, for example 0 1 2 5 4.
Otherwise, the function returns 1.
I create a new array where I'm going to save the numbers so I can check if you have a repeat number in the array. I also have one more argument in the function to know the size of the array.
#include <stdio.h>
#include <stdlib.h>
int checkArray(int *arr, int size, int number){
int i,j;
int *countArray = calloc(size,sizeof(int));
for(i=0;i<size;i++){
if(arr[i]>=number){ //Check >= number
free(countArray);
return 0;
}
for(j=0;j<i;j++){ //Check repeat number
if(countArray[j]==arr[i]){
free(countArray);
return 0;
}
}
countArray[j]=arr[i]; //no repeat number so we save it.
}
free(countArray);
return -1; //Error
}
int main(){
int arr[6] = {0,8,2,3,4,1};
printf("Result %d",checkArray(arr,6,5));
}
I hope this can help you.
Update without new array
int checkArray(int *arr, int size, int number){
int i,j;
for(i=0;i<size;i++){
if(arr[i]>=number){
return 0;
}
for(j=0;j<i;j++){
if(arr[i]==arr[j]){
return 0;
}
}
}
return -1; //Error
}
Change your upper for loop to:
for ( ; num > 0; num--) {
if(arr[i]>=number){
return 0;
}
int check3 = num;
poi=arr+1;
for ( ; check3 > 0; check3--) {
if (*arr == *poi)
return 0;
poi++;
}
arr++;
}
and remove the bottom one.
The mistakes here are as following:
1- You need to change the lines:
int check3 = num;
for ( ; num > 1; num--) {
to be:
for ( ; num > 1; num --) {
int check3 = check; // Move to inside loop to reset each time for a fresh inner loop and use check instead of num to reset the value
2- You need to change the line:
for ( ; check3 >= 0; check3--) {
To be
for ( ; check3 > 0; check3--) { // Because `>=0` means attempting to read past the array
3- poi should be initialised every time in the loop as arr+1 to skip comparing the same member of the array to itself, and to skip re-comparing members more than one time.
I suggest re-writing the method with better code style to enable easier detection of such errors and typos

Variable returned by Reference from a function gives weird values

I've been working on a hangman game lately, and this function supposedly checks for a letter that the user inputs in an array (Containing a pre-defined word such as "BUILDING") and adds on a Counter (Count) if the letter exists or decreases the lives (Which start at 5 -defined in the main function-) if it doesn't exist.
Now the Count variable works fine but the Lives variable keeps decreasing anyways, even if the letter exists and it doesn't just decrease by 1 but by bigger amounts resulting in rather big negative numbers.
Here's the code, thanks in advance:
void Checkf(char X,int r,int Length,char *Hidden, int *Lives,int *Count)
{
int i;
for (i=0;i<Length;i++)
{
if (X==Words[r][i] && Hidden[i]=='*')
{
Hidden[i] = X;
*Count = *Count + 1;
}
else if (X!=Words[r][i] && Hidden[i]=='*')
*Lives = *Lives - 1;
}
}
That behavior occurs because you (optionally) decrease the value of Lives on each iteration of the loop.
You can add a variable that indicates whether the letter was found or not, and then decrease the value of Lives after the loop ends, like this:
void Checkf(char X,int r,int Length,char *Hidden, int *Lives,int *Count)
{
int i;
unsigned char found = 0;
for (i=0;i<Length;i++)
{
if (X==Words[r][i] && Hidden[i]=='*')
{
Hidden[i] = X;
*Count = *Count + 1;
found = 1;
}
}
if (!found)
{
*Lives -= 1;
}
}

Max in array and its frequency

How do you write a function that finds max value in an array as well as the number of times the value appears in the array?
We have to use recursion to solve this problem.
So far i am thinking it should be something like this:
int findMax(int[] a, int head, int last)
{
int max = 0;
if (head == last) {
return a[head];
}
else if (a[head] < a[last]) {
count ++;
return findMax(a, head + 1, last);
}
}
i am not sure if this will return the absolute highest value though, and im not exactly sure how to change what i have
Setting the initial value of max to INT_MIN solves a number of issues. #Rerito
But the approach OP uses iterates through each member of the array and incurs a recursive call for each element. So if the array had 1000 int there would be about 1000 nested calls.
A divide and conquer approach:
If the array length is 0 or 1, handle it. Else find the max answer from the 1st and second halves. Combine the results as appropriate. By dividing by 2, the stack depth usage for a 1000 element array will not exceed 10 nested calls.
Note: In either approach, the number of calls is the same. The difference lies in the maximum degree of nesting. Using recursion where a simple for() loop would suffice is questionable. To conquer a more complex assessment is recursion's strength, hence this approach.
To find the max and its frequency using O(log2(length)) stack depth usage:
#include <stddef.h>
typedef struct {
int value;
size_t frequency; // `size_t` better to use that `int` for large arrays.
} value_freq;
value_freq findMax(const int *a, size_t length) {
value_freq vf;
if (length <= 1) {
if (length == 0) {
vf.value = INT_MIN; // Degenerate value if the array was size 0.
vf.frequency = 0;
} else {
vf.value = *a;
vf.frequency = 1;
}
} else {
size_t length1sthalf = length / 2;
vf = findMax(a, length1sthalf);
value_freq vf1 = findMax(&a[length1sthalf], length - length1sthalf);
if (vf1.value > vf.value)
return vf1;
if (vf.value == vf1.value)
vf.frequency += vf1.frequency;
}
return vf;
}
Your are not thaaaat far.
In order to save the frequency and the max you can keep a pointer to a structure, then just pass the pointer to the start of your array, the length you want to go through, and a pointer to this struct.
Keep in mind that you should use INT_MIN in limits.h as your initial max (see reset(maxfreq *) in the code below), as int can carry negative values.
The following code does the job recursively:
#include <limits.h>
typedef struct {
int max;
int freq;
} maxfreq;
void reset(maxfreq *mfreq){
mfreq->max = INT_MIN;
mfreq->freq = 0;
}
void findMax(int* a, int length, maxfreq *mfreq){
if(length>0){
if(*a == mfreq->max)
mfreq->freq++;
else if(*a > mfreq->max){
mfreq->freq = 1;
mfreq->max = *a;
}
findMax(a+1, length - 1, mfreq);
}
}
A call to findMax will recall itself as many times as the initial length plus one, each time incrementing the provided pointer and processing the corresponding element, so this is basically just going through all of the elements in a once, and no weird splitting.
this works fine with me :
#include <stdio.h>
#include <string.h>
// define a struct that contains the (max, freq) information
struct arrInfo
{
int max;
int count;
};
struct arrInfo maxArr(int * arr, int max, int size, int count)
{
int maxF;
struct arrInfo myArr;
if(size == 0) // to return from recursion we check the size left
{
myArr.max = max; // prepare the struct to output
myArr.count = count;
return(myArr);
}
if(*arr > max) // new maximum found
{
maxF = *arr; // update the max
count = 1; // initialize the frequency
}
else if (*arr == max) // same max encountered another time
{
maxF = max; // keep track of same max
count ++; // increase frequency
}
else // nothing changes
maxF = max; // keep track of max
arr++; // move the pointer to next element
size --; // decrease size by 1
return(maxArr(arr, maxF, size, count)); // recursion
}
int main()
{
struct arrInfo info; // return of the recursive function
// define an array
int arr[] = {8, 4, 8, 3, 7};
info = maxArr(arr, 0, 5, 1); // call with max=0 size=5 freq=1
printf("max = %d count = %d\n", info.max, info.count);
return 0;
}
when ran, it outputs :
max = 8 count = 3
Notice
In my code example I assumed the numbers to be positive (initializing max to 0), I don't know your requirements but you can elaborate.
The reqirements in your assignment are at least questionable. Just for reference, here is how this should be done in real code (to solve your assignment, refer to the other answers):
int findMax(int length, int* array, int* maxCount) {
int trash;
if(!maxCount) maxCount = &trash; //make sure we ignore it when a NULL pointer is passed in
*maxCount = 0;
int result = INT_MIN;
for(int i = 0; i < length; i++) {
if(array[i] > result) {
*maxCount = 1;
result = array[i];
} else if(array[i] == result) {
(*maxCount)++;
}
}
return result;
}
Always do things as straight forward as you can.

Write the definition of a function, isReverse

Write the definition of a function, isReverse , whose first two parameters are arrays of integers of equal size, and whose third parameter is an integer indicating the size of each array. The function returns true if and only if one array is the reverse of the other. ("Reverse" here means same elements but in reverse order.)
int isReverse(int array1[], int array2[], int size)
{
int i;
for (i=0;i<size;i++)
{
if(array1[i] == array2[size-1])
return 0;
else
return 1;
}
}
i keep getting an error. whats wrong with it.
When you return from within any block in the function the function execution ends there, so in your case you are returning from function even when the first elements of the arrays are matching which is not correct, you should check whole array and then return from the function in the end, check the code below:
int isReverse(int array1[], int array2[], int size)
{
int i,status=1;
for (i=0;i<size;i++) //Size is the length of the array? if yes than you need -1 from it.
{
if(array1[i] == array2[size])
{
status=0;
--size;
}
else
return 1;
}
return status;
}
Moreover, size-1 does not change the value of the variable size itself hence size will remain same throughout the loop, use --size this will decrement the value of actual variable hence decrementing it by one every time.
The variable "size" never changes, so you're always checking elements of array1 against the last element of array2.
Since this sounds like a homework problem, I'll let you see if you can go from there.
This is how I did it.
int isReverse(int array1[], int array2[], int SIZE)
{
for( int counter = 0; counter <= SIZE/2; counter++ )
if(array1[counter] != array2[SIZE-counter] || array2[counter] != array1[SIZE-counter])
return 1;
return 0;
}
You are just comparing the value at index i with a constant SIZE-1. Instead you want to compare the value at i with the comparison array's size-i. So each time the counter increments it compares with the opposite array's size-i. And you only have to do this for half of the array.
The return value is wrong because you are checking only 1 value from each array, not all of them. What you want to do is something like this.
for (i=0;i<size;i++)
{
if(!(array1[i] == array2[size-i-1]))
return 0;
}
return 1;
Basically you go through the array one by one, if any of the values are not the same as the appropriate value on the other array, it is not a reverse, so we return 0. If we get out of the for loop without going through the if, it means they are reverses so we return 1.
int isReverse(int array1[], int array2[], int size)
{
int flag = 0;
for (int i=0;i<size;i++)
{
if(array1[i] != array2[size-1]){
flag = 1;
break;
}
return flag;
}
}
In the code you have kept the return statement inside the loop... keep the return statement outside the loop and try
int isReverse(int a[], int b[], int n)
{
int i = 0;
while (i<n)
{
if (a[i] != b[n-i-1]) {return 0; break;}
else i++;
}
return 1;
}
anw this was the correct answer.
bool isReverse(int array1[], int array2[],int size)
{
int i=0;
for (int k=0;k<size;k++){
if (array1[k]==array2[size-k-1]){
i++;
}
}
if (i==size){
return true;
}else{
return false;
}
}

Resources