Find the longest arithmetic progression from an array - c

I have an array of numbers ex.[5,1,2,4,6,8,12], and I want to find the length of longest arithmetic progression within the sequence and to print it. Longest arithmetic progression means an increasing sequence with common difference, in this case [2,4,6,8].
#include <stdio.h>
void main()
{
int array[100], i, num,diff;
printf("Enter the size of an array \n");
scanf("%d", &num);
printf("Enter the elements of the array \n");
for (i = 0; i < num; i++) {
scanf("%d", &array[i]);
}
printf("\n Numbers in a.p: ");
for (i = 0; i < num; i++) {
diff = array[i+1]-array[i];
if (array[i]-diff == array[i+1]-diff);
{
printf("%d, ", array[i]);
}
}
printf("\n Common difference:%d", diff);
}

like this
#include <stdio.h>
int main(void){
#if DEBUG
int array[] = {5,1,2,4,6,8,12};
int num = sizeof(array)/sizeof(*array);
int i, diff;
#else
int array[100], i, num,diff;
printf("Enter the size of an array \n");
scanf("%d", &num);
printf("Enter the elements of the array \n");
for (i = 0; i < num; i++) {
scanf("%d", &array[i]);
}
#endif
int j, len, longest_len = 2, longest_i = 0;
for (i = 0; i < num - longest_len; i += len-1) {
diff = array[i+1]-array[i];
for(j = i+2; j < num && array[j-1]+diff == array[j]; ++j);
len = j - i;
if(longest_len < len){
longest_len = len;
longest_i = i;
}
}
printf("\n Numbers in a.p: ");
diff = array[longest_i+1] - array[longest_i];
printf("[ ");
for(i = 0; i < longest_len; ++i){
printf("%d", array[longest_i + i]);
if(i == longest_len-1)
printf(" ]\n");
else
printf(", ");
}
printf("\n Common difference:%d", diff);
}

Since this seems to be a homework or challenge I will only help by solving your immediate problems, caused by very strange code.
Here is code which at leat detects the progressions correctly.
You can yourself count the length, store the longest length and its index, then print that sequence after parsing all the array.
There are two assumptions here, which you might want to avoid for challenge/homework:
no identical numbers entered
no overlapping progressions,
i.e. no number is the last of one and the first of next progression
The representation of more than one sequence in the output is a little jittery (missing ")"), but that is not relevant for finding and exclusively printing the longest one.
I did not bother about your ratio output, no idea what that is supposed to be.
Code:
#include <stdio.h>
// avoid a warning
int main() {
int array[100], i, num, diff=0, lastdiff=0, first=1;
printf("Enter the size of an array \n");
// for good code, this should check the result
scanf("%d", &num);
// in case of scaf-failure, cleanup here for good code
// asking for the number of elements
// and then relying on that number to be entered
// is less elegant than checking for and end condition
// like EOF or negative input
printf("Enter the elements of the array \n");
for (i = 0; i < num; i++) {
// for good code, this should check the result
scanf("%d", &array[i]);
// in case of scaf-failure, cleanup here for good code
}
printf("\n Numbers in a.p: ");
for (i = 1; i < num; i++) {
lastdiff=diff;
diff = array[i]-array[i-1];
if (diff==lastdiff)
{ if(first==1)
{ first=0;
printf("(%d, %d",array[i-2], array[i-1]);
}
printf(", %d", array[i]);
} else
{ first=1;
}
}
printf(")\n Ratio:%d", diff);
// avoid a warning
return 0;
}

