简体   繁体   中英

Any ways to make this shorter?

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();
}

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 .

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:

  1. int main();
  2. 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, ie 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 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 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), ie 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 (ie 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!

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;
    }
}

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;
...

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;
      }

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

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.

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);
}

http://ideone.com/Zsg5Lu

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM