Why does this code create the correct pattern? - c

I've recently started to learn the C programming language and therefore started tackling problems on Hackerrank. One of the problems is as follows:
In this problem, you need to print the pattern of the following form containing the numbers from 1 to n.
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
I saw a programmer on YouTube. He wrote a very short program to solve it:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define max(x,y) ((x)>(y)?x:y)
int main()
{
int n;
scanf("%d", &n);
int len = n*2 - 1;
for (int i = 0; i < len; i++){
for(int j = 0; j < len; j++){
printf("%d ",max( abs(n -i-1) + 1, abs(n-j-1) +1 ));
}
printf("\n");
}
return 0;
}
I already listed all the indexing of the 2n-1 x 2n-1 matrix and tried to observe the relationship. But I can't formulate the relation of max( abs(n -i-1) + 1, abs(n-j-1) +1 ).
I just don't get the idea of max( abs(n -i-1) + 1, abs(n-j-1) +1 ), why does this line of code get the correct the value of each element in the matrix?

Related

How to print a pattern using nested for loops?

How do I make my code have an output like this:
Enter your number: 4
1 1 1 2
2 2 2 3
3 3 3 4
4 4 4 5
I can't seem to figure out how to make it so the last digit prints the next value iteration.
#include <stdio.h>
int main(){
int num;
int i = 1;
printf("Enter your number: ");
scanf("%d", &num);
for(i = 1; i<=num; i++){
for(int j = 0; j<num; ++j)
{
printf("%d ",i);
}
printf("\n");
}
Doing this using nested loops are simple and doesn't require any kind of special calculations, if-statements or other more or less fancy stuff. Just keep it simple.
Your task is:
for each row:
print "rowindex+1 and a space" n-1 times
print "rowindex+2 and a newline" 1 time
"for each row" is one simple loop.
"n-1 times" is another (nested) simple loop.
So keep it simple... just two ordinary for-loops like:
#include <stdio.h>
int main()
{
int n = 4;
for (int i = 0; i < n; i++) // for each row
{
for (int j = 0; j < n-1; j++) // n-1 times
{
printf("%d ", i + 1);
}
printf("%d\n", i + 2); // 1 time
}
return 0;
}
Here is something kind of from out in the left field, and off topic, leaving behind not only the requirements of the homework, but the C language. However, we will find our way back.
We can solve this problem (sort of) using text processing at the Unix prompt:
We can treat the smallest square
12
23
as an initial seed kernel, which is fed through a little command pipeline to produce a square of the next size (up to a single digit limitation):
We define this function:
next()
{
sed -e 's/\(.\).$/\1&/' | awk '1; END { print $0 | "tr \"[1-9]\" \"[2-8]\"" }'
}
Then:
$ next
12
23
[Ctrl-D][Enter]
112
223
334
Now, copy the 3x3 square and paste it into next:
$ next
112
223
334
[Ctrl-D][Enter]
1112
2223
3334
4445
Now, several steps in one go, by piping through multiple instances of next:
$ next | next | next | next | next
12
23
[Ctrl-D][Enter]
1111112
2222223
3333334
4444445
5555556
6666667
7777778
The text processing rule is:
For each line of input, repeat the second-to-last character. E.g ABC becomes ABBC, or 1112 becomes 11112. This is easily done with sed.
Add a new line at the end which is a copy of the last line, with each digit replaced by its successor. E.g. if the last line is 3334, make it 4445. The tr utility helps here
To connect this to the homework problem: a C program could be written which works in a similar way, starting with an array which holds the 1 2 2 3 square, and grows it. The requirement for nested loops would be satisfied because there would be an outer loop iterating on the number of "next" operations, and then an inner loop performing the edits on the array: replicating the next-to-last column, and adding the new row at the bottom.
#include <stdio.h>
#include <stdlib.h>
#define DIM 25
int main(int argc, char **argv)
{
if (argc != 2) {
fputs("wrong usage\n", stderr);
return EXIT_FAILURE;
}
int n = atoi(argv[1]);
if (n <= 2 || n > DIM) {
fputs("invalid n\n", stderr);
return EXIT_FAILURE;
}
int array[DIM][DIM] = {
{ 1, 2 },
{ 2, 3 }
};
/* Grow square from size 2 to size n */
for (int s = 2; s < n; s++) {
for (int r = 0; r < s; r++) {
array[r][s] = array[r][s-1];
array[r][s-1] = array[r][s-2];
}
for (int c = 0; c <= s; c++) {
array[s][c] = array[s-1][c] + 1;
}
}
/* Dump it */
for (int r = 0; r < n; r++) {
for (int c = 0; c < n; c++)
printf("%3d ", array[r][c]);
putchar('\n');
}
return 0;
}
#include<stdio.h>
int main(){
int n;
printf("Enter the number: ");
scanf("%d",&n);
for(int i =1; i<=n; i++){
for(int j=1;j<=n;j++) {
if(j==n)
printf("%d\t",i+1);
else
printf("%d\t",i);
}
printf("\n");
}
return 0;}
Nested loops will drive you crazy, trying figure out their boundaries.
While I usually oppose adding more variables, in this case it seems justified to keep track of things simply.
#include <stdio.h>
int main() {
int n = 4, val = 1, cnt1 = 1, cnt2 = 0;
for( int i = 1; i < n*n+1; i++ ) { // notice the 'square' calculation
printf( "%d ", val );
if( ++cnt1 == n ) // tired of this digit? start the next digit
cnt1 = 0, val++;
if( ++cnt2 == n ) // enough columns output? start the next line
cnt2 = 0, putchar( '\n' );
}
return 0;
}
1 1 1 2
2 2 2 3
3 3 3 4
4 4 4 5
A single example of desired output is hard to go by, especially when the code doesn't help... Anyway, here's the output when 'n' = 5.
1 1 1 1 2
2 2 2 2 3
3 3 3 3 4
4 4 4 4 5
5 5 5 5 6
All of these kinds of assignments are to try to get you to recognize a pattern.
The pattern you are given
1 1 1 2
2 2 2 3
3 3 3 4
4 4 4 5
is very close to
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
which is an easy nested loop. Write a solution to the easier pattern. Once you have that you can then you can fix it.
Hint: Notice that the only thing that changes is the last item of the inner loop.
Edit
This totally breaks the spirit of the assignment, and if you, dear student, ever try to submit something like this your professor will... probably not care, but also know full well that you didn’t do it. If I were your professor you’d lose marks, even if I knew you weren’t cheating and had written something this awesome yourself.
Single loop. Stuff added to pretty print numbers wider than one digit (except the very last). Maths, yo.
#include <stdio.h>
#include <math.h>
void print_off_by_one_square( int n )
{
int width = (int)log10( n ) + 1;
for (int k = 0; k++ < n*n ;)
printf( "%*d%c", width, (k+n)/n, (k%n) ? ' ' : '\n' );
}
int main(void)
{
int n;
printf( "n? " );
fflush( stdout );
if ((scanf( "%d", &n ) != 1) || (n < 0))
fprintf( stderr, "%s\n", "Not cool, man, not cool at all." );
else
print_off_by_one_square( n );
return 0;
}
The way it works is pretty simple, actually, but I’ll leave it as an exercise for the reader to figure out on his or her own.
Here is a different concept. Some of the answers are based on the idea that we first think about
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
and then tweak the logic for the item in the last line.
But we can regard it like this also:
We have a tape which goes like this:
1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
and we are blindly cutting the tape into four-element pieces to form a 4x4 square. Suppose someone deletes the first item from the tape, and then adds 5:
1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5
Now, if we cut that tape blindly by the same process, we will get the required output:
1 1 1 2
2 2 2 3
3 3 3 4
4 4 4 5
Suppose we have a linear index through the tape, a position p starting at 0.
In the unshifted tape, item p is calculated using p / 4 + 1, right?
In the shifted tape, this is just (p + 1) / 4 + 1. Of course we substitute the square size for 4.
Thus:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fputs("wrong usage\n", stderr);
return EXIT_FAILURE;
}
int n = atoi(argv[1]);
int m = n * n;
if (n <= 0) {
fputs("invalid n\n", stderr);
return EXIT_FAILURE;
}
for (int p = 0; p < m; p++) {
printf("%3d ", (p + 1) / n + 1);
if (p % n == n - 1)
putchar('\n');
}
return 0;
}
$ ./square 2
1 2
2 3
$ ./square 3
1 1 2
2 2 3
3 3 4
$ ./square 4
1 1 1 2
2 2 2 3
3 3 3 4
4 4 4 5