There are a number of ways to approach this challenge. You can either check each diff against each value in the array or work the other way around. Given you are not sorting the values, you may benefit by nesting the check of values within your loop over all possible diffs. Something similar to the following works:
#include <stdio.h>
int main (void) {
int a[] = {5, 1, 2, 4, 6, 8, 12},
n = sizeof a / sizeof *a,
startidx = 0,
maxlen = 0;
for (int d = 1; d < n; d++) { /* loop over diffs */
int idx = -1,
len = 1;
for (int i = 1; i < n; i++) /* loop over values */
if (a[i - 1] + d == a[i]) {
if (idx < 0) /* if index not set */
idx = i - 1; /* set to 1st index */
len++; /* increment length */
}
if (idx >= 0 && len > maxlen) { /* if progression found */
maxlen = len; /* save length */
startidx = idx; /* save start index */
}
}
printf ("longest progression: '%d' elements.\n", maxlen);
for (int i = 0; i < maxlen; i++)
printf (i ? ", %d" : "%d", a[startidx + i]);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/maxprogression
longest progression: '4' elements.
2, 4, 6, 8
Investigate several ways to approach it, and finally settle on the one that makes the most sense to you. You can work on optimizing later.
As far as the code you posted goes, always validate all user input by, at minimum, checking that the number of expected conversions to type took place, e.g.
if (scanf("%d", &num) != 1) {
fprintf (stderr, "error: input conversion failed for 'num'.\n");
return 1;
}
You would do the same in your values loop. Let me know if you have any questions. Good luck with your coding.

Following is the complete working code. You can see it working here:
#include <stdio.h>
int main()
{
int array[100], i, num,diff, resDiff, startIndx, resStartIndx, countCur, countPre;
printf("Enter the size of an array \n");
scanf("%d", &num);
printf("Enter the elements of the array \n");
for (i = 0; i < num; i++) {
scanf("%d", &array[i]);
}
//Now code changes
startIndx =0, resStartIndx=0, countPre=0, resDiff=0;
for (i = 0; i < num; /*No increment required here*/) {
countCur =0;
startIndx=i;
countCur++;
if(++i < num)
{
diff = array[i] - array[startIndx];
countCur++;
i++;
while((i < num) && (diff == (array[i] - array[i-1])))
{
countCur++;
i++;
}
if(countCur > countPre)
{
resStartIndx = startIndx;
countPre = countCur;
resDiff = diff;
}
}
}
countPre += resStartIndx;
printf("\n Numbers in a.p: ");
for (i = resStartIndx; i < countPre; i++) {
printf("%d, ", array[i]);
}
printf("\n Common difference:%d", resDiff);
return 0;
}

Related

How to write a program to delete an element in an array using C language? [duplicate]

I wrote the following program to delete an array element entered by the user.
#include <stdio.h>
#include <conio.h>
void main() {
int j, i, a[100], n, key, l;
clrscr();
printf("Enter the number of elements:");
scanf("%d", &n);
printf("\nEnter the elements:\n");
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
printf("\nEnter the element to delete:");
scanf("%d", &key);
l = n; //Length of the array
for (i = 0; i < l; i++) {
if (a[i] == key) {
for (j = i; j < l; j++)
a[j] = a[j + 1];
l--; //Decreasing the length of the array
}
}
printf("\nThe new array is \n");
for (i = 0; i < l; i++)
printf("%d ", a[i]);
getch();
}
It works fine for most inputs but when the input is something like: 1 2 2 3 5 (here 2 repeats consecutively) and the element to be deleted is 2, the output is 1 2 3 5.
How can I modify the program such that all instances of the entered element is removed?
After l-- put i-- too as shown below
if(a[i]==key)
{
for(j=i;j<l;j++)
a[j]=a[j+1];
l--; //Decreasing the length of the array
i--; //check again from same index i
}
Other posters have given you 2 solutions ... I think understanding why it happens is good too :)
Let's take your example 1, 2, 2, 3, 5 and follow the code line by line
i = 0; /* first time through the loop; i "points" to 1 */
if (a[i] == 2) ... /* nope; next loop */
i = 1;
if (a[1] == 2) ... /* yes! let's go inside the if */
/* move all elements back
** and "decrease" array length */
/* array is now 1, 2, 3, 5 */
/* next loop */
i = 2;
if (a[i] == 2) ... /* nope; OH! Wait ...
** a[1] is the new 2 and it wasn't checked */
If you don't care about the order of the elements in the array, you can move the last element of the array into the newly formed gap (cunningly reducing the length of the array by one). This can be vastly more efficient than shunting the elements down: in computer science term this makes deleting an element O(1) rather than O(N).
a[i] = a[--l];
If your i index is looping over the array, you'll want to loop over this element again:
a[i--] = a[--l];
For example, to remove all elements '3' from an array of length 'l':
for (i = 0; i < l; ++i) {
if (a[i] == 3) {
a[i--] = a[--l];
}
}
If you do care about the order of the elements in the array, it's most efficient to use memmove rather than move elements by hand. It's designed to be used where the source and destination memory overlap.
memmove(a + i, a + i + 1, sizeof(a[0]) * (l - i - 1));
Change "if" to "while":
for(i=0;i<l;i++)
{
while (i<l && a[i]==key)
{
for(j=i;j<l;j++)
a[j]=a[j+1];
l--; //Decreasing the length of the array
}
}
use a new array.
int array[l];
int k=0;
for(i=0;i<l;i++)
{
if(a[i]!=key)
{
array[k]=a[i];
k++;
}
}
#include<stdio.h>
int main(){
int size;
int array[20];
int delete_pos;
int i;
printf("Enter the Size of the Array :");
scanf("%d",&size);
for(i=0;i<=size-1;i++){ //no of elements taken are 1 less than size of the array asked.
printf("\nEnter the element[%d] :",i+1);
scanf("%d",&array[i]);
}
printf("\nEnter the Position of the array to be deleted :");
scanf("%d",&delete_pos);
for(i=delete_pos-1;i<=size;i++){ //every element of the array is replaced by array on next position.
array[i]=array[i+1];}
size=size-1; // Reducing the size of the array as one element is deleted.
printf("Your new array is \n");
for(i=0;i<=size-1;i++){ //printing the entire new array.
printf("%d ",array[i]);
}
printf("\n\n");
return 0;
}
Your method with 2 nested for loops is too complicated. You can simple scan the array with an index i and copy all elements different from key with a different index len. The resulting array length is the final value of len.
Here is a modified version:
#include <stdio.h>
#include <conio.h>
int main(void) {
int a[100];
int i, n, key, len;
clrscr();
printf("Enter the number of elements: ");
if (scanf("%d", &n) != 1) {
printf("invalid input\n");
return 1;
}
if (n < 0 || n > 100) {
printf("invalid number of elements\n");
return 1;
}
printf("\nEnter the elements:\n");
for (i = 0; i < n; i++) {
if (scanf("%d", &a[i]) != 1) {
printf("invalid input\n");
return 1;
}
}
printf("\nEnter the element to delete: ");
if (scanf("%d", &key) != 1) {
printf("invalid input\n");
return 1;
}
for (i = len = 0; i < n; i++) {
if (a[i] != key)
a[len++] = a[i];
}
printf("\nThe new array is:\n");
for (i = 0; i < len; i++)
printf("%d ", a[i]);
printf("\n");
getch();
return 0;
}
Notes:
The prototype for main without arguments is int main(void) and it is considered good style to return 0 for success.
always test the return value of scanf(). This prevents many bugs and undefined behavior for invalid input. It also saves a lot of time looking in the wrong places when input was just invalid.
avoid naming a variable l as it looks too close to 1 in many fixed pitch fonts.
always terminate the program output with a newline.

