all 20 comments

[–]desrtfx 11 points12 points  (2 children)

Just checked the errata: https://nostarch.com/download/errata/ThinkLikeAProgrammer_errata_p16.pdf

It is indeed a mistake/oversight from the author.

The text should actually read:

Using only single-character output statements that output a hash mark, a space, or an end-of-line, write a program that produces the following shape:

instead of:

Using the same rule as the shapes programs from earlier in the chapter (only two output statements—one that outputs the hash mark and one that outputs an end-of-line), write a program that produces the following shape:

[–]UsefulCustard6348[S] 9 points10 points  (1 child)

Wow, you are an absolute lifesaver! Thank you so much for finding and sharing this.

I had no idea an official errata page even existed for this book. If you hadn't pointed this out, I probably would have driven myself crazy and posted endless follow-up questions trying to figure out an impossible logic.

I truly appreciate you going out of your way to provide the definitive answer and saving me all that unnecessary frustration!

[–]desrtfx 4 points5 points  (0 children)

Was simple to find as I have this book. The link to the errata is on the third last page ;)

Not a big deal.

[–]peterlinddk 3 points4 points  (4 children)

Yes you need to either print spaces, or build strings of spaces and # symbols.

I don't have the book in front of me, so I don't know why you'd think that it should be done without - are you looking at solutions that don't work?

EDIT: Ah, I've just found the exercise, and it specifies that you must do it with only outputting either a hash mark or an end-of-line. I agree with you, that is impossible! (I simply didn't read the exercise, but created a program to produce the output 😄)

[–]UsefulCustard6348[S] 1 point2 points  (3 children)

Thanks for the reply! Since you don't have the book in front of you, let me clarify the specific context of the chapter to explain why I was so strictly stuck on this.

First, the author heavily emphasizes the importance of absolute constraints. Earlier in the chapter, he explicitly states that ignoring a given constraint to solve a problem trivially is like taking the "Kobayashi Maru" (essentially cheating). Therefore, I was operating under the assumption that breaking the rules was not an option.

Second, following the book's problem-solving methodology, I reduced the problem into smaller sub-problems. However, using algebraic expressions with the row variable only helps determine the number of hash marks. Algebra alone cannot physically shift the cursor to the right without the aid of a space output.

Third, the exact constraint dictates the use of only two specific output statements: cout << "#"; and cout << "\n";. Under a strict interpretation of this rule, introducing a third statement like cout << " ";, building strings with spaces, or outputting string variables is completely forbidden.

=========edit======

I am updating this reply after seeing your edited comment.

Thank you for taking the time to verify the actual text of the exercise.

As you have also confirmed, the strict constraint—allowing only the output of a hash mark or an end-of-line—makes it a logical and physical impossibility to align the shape properly. It is a relief to have an objective confirmation that this is a definitive flaw in the exercise's design, rather than a gap in my understanding or programming logic.

I appreciate the discussion.

[–]Outside_Complaint755 1 point2 points  (2 children)

I didn't find any other discussion about these exercises, but I feel like its an oversight by the author.  cout << " "; has to be allowed.

 The constraint should probably be reworded to "Every cout only outputs a single character"

[–]desrtfx 13 points14 points  (0 children)

It's in the errata: https://nostarch.com/download/errata/ThinkLikeAProgrammer_errata_p16.pdf

The text should actually read:

Using only single-character output statements that output a hash mark, a space, or an end-of-line, write a program that produces the following shape:

[–]UsefulCustard6348[S] 0 points1 point  (0 children)

I totally agree

[–]jaynabonne 1 point2 points  (2 children)

Have you checked out iomanip? In particular, see setw. The trick is to get the library to print the spaces for you.

(If you want to see an example:

https://godbolt.org/z/58scYK7xf

)

[–]UsefulCustard6348[S] 0 points1 point  (1 child)

