Check recurring characters in simple array [C] - c

The part that is commented 'recurring characters code' is a bit flawed as later on when I try to print the letter and number of occurrences, the letter is correct, but the number of occurrences is some random number. Can somebody explain where my logic is faulty?
#include <stdio.h>
#include <stdlib.h>
#define MAX 20
int main()
{
//declare variables
char arr[MAX], ch;
int counter1 = 0, counter2 = 0, i, j, temp, mostcommon[128], x = 0, y = 0;
//ask for user input until array reaches MAX or is interrupted by the 'X' character and append arr[i]
for(i = 0; i < MAX; i++)
{
printf("Input %d. character into array: ", i + 1);
ch = getchar();
if (ch == 'X'){
break;
}
getchar();
arr[i] = ch;
counter1++;
}
//recurring characters code
for (i = 0; i < 128; i++){
mostcommon[i] = 0;
}
x = mostcommon[0];
y = 0;
for (i = 0; i < counter1; i++)
{
mostcommon[(int) arr[i]] += i;
}
for (i = 0; i < 128; i++){
if (x < mostcommon[i]){
x = mostcommon[i];
y = i;
}
}
//print array as it was appended
printf ("\nArray:");
for (i = 0; i < counter1; i++)
{
printf("\narray[%d] = %c", i, arr[i]);
}
//sort array by descending ASCII value
for(i = 0; i < counter1 - 1; i++)
{
for(j = i + 1; j < counter1; j++)
{
if (arr[i] < arr[j])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
//print sorted array
printf ("\n\nSorted array:");
for (i = 0; i < counter1; i++)
{
printf("\narray[%d] = %c", i, arr[i]);
}
//print array without reoccuring characters
printf ("\n\nFinal array:");
for (i = 0; i < counter1; i++)
{
if (arr[i] != arr[i-1]){
printf("\narray[%d] = %c", counter2, arr[i]);
counter2++;
}
}
printf("\n\nThe most common character is %c and it recurred %d times", y, x);
return 0;
}

One note before:
*Shouldn't you raise counter1 at the start of the loop ? Because if you don't - when X is entered it won't raise counter1 and I supposed you want number of characters entered.
Now to the code - first in the loop:
for (i = 0; i < counter1; i++)
{
mostcommon[(int) arr[i]] += i;
}
What was your purpose? If you want the number of occurrences of the character then the loop should look like this:
for(i = 0 ; i < counter1 ; i++)
{
mostcommon[(int)arr[i]]++;
}
as "+= i" has no purpose according to my understanding - so it would be kind of random as you describe. Hope it helped.

Related

How to randomize a to p without repitition

I want to randomize a to p without repetition.
int main(){
int array2[4][4];
bool arr[100]={0};
int i;
int j;
srand(time(NULL));
for(i=0; i<=3; i++){
for(j=0; j<=3; j++){
int randomNumber1;
randomNumber1 = (rand() % (82-65+1))+65;
if (!arr[randomNumber1])
{
printf("%c ",randomNumber1);
array2[i][j]=randomNumber1;
}
else
{
i--;
j--;
arr[randomNumber1]=1;
}
}
printf("\n");
}
return;
the output still has repeat alphabet. I want to have the output in 4x4 with with all a to p without it repeating.
There are some errors in your code. IMHO the most serious is that arr[randomNumber1]=1; is is the wrong branch of the test. That means that your current code does not invalidate once a number was used but only if it has already been invalidated => if you control the arr array at the end of the program all value are still 0.
That is not all. When you get a duplicate, you should only reset the inner loop, and you are currently off by 2 in your maximum ascii code: you go up to R when you want to stop at P.
Your code should be:
for (i = 0; i <= 3; i++) {
for (j = 0; j <= 3; j++) {
int randomNumber1;
randomNumber1 = (rand() % (81 - 65)) + 65;
if (!arr[randomNumber1])
{
printf("%c ", randomNumber1);
array2[i][j] = randomNumber1;
arr[randomNumber1] = 1;
}
else
{
//i--;
j--;
}
}
printf("\n");
}
But this kind of code is terribly inefficient. In my tests it took 30 to 60 steps to fill 16 values, because random can return duplicates. This is the reason why you were advised in comments to use instead the modern algorithm for Fisher-Yates shuffle:
int main() {
int array2[16];
unsigned i, j, k=0;
// initialize array with alphabets from A to P
for (i = 0; i < sizeof(array2); i++) {
array2[i] = 'A' + i;
}
// Use Fisher-Yates shuffle on the array
srand(time(NULL));
for (i = 15; i > 0; i--) {
j = rand() % (i + 1);
if (j != i) {
int c = array2[i];
array2[i] = array2[j];
array2[j] = c;
}
}
// Display a 4x4 pattern
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
printf("%c ", array2[k++]);
}
printf("\n");
}
return 0;
}
Which shuffles the array in only 16 steps.
Here is the outline
// Need some #includes here - exercise for the reader
char items[] = "abcdefghijklmnopqrstuvwxyz";
int len = sizeof(items);
srand(time(NULL));
while (len > 0) {
int r = rand() % len;
printf("%c", items[r]);
len--;
items[r] = items[len];
}
This should do the trick to print the whole alphabet in random order without repeats. Modify to do what you need it to do

Why am I experiencing an infinite loop here?

My code never stops asking for input so I think I must've made an infinite loop, but I can't find where the error is. I've also noticed that when inserting the input line by line, it prints the result of one loop after inserting the first line of the second loop, which seems incorrect to me. Please help me debug. (For further context, the code is supposed to receive a number we'll call n, and then scan 3n more lines, which are basically n bundles of 3 similar lines. The 2nd and 3rd lines are two words with the same num of characters, and the 1st line is that num. The output is whether or not these words are anagrams.)
#include <stdio.h>
int main() {
int n, l;
scanf("%d\n", &n);
for (int i = 1; i <= n; i++) {
scanf("%d\n", &l);
char A[l], B[l];
for (int j = 0; j < l; j++) {
scanf("%c", &A[j]);
scanf("\n");
}
for (int j = 0; j < l; j++) {
scanf("%c", &B[j]);
scanf("\n");
}
for (int k = 0; k < l; k++) {
int result = 0;
for (int j = 0; j < l; j++) {
if (A[k] == B[j]) {
result = 1;
}
}
if (!result) {
printf("\nNO\n");
return 0;
}
}
printf("\nYES\n");
}
}
Example:
input:
2
6
listen
silent
4
Evil
live
output:
YES
NO
It's because you are asking for input over and over and over again,
Not sure what you are trying to achieve, but start by removing the extra scanfs
try this,
#include <stdio.h>
int main() {
int n, l;
scanf("%d\n", &n);
for (int i = 1; i <= n; i++) {
char A[l], B[l];
for (int k = 0; k < l; k++) {
int result = 0;
for (int j = 0; j < l; j++) {
if (A[k] == B[j]) {
result = 1;
}
}
if (!result) {
printf("\nNO\n");
return 0;
}
}
printf("\nYES\n");
}
}
Your scanf calls wait for an extra \n which requires more input to enter.
To fix this, remove the \n from your scanf calls. Also remove the extra calls when you enter A and B:
I have added some debug code to demonstrate where you are in your program execution while you enter your input.
#include <stdio.h>
int main() {
int n, l;
int res;
res=scanf("%d", &n);
printf ("res=%d, n=%d\n", res, n);
for (int i = 1; i <= n; i++) {
res = scanf("%d", &l);
printf ("res=%d, l=%d\n", res, l);
// char A[l], B[l];
char A[l+1], B[l+1];
for (int j = 0; j < l; j++) {
scanf(" %c", &A[j]);
}
printf ("A done\n");
for (int j = 0; j < l; j++) {
scanf(" %c", &B[j]);
}
printf ("B done\n");
A[l] = 0; B[l] = 0;
printf ("A=\"%s\" - B=\"%s\"\n", A, B);
...
Now your input should work properly.
But your code also contains another error.
You will treat "12344" and "11234" as correct match wchich is wrong.
To fix this you need to remove each matching character from B:
for (int k = 0; k < l; k++) {
int result = 0;
// We compare A[k] with the remaining characters in B only
for (int j = k; j < l; j++) {
if (A[k] == B[j]) {
result = 1;
B[j] = B[k]; // Replace matching character with non-matching character we checked earlier.
break;
}
}
if (!result) {
printf("\nNO\n");
return 0;
}
}
printf("\nYES\n");
This code stops as soon as the first match is found and removed that character from B.
The entries in B are rearranged to keep the unused entries at the end.
The full code looks like this:
#include <stdio.h>
int main() {
int n, l;
int res;
res=scanf("%d", &n);
printf ("res=%d, n=%d\n", res, n);
for (int i = 1; i <= n; i++) {
res = scanf("%d", &l);
printf ("res=%d, l=%d\n", res, l);
// char A[l], B[l];
char A[l+1], B[l+1];
for (int j = 0; j < l; j++) {
scanf(" %c", &A[j]);
}
printf ("A done\n");
for (int j = 0; j < l; j++) {
scanf(" %c", &B[j]);
}
printf ("B done\n");
A[l] = 0; B[l] = 0;
printf ("A=\"%s\" - B=\"%s\"\n", A, B);
for (int k = 0; k < l; k++) {
int result = 0;
for (int j = k; j < l; j++) {
if (A[k] == B[j]) {
result = 1;
B[j] = B[k];
break;
}
}
if (!result) {
printf("\nNO\n");
return 0;
}
}
printf("\nYES\n");
}
}
output:
~/stackoverflow$ ./test
4
res=1, n=4
2
res=1, l=2
12
A done
21
B done
A="12" - B="21"
YES
6
res=1, l=6
liver1
A done
evil1r
B done
A="liver1" - B="evil1r"
YES
3
res=1, l=3
111
A done
111
B done
A="111" - B="111"
YES
4
res=1, l=4
abcd
A done
dcbb
B done
A="abcd" - B="dcbb"
NO

Print letters in lower triangle in C

I spent hours in printing a lower triangle in C. However, I just cannot figure out how to solve this same question with array.
Below is one of the solution I found on net:
int main(void)
{
char ch='A';
int i,j;
for(i=1;i<7;i++)
{
for(j=0;j<i;j++)
printf("%c",ch++);
printf("\n");
}
return 0;
}
Below is how I try to do the same thing:
#define SIZE 8
int main(void){
char Alphabet[SIZE];
int i, j;
for (i = 0, j = 'A'; i < SIZE, j < 'A' + SIZE; i++, j++){
Alphabet[i] = j;
}
for (i = 0; i <= 7; i++){
for (j = 0; j <= i; j++){
printf("%c", Alphabet[j+i]);
}
printf("\n");
}
return 0;
}
The result of the code above is :
A
BC
CDE
DEFG
EFGHI
FGHIJK
GHIJKLM
HIJKLMNO
What should I revise if I want to print as follow:
A
BC
DEF
GHIJ
KLMNO
PQRSTU
Thank you.
Keep a track of elements printed from the Alphabet array so far and in the inner loop start printing from next element onward. You can do:
#include <stdio.h>
#define SIZE 26
int main(void) {
char Alphabet[SIZE];
for (int i = 0; i < SIZE; i++) {
Alphabet[i] = 'A' + i;
}
// Or simply have the Alphabet array initialized like this
// char Alphabet[SIZE] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int k = 0;
for (int i = 0; i < 6; i++) {
for (int j = 0; j <= i && k < SIZE; j++) {
printf("%c", Alphabet[k++]);
}
printf("\n");
}
return 0;
}
Output:
# ./a.out
A
BC
DEF
GHIJ
KLMNO
PQRSTU
EDIT:
In the comments, a fellow SO contributor said that the above approach is same as the one OP already found as a solution and OP might be looking for approach of calculating the Alphabet array index using i and j only and without use of variable keeping track of array index. Below is the program which does not use any extra variable to keep the track of Alphabet array index to print characters in inner loop and calculating the index using i and j:
#include <stdio.h>
#define SIZE 26
#define ARRLOC(x) ((x * ((x + 1) / 2)) + ((x % 2 == 0) ? (x / 2) : 0))
int main(void) {
char Alphabet[SIZE];
for (int i = 0; i < SIZE; i++){
Alphabet[i] = 'A' + i;
}
// Or simply have the Alphabet array declared like this
// char Alphabet[SIZE] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < 6; i++){
for (int j = 0; j <= i && (ARRLOC(i) + j) < SIZE; j++){
printf("%c", Alphabet[ARRLOC(i) + j]);
}
printf("\n");
}
return 0;
}
Output:
# ./a.out
A
BC
DEF
GHIJ
KLMNO
PQRSTU
You can just have a third 'index' variable that keeps track of which letter to output across both loops (I've called this k in the code below). Also, you need to make your Alphabet array bigger (26 seems like a reasonable number); then, if that k variable gets past 'Z', we can simply loop back to 'A' using the modulo operator (%):
#include <stdio.h>
#define SIZE 26
int main(void)
{
char Alphabet[SIZE];
int i, j, k;
for (i = 0; i < SIZE; i++) Alphabet[i] = 'A' + i;
int k = 0;
for (i = 0; i <= 7; i++) {
for (j = 0; j <= i; j++) {
printf("%c", Alphabet[k % 26]); // If past the end, loop back with the "%" operator
++k;
}
printf("\n");
}
return 0;
}
Or we can make the code a little more 'succinct' (though perhaps less clear) by initializing the k variable at the start of the outer loop and incrementing at the end of the inner loop:
for (k = i = 0; i <= 7; i++) { // Initialize "k" here ...
for (j = 0; j <= i; j++, k++) { // .. but increment it here!
printf("%c", Alphabet[k % 26]); // If past the end, loop back with the "%" operator
}
printf("\n");
}
If you want an 8 by 8 pyramid, you won't have enough characters to do it using the alphabet (requires 36), so I made the alphabet repeat itself (u could also make it go to numeric instead?)
#define SIZE 8
int area(int size);
int main(void){
char Alphabet[area(SIZE)];
int i, j;
for (i = 0, j = 'A'; i < area(SIZE); i++, j++){
if (j > 'Z') j = 'A';
Alphabet[i] = j;
}
int idx=0;
for (i = 0; i < SIZE; i++){
for (j = 0; j <= i; j++){
printf("%c", Alphabet[idx++]);
}
printf("\n");
}
return 0;
}
int area(int size) {
if (size==1) return 1;
return size + area(size - 1);
}

Finding duplicate value in a row (2D array)

I would like to know how to find duplicate values in the 1st row of my 2d array.
I thought that by setting array[0][0] == array[i][j], it would check if the array[0][0] equals to the number of array[0][rest of the column]. But my code is just popping up my try again message whenever I put my first value.
Here's what I've tried so far.
void main(void)
{
int array[2][5];
int i, j, l, k;
printf("\Please enter 10 values\n");
for (j = 0; j < 5; j++)
{
for (i = 0; i < 2; i++)
{
scanf("%i", &array[i][j]);
for (k = 0; k < 2; k++)
{
for (l = 0; l < 5; l++)
{
while (array[0][0] == array[i][j])
{
printf("You entered 2 identical numbers in the first row, try again:\n");
scanf("%i", &array[i][j]);
}
}
}
}
}
}
// this isn't the fastest algorithm but it works because of the small length
int check_duplicates(int arr[], int len) {
// iterate through the array
for (int i = 0; i < len; i++) {
// only need to check to the right
// since the left elements have been checked previously
for (int j = i + 1; j < len; j++) {
if (arr[i] == arr[j]) {
// there's a duplicate, return
return 1;
}
}
}
// no duplicates found
return 0;
}
int main(void) {
int array[2][5];
int i, j, l, k;
printf("Please enter 10 values\n");
for (j = 0; j < 5; j++) {
for (i = 0; i < 2; i++) {
scanf("%i", &array[i][j]);
// a duplicate has been found
if (check_duplicates(array[0], j + 1)) {
printf("You entered a duplicate, try again.\n");
// undo one loop to read back into that position
i --;
}
}
}
return 0;
}

C array nondecreasing order insert value

I am writing a program that arranges an array in nondecreasing order; then, it inserts a value into the sequence. I can easily get numbers in the beginning and the middle of the array, but whenever I add a number that should go at the end, I keep getting 0. Where am I going wrong?
#include <stdio.h>
int main()
{
int array[10];
int i, j, n, m, temp, key, pos;
printf("Enter number of elements:\n");
scanf("%d", &n);
printf("Enter the elements:\n");
for (i = 0; i < n; i++)
{
scanf("%d", &array[i]);
}
printf("Input array elements:\n");
for (i = 0; i < n; i++)
{
printf("%d\n", array[i]);
}
for (i = 0; i < n; i++)
{
for (j = i + 1; j < n; j++)
{
if (array[i] > array[j])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
printf("Sorted list is\n");
for (i = 0; i < n; i++)
{
printf("%d\n", array[i]);
}
printf("Enter the element to be inserted X:\n");
scanf("%d", &key);
for (i = 0; ; i++)
{
if (key < array[i])
{
pos = i;
break;
}
}
m = n - pos + 1 ;
for (i = 0; i <= m; i++)
{
array[n - i + 2] = array[n - i + 1] ;
}
array[pos] = key;
printf("Final list is:\n");
for (i = 0; i < n + 1; i++)
{
printf("%d\n", array[i]);
}
}
If the number to be entered is larger than all elements the following loop poses an issue.
...
for (i = 0; ; i++)
{
if (key < array[i])
{
pos = i;
break;
}
}
If the number is largest,then the pos will be junk and not n.The default value of an array is junk.
Replace it with this.
for (i = 0;i<n ; i++)
{
if (key < array[i])
{
break;
}
}
pos = i;
...

Resources