5

It's a bit tricky to explain the question, but suppose two alternating chars must be shown:

for(int n=0; n<20; n++)
{
    cout<<(n%2==0 ? 'X' : 'Y');
}

Is there a one-liner or more efficient way to accomplish the task above? (i.e. using something like <iomanip>'s setfill())?

ayane_m
  • 962
  • 2
  • 10
  • 26
  • I would just use `cout << "XYXYXYXYXYXYXYXYXYXY";`... –  Sep 21 '13 at 05:41
  • That won't be a viable option, as this is inside a function and "int n " can change to something else. It needs to be scalable. – ayane_m Sep 21 '13 at 05:42
  • In that case, just go with the loop. `cout` will have to loop through each character too, and there's no much you can do about I/O being slow anyway. If this code is the bottleneck in your application, then you have huge problems. If it isn't, then just don't worry about efficiency. –  Sep 21 '13 at 05:44
  • Well, yeah, this is the only inefficient code; it takes ~150-200 ms to execute (because of the loop) and there are lots of calls to this function. – ayane_m Sep 21 '13 at 05:46
  • @abckookooman interviewer puzzle? – Grijesh Chauhan Sep 21 '13 at 05:59

3 Answers3

7

I think I'd keep it simple:

static const char s[] ="XY";

for (int n=0; n<20; n++)
    std::cout << s[n&1];

The other obvious possibility would be to just write out two characters at a time:

for (int n=0; n<total_length/2; n++)
    std::cout << "XY";
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 2
    +1. A note for readers : `std::cout << "XY"[n&1];` would also work and the variable `s` is not really needed. – Nawaz Sep 21 '13 at 08:43
  • 2
    I doubt that this is "better" than OP's code. For instance, it's not entirely obvious to read. Better be explicit with the `?:` operator, the compiler will optimize it anyway. –  Sep 21 '13 at 17:35
  • 1
    @H2CO3: If that is not readable enough, then `s[n%2]` is another option, which means `?:` is still not needed. :P – Nawaz Sep 21 '13 at 17:39
  • 3
    @H2CO3: I think there's a minimum level of competence that should be expected of anybody who's going to write C++, and knowing how binary counting works is part of that -- so no, `n%2` is not better. – Jerry Coffin Sep 21 '13 at 19:06
  • @JerryCoffin "I think there's a minimum level of competence that should be expected of anybody who's going to write C++, and knowing how binary counting works is part of that" - absolutely. It does not mean that we should intentionally write obfuscated code, though. –  Sep 21 '13 at 19:18
  • 2
    @H2CO3 ...and this is not doing anything of the sort. – Jerry Coffin Sep 21 '13 at 19:52
6

If I work with strings and concise code matters a bit more than performance (like you have in Python), then I might write just this:

 static const std::string pattern = "XY";
 std::cout << pattern * n; //repeat pattern n times!

And to support this, I would add this functionality in my string library:

std::string operator * (std::string const & s, size_t n)
{
   std::string result;
   while(n--) result += s;
   return result;
}

One you have this functionality, you can use it elsewhere also:

std::cout << std::string("foo") * 100; //repeat "foo" 100 times!

And if you have user-defined string literal, say _s, then just write this:

std::cout << "foo"_s * 15;  //too concise!!

std::cout << "XY"_s * n;  //you can use this in your case!

Online demo.

Cool, isn't it?

Nawaz
  • 353,942
  • 115
  • 666
  • 851
2

If there is a reasonable upper limit for n, you could use:

static const std::string xy = "XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY";
cout << xy.substr( 0, n );

or, to be safe, you could add:

static std::string xy = "XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY";
while( xy.size() < n ) xy += "XYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXY";
cout << xy.substr( 0, n );

finally, consider cout.write( xy.c_str(), n ); if efficiency is most important for you to avoid the overhead of substr() copying of the result.

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180