C Programming array with repetition

I wrote a program that examines whether a number in a sequence is repeated 2 times (so many times it should be repeated) if it is repeated 2 times "YES", if not "NO". I think this can be written in a simpler and better way, so I'm interested in the suggestions and corrections of someone more experienced than me.
The program should print YES if each member of array is repeated exactly once, and otherwise it should print NO:
Enter the number of array: 8
Enter the sequence: 1 2 2 1 3 3 4 4
YES
Enter the number of string members: 7
Enter the string: 1 2 1 2 1 3 4
NO
Here is my code:
#include <stdio.h>
#define arr 100
int main() {
int n, i, p = 1, j, a;
double array[arr];
int num[100];
do {
printf("Enter the number of array: ");
scanf("%d", &n);
} while (n < 1 || n > 100);
printf("Enter array: ");
for (i = 0; i < n; i++) {
scanf("%lf", &array[i]);
num[i] = -1;
}
for (i = 0; i < n; i++) {
a = 1;
for (j = i + 1; j < n; j++) {
if (array[i] == array[j]) {
a++;
num[j] = 0;
}
}
if (num[i] != 0)
num[i] = a;
}
for (i = 0; i < n; i++) {
if (num[i] == 0)
continue;
if (num[i] != 2) {
p = 0;
break;
}
}
if (p == 1)
printf("YES");
else
printf("NO");
return 0;
}
I am going to provide a code review here because the code doesn't work and that makes it off-topic on Code Review.
Good things about the code:
There are no global variables.
There is an attempt to define a symbolic constant for the array size.
Things that can be improved:
Declare the variables are you need them. In the original version of C back in the 1970s and 1980s variables had to be declared at the top of the function. That is no longer the case, and a recommended programming practice to declare the variable as needed. In C the language doesn't provide a default initialization of the variable so variables should be initialized as part of the declaration. For readability and maintainability each variable should be declared and initialized on its own line.
Capitalize the constants, arr should be ARR.
ARR should be used in the declaration of num as well as the declaration of array.
ARR should be used instead of 100 in this statement while (n < 1 || n > 100).
Since the program only allows a single digit to be read at a time, array should be an array of integers rather than array of doubles.
There is only one error check on user input.
A simplified version of the program that does work:
One of the first things you need to learn in programming is how to write functions and subroutines. This is important because it allows you to break problems into smaller and smaller pieces until it is very easy to solve the problem. There are a number of programming principles that this relates to, 2 of them are the Single Responsibility Principle states:
that every module, class, or function should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by that module, class or function.
and the KISS Principle (Keep It Simple).
#include <stdio.h>
#include <stdbool.h>
#define ARR 100
static int get_user_input(int array[ARR])
{
int count = 0;
do {
printf("Enter the number of array: ");
scanf("%d", &count);
} while (count < 1 || count > ARR);
printf("Enter array: ");
for (int i = 0; i < count; i++) {
scanf("%1d", &array[i]);
}
return count;
}
static bool find_first_repetition(int count, int array[ARR])
{
bool repetition = false;
for (int i = 1; i < count; i++)
{
if (array[i - 1] == array[i])
{
return true;
}
}
return repetition;
}
int main() {
int n;
int num[ARR];
n = get_user_input(num);
if (find_first_repetition(n, num))
{
printf("YES");
}
else
{
printf("NO");
}
return 0;
}
Your code works, but there are some issues:
you should test for conversion failures in scanf(): the return value must be 1 as there is a single conversion for each scanf() call.
the counting loops are too complicated: just counting the number of occurrences with 2 nested loops is much simpler and has comparable time complexity, and using a += (array[i] == array[j]); may produce fast branchless code on most architectures.
it is good style to finish the program output with a newline.
Here is a modified version:
#include <stdio.h>
int main() {
int n;
do {
printf("Enter the length of the array: ");
if (scanf("%d", &n) != 1)
return 1;
} while (n < 1 || n > 100);
double array[n];
printf("Enter array: ");
for (int i = 0; i < n; i++) {
if (scanf("%lf", &array[i]) != 1)
return 1;
}
int p = 1;
for (int i = 0; i < n; i++) {
int a = 0;
for (int j = 0; j < n; j++) {
a += (array[i] == array[j]);
}
if (a != 2) {
p = 0;
break;
}
}
if (p == 1)
printf("YES\n");
else
printf("NO\n");
return 0;
}