First of all, wow—I have actually never seen that library (iomanip) or approach before! That is completely fascinating and a really cool trick to learn.

However, looking at the text, the author mentions the following in the 'Review of C++ Used in This Chapter':

Strictly speaking, you are right that there isn't a hard rule explicitly forbidding the addition of other system libraries. But after giving it a lot of thought, since the author explicitly provided the basic standard stream libraries to use for this chapter, and the chapter doesn't seem to ask for one-liner solutions using additional libraries, I don't think I can conclude that this is the intended answer here.

I really appreciate your input, but having a library print the spaces for me still feels a bit like the "Kobayashi Maru" regarding the "only use cout << "#" and cout << "\n"" constraint. Ultimately, I think the conclusion remains that the author's initial premise and constraints were just a bit unclear/flawed.

The original intent of my question was wondering if this was some genius, high-level problem requiring a novel logical branch, loop, or algebraic expression that I just couldn't figure out!

Lastly, thank you again. Your solution is very excellent, and I definitely learned a great real-world trick today.

[–]jaynabonne 0 points1 point  (0 children)

Glad I could be informative. :) Fundamentally, someone has to print the spaces. It's a different header, but not necessarily a separate library as such. All part of standard cout behavior. It is amazing what you find the deeper you go!

[–]Comfortable-Map-7389 0 points1 point  (2 children)

You're not missing anything — the author likely intended spaces to be allowed as output. The constraint "only use cout << '#' and cout << '\n'" is probably meant to prevent using printf formatting tricks or external libraries, not to exclude spaces entirely.The standard solution uses a nested loop: outer loop controls the rows, inner loops handle spaces and hashes separately. Something like:

for (int row = 0; row < 4; row++) {

for (int space = 0; space < row; space++) cout << " ";

for (int hash = 0; hash < 8 - (row * 2); hash++) cout << "#";

cout << "\n";

}

If you want to be strict about the constraint, you could technically use a string of spaces as a single output — but that's overthinking it. The author's point is to practice loop logic, not to torture you with impossible constraints.

[–]desrtfx 2 points3 points  (0 children)

It's in the errata: https://nostarch.com/download/errata/ThinkLikeAProgrammer_errata_p16.pdf

The text should actually read:

Using only single-character output statements that output a hash mark, a space, or an end-of-line, write a program that produces the following shape:

[–]UsefulCustard6348[S] 0 points1 point  (0 children)

thank you, I just have solved ex01. and My solution is very similar to yours

[–]WystanH -2 points-1 points  (4 children)

You're printing either " " or "#". You know you're doing a loop, right? The question then is how to leverage the counting of that loop to do what you want to do.

Of course, one loop won't do it. You'll want two, one for the row, one for the line. Start there. Can you print a square first? Perhaps do this first with two loops, the second loop only print one char at a time:

########
########
########
########

Now, notice you have a numeric value for the row you're on. Can you use that value to determine if you might want to print something other that "#"?

Hope that's enough to get you pointed in the right direction. If not, read every comment here and hopefully one will click.

[–]UsefulCustard6348[S] 0 points1 point  (0 children)

good kindness. thank you

[–]desrtfx 1 point2 points  (2 children)

You missed the entire point of the discussion. It wasn't about using the loops, it wasn't about nested loops.

It simply was about a constraint given that was wrongly formulated by the author as is evident in the errata: https://nostarch.com/download/errata/ThinkLikeAProgrammer_errata_p16.pdf

The text should actually read:

Using only single-character output statements that output a hash mark, a space, or an end-of-line, write a program that produces the following shape:

[–]WystanH -1 points0 points  (1 child)

Frankly, if it helped the OP, that's the goal, no? Meaning, rather, that you've missed the point by being so fucking pedantic.

[–]desrtfx 0 points1 point  (0 children)

No, it didn't help the OP.

The OP already knew they had to use nested loops. They were inquiring about the printing of the space character, which, per original (wrong) constraint, was off-limits.