It might seem like long but I over explained it.
So I have my problem is not necessarily finding the palindromes it is just the finding the length of the palindrome I can't figure out and my code doesn't work for single digit palindromes (yes we count them too) so here is the code and the explanation:
#include <stdio.h>
#define LEN 9
int *lastEqual(int *p, int *q) {
int *rightmost;
int *temp;
int *zero = p;
while (p <= q) {
if (*zero == *(p + 1)) {
temp = p + 1;
if (temp < q) {
rightmost = temp;
}
}
p++;
}
return rightmost;
}
What this funtion does or suppose to do:
*For the given array: {3,6,7,8,7,6,5,3,5} If lastEqual is called by the references of the
bold numbers, it returns a pointer to 3.(The one closest to the end of array)*
*For the given array: {3,6,7,8,7,6,5,3,5} If lastEqual is called by the references of the
bold numbers it returns a pointer to 6.*
Here is the second function:
int isPalindromic(int *p, int *q) {
int *left = p;
int *right = q;
int pali;
while (left < right) {
if (*left == *right) {
pali = 1;
} else {
pali = 0;
}
left++;
right--;
}
return pali;
}
Here is what it does or is supposed to do:
For the given array: {3,6,7,8,7,6,5,3,5} If isPalindromic is called by the references of
the bold numbers it returns 0, since the numbers between those addresses do not
represent a palindrome.
For the given array: {3,6,7,8,7,6,5,3,5} If isPalindromic is called by the references of
the bold numbers it returns 1, since the numbers between those addresses represent
a palindrome.
And here is the main function:
int main() {
int *p, *q, *rightmost;
int arr[LEN] = { 3, 6, 7, 8, 7, 6, 5, 3, 5 };
p = arr;
q = p + (LEN - 1);
for (int i = 0; i < LEN; i++) {
if (isPalindromic(p + i, lastEqual(p + i, q)) == 1) {
rightmost = lastEqual(p + i, q);
printf("Palindrome at index %d, length %ld\n", i, &p - &rightmost);
}
}
return 0;
}
And the output should be like these but I cant figure out how to find lenght and why it doesnt count the single digit number as a palindrome like this 8 :
{3,6,7,8,7,6,5,3,5} so 3 to 3 is not a palindrome 6 to 6 is 7 to 7 is and 8 should be counted as well because there is not a pair of 8
The output Should be like these:
Input Array: {1}
Output: “palindrome at index 0, length: 1”
Input Array: {5, 6, 7, 8, 7, 6, 5, 2, 5}
Output: “palindrome at index 0, length: 7”
Input Array: {2, 7, 6, 11, 10, 11, 6, 5, 3}
Output: “palindrome at index 2, length: 5”
Input Array: {7, 8, 9, 8, 7}
Output: “palindrome at index 0, length: 5”
Input Array: {2, 7, 4, 3, 2, 6, 1, 2, 1}
Output: “palindrome at index 6, length: 3”
Here is a simpler version of isPalindromic with the same arguments, and a much simpler version of main() to find all palindromes:
#include <stdio.h>
int isPalindromic(int *p, int *q) {
while (p < q) {
if (*p++ != *q--)
return 0;
}
return 1;
}
int main() {
int arr[] = { 3, 6, 7, 8, 7, 6, 5, 3, 5 };
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; i++) {
for (int j = i; j < len; j++) {
if (isPalindromic(arr + i, arr + j))
printf("Palindrome at index %d, length %d\n", i, j - i + 1);
}
}
return 0;
}
If you just want to output the longest palindrome, change the main function to this:
int main() {
int arr[] = { 3, 6, 7, 8, 7, 6, 5, 3, 5 };
int len = sizeof(arr) / sizeof(arr[0]);
int max_pos = 0, max_len = 1;
for (int i = 0; i < len; i++) {
for (int j = i + max_len; j < len; j++) {
if (isPalindromic(arr + i, arr + j)) {
max_pos = i;
max_len = j - i + 1;
}
}
}
printf("Longest palindrome at index %d, length %d\n", max_pos, max_len);
return 0;
}
Related
I'm trying to solve a problem where I have to identify the number of pairs in an array that have the same mean/average as the original array.
Though I have solved the problem with nested loops(refer to the code below), I wanted to reduce the complexity of my solution, and I'm not getting any ideas so far.
Update: 'T' is just a variable representing the number of test cases. You can assume that to be 1.
#include <stdio.h>
#include <stdlib.h>
int comparator(const void *p, const void *q) {
int l = *(int *)p;
int r = *(int *)q;
return (l-r);
}
int fSum(int *Arr, int N){
int sum = 0;
for(int i=0; i<N; i++){
sum+=Arr[i];
}
return sum;
}
int main(void) {
int i=1, T, N, pos = 1, j=0, k=0, c = 0, sum;
int Arr[100000];
scanf("%d",&T);
while(i<=T){
scanf("%d", &N);
c = 0;
j = 0;
while(j<N){
scanf("%d", &Arr[j]);
++j;
}
qsort(Arr, N, sizeof(int), comparator);
sum = fSum(Arr, N);
for(j=0; j<N-1; j++){
for(k=N-1; k>=j+1; k--){
if(sum*2 == ((Arr[j]+Arr[k])*N)) {
c++;
}
else{
if(sum*2 > ((Arr[j]+Arr[k])*N))
break;
}
}
}
printf("%d\n", c);
++i;
}
return 0;
}
The general approach to problems like this is a single loop that maintains two indexes. One index starts at the beginning of the array, the other at the end. When the indexes meet in the middle, the loop is finished. In the body of the loop, the code must decide whether to update one index, or the other, or both.
For this particular problem, there are couple of additional wrinkles, which are caused by duplicates in the array.
For example, given the array { 1, 1, 1, 4, 5, 12, 15, 15, 18 }, there are 7 pairs. There are three 1's that can be matched with either of the two 15's, giving 6 possible pairs. The 4,12 pair is the seventh pair. So when the code finds a pair of distinct number that have the correct average, it must count the number of duplicates of each number. The number of pairs is then updated by the product of the two counts.
Given the array { 2, 3, 4, 8, 8, 8, 12, 12, 15 }, there are 5 pairs. Three pairs due to the three 8's, plus two ways to pair a 4 with a 12. When the average value is present in the array, and is duplicated, one index will reach the first instance of the average while the other will reach the last. The duplicate count can be computed from the two indexes, and the number of pairs is the number of ways to choose any two of the duplicates.
Here's a sample implementation using a single loop that updates two indexes:
#include <stdio.h>
void showArray(int Arr[], int N)
{
printf("Arr[] = {");
if (N > 0)
printf(" %d", Arr[0]);
for (int i = 1; i < N; i++)
printf(", %d", Arr[i]);
printf(" }\n");
}
int computeSum(int Arr[], int N)
{
int sum = 0;
for (int i=0; i < N; i++)
sum += Arr[i];
return sum;
}
int solve(int Arr[], int N)
{
showArray(Arr, N);
int sum = computeSum(Arr, N);
printf("N=%d sum=%d\n", N, sum);
int pairs = 0;
for (int j=0, k=N-1; k > j; )
{
if ((Arr[j] + Arr[k])*N > sum*2)
{
// the average is too high, so skip the larger value
k--;
}
else if ((Arr[j] + Arr[k])*N < sum*2)
{
// the average is too low, so skip the smaller value
j++;
}
else if (Arr[j] == Arr[k])
{
// handle the case where the average value is present and duplicated
int repeat = k - j + 1;
pairs += (repeat * (repeat-1)) / 2;
break;
}
else
{
// handle the case where two distinct numbers in the array have the correct average
// note that if there are duplicates of the numbers, the indexes are updated to the next non-duplicate
int oldj = j++;
while (Arr[j] == Arr[oldj])
j++;
int oldk = k--;
while (Arr[k] == Arr[oldk])
k--;
pairs += (j - oldj) * (oldk - k);
}
}
return pairs;
}
#define len(arr) (sizeof(arr) / sizeof(arr[0]))
int main(void)
{
int Arr1[] = { 1, 4, 5, 6, 6, 7, 7, 11, 15, 18 };
printf("pairs=%d\n\n", solve(Arr1, len(Arr1)));
int Arr2[] = { 1, 1, 1, 4, 5, 12, 15, 15, 18 };
printf("pairs=%d\n\n", solve(Arr2, len(Arr2)));
int Arr3[] = { 2, 3, 4, 8, 8, 8, 12, 12, 15 };
printf("pairs=%d\n\n", solve(Arr3, len(Arr3)));
}
Output from the code:
Arr[] = { 1, 4, 5, 6, 6, 7, 7, 11, 15, 18 }
N=10 sum=80
pairs=2
Arr[] = { 1, 1, 1, 4, 5, 12, 15, 15, 18 }
N=9 sum=72
pairs=7
Arr[] = { 2, 3, 4, 8, 8, 8, 12, 12, 15 }
N=9 sum=72
pairs=5
Question
There are two arrays, one contains a large number of numbers (arr1) that may have a few repeating sequences for example 1,2,4 might repeat multiple times in this array. There is another array (arr2) that will be assigned by the user.
I need a way to search arr1 for the exact input the user gave for arr2. For a match to be valid, all the elements have to be in the exact same order as entered by the user.
For example, if the user enters 1,2,4,3 the program has to find 1,2,4,3 in that exact order in arr1, this means that 1,2,3,4 in arr1 should not be counted as a match. Below is what I have been able to come up with so far, but this returns true even if just the first element of the 2 arrays matches.
for (int i=0; i<size1; i++)
{
for (int j = 0; j<size2; j++)
{
if(arr1[i] == arr2[j])
{
printf("found a match %d", j);
break;
}
else if (arr1[i] != arr2[j])
{
printf("not match");
break;
}
Below is the complete code :-
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = {1, 2, 4, 2, 2, 2, 1, 1, 2, 4, 3, 4, 4, 1, 2, 4, 4, 1, 3, 3};
int size1 = (int) (sizeof(arr1)/sizeof(arr1));
int arr2[] = {1, 2, 4};
int size2 = (int) (sizeof(arr2)/sizeof(arr2[0]));
int match = 0;
for (int i=0; i<size1; i++)
{
for (int j = 0; j < size2; j++) {
if (arr1[i] != arr2[j]) {
match = 1;
break;
}
}
}
if(match == 1){
printf("Not a match");
}else if(match == 0){
printf("The lists match");
}
return 0;
}
if you look at the arr1 and arr2, I need a way to return the index 0,7,13 and also this is still rough since arr2 is technically dynamic since it is assigned by the user and has no fixed size, only arr1 will have a fixed size.
Your question is similar to finding substrings in a string. But characters are replaced with integers.
Here is a program that will find the matches. It has some debug print statements to show how it works.
#include <stdio.h>
int g_Arr2_Changed=0; //----Global boolean if arr2 changes.
int main(int argc, const char *argv[])
{ int arr1[] = {1, 2, 4, 2, 2, 2, 1, 1, 2, 4, 3, 4, 4, 1, 2, 4, 4, 1, 3, 3};
int size1 = (int) (sizeof(arr1)/sizeof(int));
int arr2[] = {1, 2, 4};
int size2 = (int) (sizeof(arr2)/sizeof(int));
int patternStart = -1; //----Start pattern in arr1.
int nPatternMatch = 0; //----Number of ints matched so far.
for (int i=0; i<size1; i++)
{ int checkInt = arr1[i];
//printf("[%i](%i)", i, checkInt);
if (nPatternMatch == 0) //----No integers are matched yet.
{ //printf("<None>");
//----Is checkInt the start of arr2?
if (arr2[nPatternMatch] == checkInt)
{ patternStart=i; nPatternMatch++; //printf("<start>");
}
}
else //----At least one integer has been matched already.
{ //printf("<Some>");
//----Is checkInt a continuation?
if (arr2[nPatternMatch] == checkInt)
{ nPatternMatch++; //----Matched another integer.
//printf("<matched>");
}
else
{ //printf("<NotMatched>");
i = patternStart; //---- for() will add one.
patternStart = - 1;
nPatternMatch = 0; //----Not match. Start at next int.
}
}
//----If match found print and reset for next.
if (nPatternMatch == size2)
{ printf("Pattern found at %i\n", patternStart);
i = patternStart + 1;
patternStart = -1; nPatternMatch = 0;
}
//----Just in case the global variable says arr2 changed.
if (g_Arr2_Changed != 0) //----Start over.
{ //printf("<arr2 changed.>");
i=0; patternStart = -1; nPatternMatch = 0;
size2 = (int) (sizeof(arr2)/sizeof(int));
}
//printf("\n");
}
return 0;
}
This code will return a match for every character that is found in the same position in both lists.
So if you you want to verify the whole list, you should set an int, to identify if there is even one character that doesn't match in both lists.
If you want to show the list that match, you just have to print the whole list inside the second if.
int match = 0;
for (int i=0; i<size1; i++)
{
for (int j = 0; j < size2; j++) {
if (arr1[i] != arr2[j]) {
match = 1;
break;
}
}
if(match == 1){
printf("Not a match");
}else if(match == 0){
printf("The lists match");
printf("First character: %c", arr2[0]);
}
match = 0;
}
Would you please try the following:
#include <stdio.h>
int main()
{
int arr1[] = {1, 2, 4, 2, 2, 2, 1, 1, 2, 4, 3, 4, 4, 1, 2, 4, 4, 1, 3, 3};
int size1 = sizeof arr1 / sizeof arr1[0];
int arr2[] = {1, 2, 4};
int size2 = sizeof arr2 / sizeof arr2[0];
int match;
int i, j;
for (i = 0; i < size1 - size2 + 1; i++) {
match = 0;
for (j = 0; j < size2; j++) {
if (arr1[i + j] != arr2[j]) {
match = 1;
break;
}
}
if (! match) {
printf("matched at %d\n", i);
}
}
return 0;
}
It will output:
matched at 0
matched at 7
matched at 13
If you want to assign an array to the list of the matched indices, it will be easy for you to modify the code.
I have an array [1, 2, 3, 4, 5, 6, 7, 8] and I need to get [__, __, 1, 2, 3, 4, 5, 6] where I can put my new elements in the blank spaces. I tried to do it in a standard way:
int temp1 = arr[len - 1];
int temp2 = arr[len - 2];
for (int i = len - 1; i > 1; i -= 2) {
arr[i] = arr[i - 1];
arr[i - 1] = arr[i - 2];
}
arr[0] = temp1;
arr[1] = temp2;
but it seems to do nothing at all.
You're only moving elements by one space, not by two. Take a look at the following:
#include <stdio.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
int len = sizeof(arr) / sizeof(int);
printf("len = %d\n", len);
int temp1 = arr[len - 1];
int temp2 = arr[len - 2];
printf("temp1 = %d\n", temp1);
printf("temp2 = %d\n", temp2);
for(int i = len-1 ; i > 1 ; --i)
{
printf("Moving arr[%d] to arr[%d]\n", i-2, i);
arr[i] = arr[i-2];
}
arr[0] = temp1;
arr[1] = temp2;
for(int i = 0 ; i < len ; ++i)
printf("arr[%d] = %d\n", i, arr[i]);
}
onlinegdb here
EDIT
And if you'd rather do away with the loop and just copy the memory in one shot you can use:
#include <stdio.h>
#include <string.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
int len = sizeof(arr) / sizeof(int);
printf("len = %d\n", len);
int temp1 = arr[len - 1];
int temp2 = arr[len - 2];
printf("temp1 = %d\n", temp1);
printf("temp2 = %d\n", temp2);
memmove(((int *)arr)+2, arr, (len-2)*sizeof(int));
arr[0] = temp1;
arr[1] = temp2;
for(int i = 0 ; i < len ; ++i)
printf("arr[%d] = %d\n", i, arr[i]);
}
Note here that I've used memmove instead of memcpy because the source and destination buffers overlap. memmove handles this correctly, while memcpy is not required to do so.
onlinegdb here
I suppose that code rewrite right this way
int arr[8] = { 1,2,3,4,5,6,7,8 };
for( int i = 0 ; i < 8 ; i++ ){
arr[7-i] = arr[7-i-1];
}
for( int i = 0 ; i < 8 ; i++ ){
arr[7-i] = arr[7-i-1];
}
//here, arr[8] = { 1,1,1,2,3,4,5,6 }
//so, you can put new two elements in arr[0], arr[1]
the below might be useful for you,
#include <stdio.h>
#include <memory>
int main()
{
int temp1[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int temp2[10] = { 0 }; // to avoid garbage values in 0 & 1 positions or you may find a place holder to indicate empty
memcpy(&temp2[2], temp1, sizeof(temp1));
for (int i = 0; i < 10; ++i)
printf("%d ", temp2[i]);
}
I was hoping to get some input on how to correctly find the mode of a sorted array in C. Here's what I'm working with. First, my freqDistrib function:
void freqDistrib(int t[], int num) {
int i, j, x;
static int f[SIZE];
printf("\n\n");
printf("Part C:\n");
printf(" %-5s %-16s\n", "score", "frequency");
printf(" %-5s %-16s\n", "-----", "---------");
for (i = 1; i < num; i++) {
x = t[i];
j = i - 1;
while (j >= 0 && x > t[j]) {
t[j + 1] = t[j];
j = j - 1;
}
t[j + 1] = x;
} // sorts input in descending order
for (i = 0; i < num; i++) {
++f[t[i]];
if (t[i] != t[i + 1])
printf(" %3d %7d\n", t[i], f[t[i]]);
} // finds the frequency of each input and prints
}
and my mode function:
void modeScore(int t[], int num) {
int i, j, max, mode;
int f[SIZE];
for (i = 0; i < num; i++) {
f[t[i]]++;
}
mode = 0;
max = 0;
for (j = 0; j < num; j++) {
if (f[j] > max) {
max = f[j];
mode = j;
}
}
printf("\n\n");
printf("Part F:\n");
printf("%3d is mode\n", mode);
}
Output right now:
0 is mode
I realize that I need to compare the current frequency tally to a max, and if it is higher than set it equal to max. I just can't for the life of my figure out why this isn't working. Any input would be appreciated thanks.
As noted in a comment, the principal problem was that you did not initialize f in the function.
Here's working code which shows that was all the change that was necessary:
#include <stdio.h>
enum { SIZE = 100 };
static void modeScore(int t[], int num)
{
int f[SIZE] = { 0 };
for (int i = 0; i < num; i++)
f[t[i]]++;
int mode = 0;
int max = 0;
for (int j = 0; j < num; j++)
{
if (f[j] > max)
{
max = f[j];
mode = j;
}
}
printf("Part F: %3d is mode (count %d)\n", mode, max);
}
int main(void)
{
int data[] =
{
/* random -n 40 0 9 | commalist -b ' ' -l 38 */
7, 8, 3, 8, 5, 9, 5, 8, 9, 6,
8, 0, 1, 8, 2, 0, 3, 4, 3, 3,
3, 0, 2, 7, 5, 4, 6, 5, 9, 0,
1, 9, 1, 7, 8, 0, 5, 4, 0, 8,
};
enum { DATA_SIZE = sizeof(data) / sizeof(data[0]) };
modeScore(data, DATA_SIZE);
return 0;
}
For the given data, the output is:
Part F: 8 is mode (count 7)
(Funny coincidence: the first time I ran it — with slightly different data — the answer came back as Part F: 0 is mode (count 7). This was actually correct; I changed one of the zeros into an eight to produce the current result.)
Note that I would normally design the function to return the modal value, rather than have it do the printing. As it stands, it can't be reused because the printing is not material to most code that wants to determine the mode.
The code also does not check that the values in t fall in the range 0..SIZE-1 (but it should).
The parameter order you use is traditional, but there is at least nominally some advantage to using:
void modeScore(int num, int t[num])
to express explicitly that the array t has num elements in it. The size must precede its use in the array dimentson, though.
Since you say the array is sorted, you don't need to create a temporary array to count the values. Instead, you just need to traverse the input, keeping count of how many identical values you've seen in the current run. At the end of the run, then compare the length of the run to the previous longest run, and update if the new run is longer.
(Actually, we update whenever the current run is longer, so we don't forget to update if the mode is the very last value).
Notice that we no longer need SIZE to bound our values; we can now work with the full range of int if we wish.
#include <stdio.h>
static void modeScore(const int t[], int num)
{
int start = 0;
int mode = t[0];
int score = 0;
for (int i = 1; i < num; ++i) {
if (i - start > score) {
// a longer run than the previous candidate
score = i - start;
mode = t[start];
}
if (t[start] != t[i])
// we've reached a change in value
start = i;
}
printf("Part F: %3d is mode (count %d)\n", mode, score);
}
You didn't provide a main(), so I adapted Jonathan Leffler's:
int main(void)
{
int data[] =
{
/* random -n 40 0 9 | commalist -b ' ' -l 38 */
0, 0, 0, 0, 0, 0, 1, 1, 1, 2,
2, 3, 3, 3, 3, 3, 4, 4, 4, 5,
5, 5, 5, 5, 6, 6, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
};
modeScore(data, sizeof data / sizeof data[0]);
return 0;
}
Say I have an array:
int {2, 2, 2, 6, 6, 2, 2, 5, 5, 5}
and I want to delete all the adjacent duplicates so that it becomes
int {2, 6, 2, 5}
How can I do this?
Not sure what you have tried. My idea would be like this.
int i, num[] = {2, 2, 2, 6, 6, 2, 2, 5, 5, 5};
// Prepare new array for the result (result never larger than num[])
int *newNum = malloc(sizeof(num));
int used = 0, last = 0;
// Get number of elements in num[], which is 10 in this example
size_t n = sizeof(num) / sizeof(int);
for (i = 0; i < n; i++)
{
if (num[i] != last)
{
newNum[used++] = num[i];
}
last = num[i];
}
printf("new array: \n");
for (i = 0; i < used; i++)
{
printf("%i ", newNum[i]);
}
like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
int size = 10;
int *array = memcpy(malloc(size * sizeof(*array)), (int[]){2, 2, 2, 6, 6, 2, 2, 5, 5, 5}, size * sizeof(*array));
int i, new_size;
for(i = new_size = 1; i < size; ++i){
if(array[new_size-1] != array[i])
array[new_size++] = array[i];
}
if(size > new_size){
size = new_size;
array = realloc(array, size * sizeof(*array));
}
for(i = 0; i < size; ++i)
printf("%d ", array[i]);//2 6 2 5
free(array);
return 0;
}