Program for binary to decimal conversion in C isn't working like it's supposed to and instead gives some random outputs

The program is supposed to ask for length and number of binary arrays and then stores them and converts them all into decimal and prints the decimal part. The logic seems fine to me but it isn't working for some reason and gives weird outputs. Here's the code:
#include <stdio.h>
int main() {
int n, decimal_num = 0, base = 1, rem;
printf ("Enter the length and number of binary strings: ");
scanf(" %i", &n);
int str[n], deci[n];
for (int i = 0; i<n; i++) {
printf("Enter string %i: ", i + 1);
scanf(" %i", &str[i]);
}
for (int i = 0; i < n; i++) {
while (str[i] > 0) {
rem = str[i] % 10;
decimal_num = decimal_num + rem * base;
str[i] = str[i] / 10;
base = base * 2;
}
deci[i]= decimal_num;
decimal_num= 0;
}
for (int i = 0; i < n; i++) {
printf("%i\n", deci[i]);
}
}
There are a few issues I see with this program. First off creating arrays the way you did will give errors with most compilers. This is fixed by dynamically allocating the arrays by including stdlib.h and using malloc
int *str, *deci;
str = malloc(n * sizeof(int));
deci = malloc(n * sizeof(int));
This also means you would need to free this memory at the end at the end of your program.
free(str);
free(deci);
The second issue is in the second loop calculating the base 10 values. This is most likely what is causing the incorrect output. The issue is caused by not resetting the base variable after each iteration of the loop. This is causing the program to interpret the binary numbers at much larger than they actually are. This can be fixed by setting the base variable back to one in the same place you are setting decimal_num to zero
Another issue which doesn't affect functionality is the naming of your variables. More specifically the variable str which doesn't store a string. You should rename this to something more descriptive e.g. binary_nums. I would also recommend renaming deci for the same reason.
Additionally I was also getting issues with the scanf call using %i in the first loop so I changed it to %d which fixed the issue for me.
The fixed program looks like this
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, decimal_num = 0, base = 1, rem;
int *binary_nums, *base10_nums;
printf("Enter the length and number of binary strings: ");
scanf(" %d", &n);
binary_nums = malloc(n * sizeof(int));
base10_nums = malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
printf("Enter string %i: ", i + 1);
scanf(" %d", &binary_nums[i]);
}
for (int i = 0; i < n; i++) {
while (binary_nums[i] > 0) {
rem = binary_nums[i] % 10;
decimal_num = decimal_num + rem * base;
binary_nums[i] = binary_nums[i] / 10;
base = base * 2;
}
base10_nums[i] = decimal_num;
decimal_num = 0;
base = 1;
}
for (int i = 0; i < n; i++) {
printf("%i\n", base10_nums[i]);
}
free(binary_nums);
free(base10_nums);
}
unsigned conv(const char *binaryString)
{
unsigned result = 0;
while(binaryString && *binaryString)
{
if(*binaryString == '\n') break;
result *= 2;
result += *binaryString++ == '1';
}
return result;
}
int main(void)
{
int size, number;
scanf("%u", &size);
scanf("%u", &number);
/* check return value of scanf */
char strings[number][size+1];
for(int n = 0; n < number; )
{
fgets(strings[n], size, stdin);
/* add error checks */
if(strings[n++][0] == '\n') n--;
}
for(int n = 0; n < number; n++)
{
printf("%u (0x%x) == %s", conv(strings[n]), conv(strings[n]), strings[n]);
}
}