Printing all permutations of n numbers

Print all n! permutations of the number 1,2,3,...,n.
Example: Input: 3
Output: 1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Following is my approach. My program is not working for inputs greater than 3. I understand the logic why it is not working , but I am unable to translate that logic into a code block to overcome that issue.
#include <stdio.h>
int permute(int n)
{
int a[n];
int i,j,k,store;
for(i=0;i<n;i++)
a[i]=i+1;
for(i=1;i<=n;i++)
{
for(j=0;j<n-1;j++)
{
store=a[j+1];
a[j+1]=a[j];
a[j]=store;
for(k=0;k<n;k++)
printf("%d ",a[k]);
printf("\n");
}
}
}
int main()
{
int n;
scanf("%d",&n);
permute(n);
return 0;
}
Following is the output for n as 4:
We can clearly see that some permutation are missing, and I know exactly the fault in my code. But I am unable to fix it.( I am a beginner , hence I don't know much advanced C libraries or functions)
One solution consists in calling the function recursively: you set the first number (n possible choices), then call the function for a size n-1.
Output, for n=4
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 3 2
1 4 2 3
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 3 1
2 4 1 3
3 2 1 4
3 2 4 1
3 1 2 4
3 1 4 2
3 4 1 2
3 4 2 1
4 2 3 1
4 2 1 3
4 3 2 1
4 3 1 2
4 1 3 2
4 1 2 3
#include <stdio.h>
#include <stdlib.h>
void swap (int *i, int *j) {
int temp = *i;
*i = *j;
*j = temp;
}
void permute(int index, int* arr, int n) {
if (index == n-1) {
for (int k = 0; k < n; ++k) {
printf ("%d ", arr[k]);
}
printf ("\n");
return;
}
for (int i = index; i < n; i++) {
swap (arr + index, arr + i);
permute (index+1, arr, n);
swap (arr + i, arr + index);
}
return;
}
int main()
{
int n;
if (scanf("%d",&n) != 1) exit (1);
int arr[n];
for (int i = 0; i < n; ++i) arr[i] = i+1;
permute(0, arr, n);
return 0;
}

recursion - data structure course - print all possible series

I need to print all possible series that their sum is equal to N;
for example is n == 4 the output should be:
[1, 1, 1, 1]
[1, 1, 2]
[1, 2, 1]
[1, 3]
[2, 1, 1]
[2, 2]
[3, 1]
[4]
My way of thinking to solve this problem was:
print the series that the number i is not in the series
print the series that the number i is in the series, now need to find the sum of N-i.
my code:
#include <stdio.h>
#include <stdlib.h>
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
{
printf(" %d ", arr[i]);
}
printf("\n");
}
void printAllHelper(int* a,int size, int sum, int used,int index) {
if (sum == 0) {
a -= used;
printArr(a, used);
}
else if (sum < 0 || index == size)
{
return;
}
else {
for(int i = 1 ; i <= size ; i ++)
{
printAllHelper(a, size, sum, used, index + 1);
if (i <= sum)
{
*a = i;
}
printAllHelper(a+1, size, sum -i, used +1, index + 1);
}
}
}
void printAll(int num) {
int* myArray = (int*)malloc(num * sizeof(int));
printAllHelper(myArray,num,num,0,0);
}
void main() {
printAll(4);
}
my output:
3 1
3 1
3 1
3 1
3 1
3 1
3 1
3 1
3 1
4
1 3
4
2 2
4
3 1
4
4
1 3
1 1 2
1 3
1 2 1
1 3
1 3
1 3
4
1 3
4
2 2
4
3 1
4
4
2 2
2 1 1
2 2
2 2
2 2
2 2
4
1 3
4
2 2
4
3 1
4
4
3 1
3 1
3 1
3 1
3 1
4
1 3
4
2 2
4
3 1
4
4
4
4
Please try to explain to me your way of thinking, and how you approach this kind of problem, I want to be the very best like no one ever was :(.....
Your reasoning is not quite correct, but your code is almost right. The loop in your else part should be
for(int i = 1 ; i <= sum ; i ++) {
*a = i;
printAllHelper(a+1, size, sum-i, used+1, index+1);
}
With this, I get the output
1 1 1 1
1 1 2
1 2 1
1 3
2 1 1
2 2
3 1
4
The idea is basically: "The numbers sum to sum if the first number i is any number from 1 to sum and the rest of the numbers sum to sum - i."
Also, note that your code shows some room for improvement, e.g. the used and index variables seem a bit redundant. And with not adding numbers larger than sum or smaller than 1, the check whether sum < 0 || index == size is not necessary, either. Thus you also do not need the size parameter. Your printAllHelper could be simplified to something like this:
void printAllHelper(int* a, int sum, int index) {
if (sum == 0) {
printArr(a, index);
} else {
for(int i = 1 ; i <= sum ; i++) {
a[index] = i;
printAllHelper(a, sum-i, index+1);
}
}
}
(Note: C is not my native language, if you see more things to improve, please comment.)

Why 2 is not smaller than 10 on Codeblocks?

I just worked to my final exam with simple codes; when I try to sorting strings, I face annoying error. Why 2 is not smaller than 10 on my CodeBlocks IDE but is smaller than 10 on real and onlinegdb.com?
This is the annoying code:
#include <string.h>
#include <stdio.h>
#define STR_SIZ 20
int main()
{
char strArr[][STR_SIZ] = {"abc", "hdas", "sdfasf", "kakldf", "caksl", "casd", "keam", "cznjcx", "mnxzv", "jkalkds"};
char minStr[STR_SIZ];
strcpy(minStr, strArr[0]);
int N = sizeof(strArr)/sizeof(minStr);
// int N = 10;
for(int x = 0; x < N-1; x++)
{
printf("%d", x);
strcpy(minStr,strArr[x]);
int j;
for(j=1+x; j < 10; j++)
{
printf("%4d\n", j);
int cmp = strcmp(strArr[j], minStr);
if(cmp < 0)
strcpy(minStr,strArr[j]);
}
char temp[STR_SIZ];
strcpy(temp,strArr[x]);
strcpy(strArr[x], minStr);
strcpy(strArr[j], temp);
}
return 0;
}
Output on onlinegdb.com:
0 1
2
3
4
5
6
7
8
9
1 2
3
4
5
6
7
8
9
2 3
4
5
6
7
8
9
3 4
5
6
7
8
9
4 5
6
7
8
9
5 6
7
8
9
6 7
8
9
7 8
9
8 9
Output on CodeBlocks:
0 1
2
3
4
5
6
7
8
9
1 2
3
4
5
6
7
8
9
2
PS: I just have used Codeblock in the morning and it was okey with executing.
strArr has 10 elements. At the end of your loop, you call strcpy(strArr[j], temp);. This will write to strArr[10], which is out of bounds and will overwrite some unknown memory. Anything can happen after that.
You should save the j value when you copy a string into minStr.
FYI, your code above prints this as your final string order with onlinegdb:
abc
caksl
caksl
caksl
caksl
casd
cznjcx
cznjcx
jkalkds
jkalkds
So I think you have other problems as well.
try this
#include <string.h>
#include <stdio.h>
#define STR_SIZ 20
int main()
{
char strArr[][STR_SIZ] = {"abc", "hdas", "sdfasf", "kakldf", "caksl", "casd", "keam", "cznjcx", "mnxzv", "jkalkds"};
strcpy(minStr, strArr[0]);
// Calculate the number of elements this way.
const int N = sizeof(strArr)/sizeof(strArr[0]);
// int N = 10;
for(int x = 0; x < N-1; x++)
{
printf("%d", x);
int j;
for(j=1+x; j < N; j++) // Use N here too!
{
printf("%4d\n", j);
int cmp = strcmp(strArr[j], strArr[x]);
if(cmp < 0)
{
// Do the swaps only when needed.
char temp[STR_SIZ];
strcpy(temp,strArr[x]);
strcpy(strArr[x], strArr[j]);
strcpy(strArr[j], temp);
}
}
}
// Verify result
for(int x = 0; x < N; x++) printf("%s\n", strArr[x]);
return 0;
}
I moved your swap into your if check and got rid of your minStr as it was not needed. Notice how I calculate the N size too. Honestly, you were close, but you needed to verify your output.

C programming: Replacing if statements

Hello a beginner here who needs some of your help. My C program is good and does what it is supposed to do only that it is not supposed to use any kind of if statements. I wrote it that way as I saw it would be easier so that I can then replace the if statements. I have been trying to replace the if statements but am now stuck. What can I use instead of the if statement to still produce the same output.
The program is supposed to generate a sequence of thirty random integers between 0 and 9 and then print out the sequence both forward and backwards. Then print out a count of how many times each number between 0 and 9 appeared in the sequence.
This is the output
Here is a sequence of 30 random numbers between 0 and 9:
3 6 7 5 3 5 6 2 9 1 2 7 0 9 3 6 0 6 2 6 1 8 7 9 2 0 2 3 7 5
Printing them backwards, that's:
5 7 3 2 0 2 9 7 8 1 6 2 6 0 6 3 9 0 7 2 1 9 2 6 5 3 5 7 6 3
There were 3 0's
There were 2 1's
There were 5 2's
There were 4 3's
There were no 4's
There were 3 5's
There were 5 6's
There were 4 7's
There was only 1 8
There were 3 9's
This is my C program
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, array[30]={0}, count=0,check;
srand(time(NULL));
for(i=0;i<30;i++)
array[i]=rand()%10;
for(i=0;i<30;i++)
printf("%d ",array[i]);
printf("\n\n");
for(i=29;i>=0;i--)
printf("%d ",array[i]);
printf("\n\n");
for(i=0;i<30;i++){
check=array[i];
if(array[i]!=-1)
array[i]=-1;
if(check == -1)
continue;
count =1;
for(j=0;j<30;j++){
if((i==j) || (array[j]==-1))
continue;
if(check==array[j]){
count++;
array[j]=-1;
}
}
printf("There were %d %d's\n",count,check);
}
return 0;
}
You'll understand the algorithm from comments:
#include <stdio.h>
#include <stdlib.h>
//time.h is needed for time()
#include <time.h>
int main()
{
int i, array[30] = {0};
srand(time(NULL));
//generate and print 30 random numbers
for(i = 0; i < 30; i++){
array[i] = rand() % 10;
printf("%d ", array[i]);
}
puts("\n\n");
//print these numbers backwards
for(i = 29; i >= 0; i--)
printf("%d ",array[i]);
puts("\n\n");
// print out a count of how many times each number
// between 0 and 9 appeared in the sequence.
int count[10] = {0};
for(i = 0; i < 30; i++)
count[array[i]]++;
//output the count for each number
for(i = 0; i < 10; i++)
printf("There were %d %d's\n",count[i], i);
return 0;
}
Output:
9 2 3 9 8 4 3 8 1 3 6 4 3 2 5 3 2 3 0 1 9 0 3 5 1 3 3 8 2 0
0 2 8 3 3 1 5 3 0 9 1 0 3 2 3 5 2 3 4 6 3 1 8 3 4 8 9 3 2 9
There were 3 0's
There were 3 1's
There were 4 2's
There were 9 3's
There were 2 4's
There were 2 5's
There were 1 6's
There were 0 7's
There were 3 8's
There were 3 9's
The following is a simplification of your original source while removing the if statements. There are implied if statements in several places where a logical expression is used as part of a source code statement.
For instance for(j = 0; j < 30 && match >= 0; j++) has several logical expressions but no if appears in this statement. The logical expressions are j < 30 and match >= 0 and the complete expression of j < 30 && match >= 0.
This example uses a logical expression and the evaluation short circuit behavior of the C compiler (see Short-circuit evaluation in Wikipedia) in the statement array[j] == match && ++count && (array[j] = -1); so that if the logical expression array[j] == match evaluates to false then the rest of the statement will not be executed.
We also depend on the preincrement operator with the ++count to increment count and then take the resulting value to check if it is false (zero) or true (non-zero). Since the variable count is initialized to zero and when incremented will always be non-zero then the next logical expression in the statement is evaluated the (array[j] = -1). We put the assignment statement within parenthesis to enforce the order of evaluation. We want the variable array[j] to be assigned the value of -1 and for the result to then be used in the logical statement. Since this is the last logical expression of the entire logical statement, whether it evaluates to false (zero) or true (non-zero) doesn't matter as what we want is the side effect of assigning the value of -1 to the array element.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i, array[30] = {0};
srand(time(NULL));
for(i = 0; i < 30; i++)
array[i] = rand() % 10;
for(i = 0; i < 30; i++)
printf("%d ", array[i]);
printf("\n\n");
for(i = 29; i >= 0; i--)
printf("%d ",array[i]);
printf("\n\n");
for(i = 0; i < 30; i++){
int j;
int count = 0;
int match = array[i];
for(j = 0; j < 30 && match >= 0; j++){
array[j] == match && ++count && (array[j] = -1);
// replaces the following if as value of count is
// tested after it is incremented so will always be nonzero.
// if (array[j] == match) {
// count++; array[j] = -1;
// }
}
// if this is a valid array element value we are trying to match
// then print the count and the value being matched. printf()
// is a function that returns an int indicating number of character written.
match >= 0 && printf("There were %d %d's\n", count, match);
}
return 0;
}
An example output.
8 2 4 0 8 0 8 1 1 4 6 9 3 9 7 6 3 9 0 1 0 7 1 2 4 0 3 0 2 3
3 2 0 3 0 4 2 1 7 0 1 0 9 3 6 7 9 3 9 6 4 1 1 8 0 8 0 4 2 8
There were 3 8's
There were 3 2's
There were 3 4's
There were 6 0's
There were 4 1's
There were 2 6's
There were 3 9's
There were 4 3's
There were 2 7's

Resources