Reputation: 13
The output is supposed to be in this fashion
I
IN
IND
INDI
INDIA
INDIA
INDI
IND
IN
I
I was wondering if there is anyway to make my program shorter.
Maybe use 2 while
loops or 2 for
loops instead of 4.
#include<iostream>
#include<conio.h>
using namespace std;
void main()
{
char a[]={'I','N','D','I','A'};
int r,c;
for(r=1;r<=5;r++)
{
for(c=0;c<r;c++)
cout<<a[c]<<" ";
cout<<endl;
}
for(r=5;r>=0;r--)
{
for(c=0;c<r;c++)
cout<<a[c]<<" ";
cout<<endl;
}
_getch();
}
Upvotes: 0
Views: 431
Reputation: 20523
The "cheating" ;-) but very short solution is
#include <cstdio>
int main() {
puts("I\nIN\nIND\nINDI\nINDIA\nINDIA\nINDI\nIND\nIN\nI\n");
}
Yet another solution based on TonyK's beautiful idea (works in C and C++):
#include <stdio.h>
int main() {
for (int i = 1; i < 11; ++i)
printf("%.*s\n", i < 6 ? i : 11 - i, "INDIA") ;
}
Update: (After TonyK's comment):
If you want spaces, then replace the printf
above with this
printf("%.*s\n", 2*(i < 6 ? i : 11 - i), "I N D I A ");
Update: A solution with no loop:
#include <stdio.h>
int main(int i, char**) {
return printf("%.*s\n", i < 6 ? i : 11 - i, "INDIA") - 1 && main(i + 1, 0);
}
Detailed explanations for the benefit of beginners follow.
The most important point is that this is an "academic" exercise. The code is obscure and one should refrain from writing serious code like this.
The standard doesn't fix a particular signature for the function main
. It only says that it must return an int
and the compiler must accept two particular forms:
int main();
int main(int argc, char** argv);
I'm using the second one. The more popular form int main(int argc, char* argv[])
is equivalent to (2). Indeed, in general, an array of T used as a function argument is implicitly converted to pointer to T. In this example, char* argv[]
is an array of pointer to char which becomes a pointer to pointer to char. The above program is not using the second parameter though (it's either ignored or given a NULL, i.e. 0 value).
Instead of doing a loop, the program calls main
recursivelly. Actually, this is illegal but the major compilers turn a blind eye to it (at most GCC gives a warning if you ask it to be pedantic with option -Wpedantic). When the program is called from the command line with no arguments the operating system calls main
passing 1
(which is 1
+ the number of arguments) and a pointer to pointer to char which, as said, is ignored by this program. Hence, i = 1
at the first call.
Subsequently, main
potentially calls itself incrementing i
each time. In summary, main
is sequentially called with i
being 1
, 2
, 3
, 4
, ...
It's easy to see that for this sequence of values for i
, the expression i < 6 ? i : 11 - i
evaluates to 1
, 2
, 3
, 4
, 5
, 5
, 4
, 3
, 2
, 1
, 0
, ... (This can also be expressed by 5.5 - abs(5.5 - i)
as per Drew Dorman's solution but using the ternary operator avoids the need to #include <cmath>
which saves a line ;-) These numbers are the quantity of characters of "INDIA" that should be displayed at each time.
The call printf("%.s\n", j, "INDIA")
, where j = i < 6 ? i : 11 - i
, displays the first j
characters of "INDIA" followed by a new line and returns the number of characters effectivelly printed (including the new line), i.e. j + 1
. Taking away 1
yields j
.
We recall now an important point of the semantics of a && b
, for integers a
and b
. If a == 0
, then b
is not evaluated. Otherwise, b
is evaluated. For us, a = printf("%.*s\n", j, "INDIA") - 1
(i.e. a = j
) and b = main(i + 1, 0)
.
Now, let's put these pieces together.
1. Initially, i = 1
and j = 1
. The call to printf
outputs "I\n" and returns 2
. Taking away 1
, gives a = 1 != 0
. Therefore, b = main(2, 0)
is evaluated (that is, main(2, 0)
is called).
2. Well, for this second call to main
, we have i = 2
, j = 2
, printf
displays "IN\n", a = 2 != 0
and b = main(3, 0)
is evaluated.
Repeating this argument, at each call to main
we have:
3. i = 3
, j = 3
, "IND\n" is printed, a = 3 != 0
and main(4, 0)
is called.
4. i = 4
, j = 4
, "INDI\n" is printed, a = 4 != 0
and main(5, 0)
is called.
5. i = 5
, j = 5
, "INDIA\n" is printed, a = 5 != 0
and main(6, 0)
is called.
6. i = 6
, j = 5
, "INDIA\n" is printed, a = 5 != 0
and main(7, 0)
is called.
7. i = 7
, j = 4
, "INDI\n" is printed, a = 4 != 0
and main(8, 0)
is called.
...
10. i = 10
, j = 1
, "I\n" is printed, a = 1 != 0
and main(11, 0)
is called.
11. i = 11
, j = 0
, "\n" is printed, a = 0
. Now main(12, 0)
is not exectued and the main
returns
Notice that main
in step 1 calls main
in step 2, which calls main
in step 3
, ... which calls main
in step 11. Therefore, main
in step 11 returns to main
in step 10, which returns to main
in step 9, ..., which returns to main
in step 1. Finally, main
in step 1 returns to the operating system.
If you are interested in even more obfuscated code, see present and past winners of the IOCCC. Enjoy!
Upvotes: 2
Reputation: 854
Another solution based on TonyK's answer. You can enter your desired string.
#include <stdio.h>
#include <string.h>
int main() {
char s[100];
gets(s);
for (int i = 0; i < strlen(s) * 2; i++)
printf ("%.*s\n", i < strlen(s) ? i + 1: 2 * strlen(s) - i, s);
}
Upvotes: 0
Reputation: 58271
You can do like this:
void main()
{
char a[]={'I','N','D','I','A'};
int r,c;
int x = 0; // initially x is 0
int l = 5;
for(r=1;r<= 11 ;r++) //loop runs for 5*2 + 1 times
{
if(r>=6){
x = l - r % 6; //set x to remaining length
l--;
}
for(c=0;c< (r % 6) + x; c++) // add x
cout<<a[c]<<" ";
cout<<endl;
}
}
and you can find it working here.
Upvotes: 0
Reputation: 3912
Here is an example using two loops:
#include<iostream>
using namespace std;
int main()
{
char a[]={'I','N','D','I','A'};
int arr_length=5;
bool two_times=false;//if you want to output INDIA twice
for(int i=2*arr_length-1; i>=1; i--)
{
for(int j=0; j<arr_length-abs(arr_length-i); j++)
{
cout << a[j];
}
if(i==arr_length && !two_times){ two_times=true; i++;}//if you want to output INDIA twice
cout << endl;
}
return 0;
}
Output:
I
IN
IND
INDI
INDIA
INDIA
INDI
IND
IN
I
Upvotes: 0
Reputation: 63775
Shorter.
#include <iostream>
#include <cmath>
int main()
{
char a[]={'I','N','D','I','A'};
for(int r=1;r<=10;r++)
{
int c = 5.5 - std::abs(5.5 - r);
std::cout << std::string(a, 0, c) << std::endl;
}
}
Upvotes: 1
Reputation: 17114
This is nice and short, if you have C++11:
#include <stdio.h>
#include <initializer_list>
int main() {
for (int i : {1,3,5,7,9,9,7,5,3,1})
printf ("%.*s\n", i, "I N D I A") ;
}
I put it on ideone at this link.
Upvotes: 10
Reputation: 1092
smth like this: Anyway, 2 loops is hard thing)
int i=1;
bool ind=0;
for(r=0;r<10;r++)
{
if (ind == 0){
for(c=0;c<i;c++)
cout<<a[c]<<" ";
i++; }
if (ind == 1){
for(c=0;c<i;c++) cout<<a[c]<<" ";
i--;
}
if (i % 5 == 0) ind=1;
cout<<endl;
}
Upvotes: 0
Reputation: 10840
You could use substr.
Additionally, if you want to add spaces between the characters (as it's in your code right now) you could do that once for the whole word and then work on that modified string:
input = "INDIA";
modifiedInput = ...; // Figure out a way to get "I N D I A " here
for (int i = 1; ...)
cout << substr(modifiedInput, 0, 2 * i) << endl;
...
Upvotes: 0