Problem with frequency analysis of user input array in C

I'm supposed to do a freqency analysis of a user input array. User may enter as many numbers between 0-1000 as s/he wants and a maximum of 100 numbers can be entered, user ends input by entering a negative number. A void function will calculate which number appears the most times and those 2 variables should be sent to the function as pointers.
My problem is that no matter what I do the analysis seems to calculate all the "empty" elements of the array and I can't figure out what I'm doing wrong. If i make the array smaller to lets say 10 elements it works fine. As I'm a complete novice when it comes to programming and I've changed the code about a million times so at this point I can't remeber what I've changed from my original code. When debugging I get stuck in the second for loop in the function..
#include <stdio.h>
#define MAX 100
#define INTERVAL 1000
void frequencyAnalysis(int array[],int *number, int *freq)
{
int element = 0, count = 0;
for (int i = 0; i < MAX; i++) {
int tempElement = array[i];
int tempCount = 0;
for (int j = 0; j < MAX; j++)
if (array[j] == tempElement)
tempCount++;
if (tempCount > count) {
element = tempElement;
count = tempCount;
}
}
*number = element;
*freq = count;
}
int main(void)
{
int array[MAX], i, j, number = 0, freq = 0;
printf("Hello.\n"
"Please enter a number between 0-1000. "
"Enter as many number as you want (maximum 100).\n"
"Exit by entering a negative number.\n\n");
printf("Enter a number:\n");
for (i = 0; i < MAX; i++) {
scanf("%d", &array[i]);
if (array[i] < 0)
break;
}
frequencyAnalysis(array, &number, &freq);
printf("The number:%d is the most frequent number and appears %d times.\n", number, freq);
return 0;
}
Addressing the first issue, pass in how many items the user actually entered so you're not running up to MAX (which would include all the unused cells). The key is nitems.
void frequencyAnalysis(int array[], int nitems, int *number, int *freq)
{
for (int i = 0; i < nitems; i++) {
...
for (int j = 0; j < nitems; j++)
{
// do stuff
}
}
}
int main(void)
{
int array[MAX],i, j, number = 0, freq = 0;
...
frequencyAnalysis(array, i, &number,&freq);
///
}

Why does this ISBN checking code turn '0' into 45?

Can you help me find out why the second 0 in the array turns into 45 please.
Everything is okay but except this number makes the result goes wrong. I cannot find out what's the matter with this.
Here is my code:
#include <stdio.h>
int getuserchoice() {
int n;
printf("---ISBN Validate---");
printf("\n1-ISBN Checking");
printf("\n2-Quit");
printf("\nSelect: ");
scanf("%d", &n);
return n;
}
int main() {
long a[10];
long sum = 0;
int i = 0, n = 1;
long x;
if (getuserchoice() == 1) {
printf("\nEnter the values for ISBN number : ");
scanf("%ld", &x);
if (x > 0) {
while (x > 0) {
a[i] = x % 10;
x = x / 10;
i++;
}
}
for (i = 0; i < 10; i++)
printf("%ld\t", a[i]);
for (i = 0; i < 10; i++) {
sum += a[i] * n;
n++;
}
if (sum % 11 == 0)
printf("\nISBN Status: Valid!");
else
printf("\nISBN Status: Invalid!");
} else
printf("\nSee you later!");
getchar();
return 0;
}
By default uninitialized arrays contain garbage (literally anything). It so happens that that particular element contains 45 (amazing, isn't it?).
It stays 45 because leading 0s are discarded when reading a number (you should read it as a string (C++) or char[]), so you are never accessing that particular array element to give it a meaningful value.
Here's SO post on how to initialize an array with 0s in C.

Resources