Velocity Reviews > C++ > DIAMOND SHAPE

# DIAMOND SHAPE

coinjo
Guest
Posts: n/a

 11-10-2005
I need to write a program which takes a number as an input and prints a
diamond of # and \$. The number of rows in the shape is equal to the
number entered by the user. Your program should display the shape for
both even and odd value of size. For example if user enters number 7
the program should print following shape.

#
#\$#
#\$#\$#
#\$#\$#\$#
#\$#\$#
#\$#
#

If user enters a value 6, the program prints diamond in following
shape.

#
#\$#
#\$#\$#
#\$#\$#
#\$#
#

I have tried very hard and this is the best i could come up with

#include<iostream>
using namespace std;

int main()
{

int rows=0;
cout<<"Enter the number of rows of the diamond"<<endl;
cin>>rows;

int space=0;
int space1=0;
int space2=0;
int space3=0;
int space4=1;
int a=0;
int b=0;

space1=rows/2;
space2=space1;
space3=space1;
a=rows-2;
space=space1+a;

int count=0;
int count1=0;
int count2=0;
int count3=0;
int count4=0;
int count5=0;
int count6=0;

int char1=1;
int char2=0;

b=a-1;

char2=space1+b;

while(count1<space1)
{

count2=0;
count3=0;

while(count2<space2)
{

cout<<" ";
count2=count2+1;

}

while(count3<char1)
{

cout<<"#";
count3=count3+1;

if(count3<char1)

{

cout<<"\$";
count3=count3+1;

}
}

cout<<endl;
count1=count1+1;
char1=char1+2;
space2=space2-1;

}

while(count<=space)
{
cout<<"#";
count=count+1;
if(count<space)
{
cout<<"\$";
count=count+1;
}
}

cout<<endl;

while(count4<=space3)
{

count5=0;
count6=0;

while(count5<space4)
{

cout<<" ";
count5=count5+1;

}

while(count6<char2)
{

cout<<"#";
count6=count6+1;

if(count6<char2)
{

cout<<"\$";
count6=count6+1;

}
}

space4=space4+1;
char2=char2-2;
count4=count4+1;
cout<<endl;
}
}

This above code works fine for 3 but not for other odd values like 5
and 7. Can anyone help?
Also how to make it work for even numbers?

coinjo
Guest
Posts: n/a

 11-10-2005
I need to write a program which takes a number as an input and prints a
diamond of # and \$. The number of rows in the shape is equal to the
number entered by the user. My program should display the shape for
both even and odd value of size. For example if user enters number 7
the program should print following shape.

#
#\$#
#\$#\$#
#\$#\$#\$#
#\$#\$#
#\$#
#

If user enters a value 6, the program prints diamond in following
shape.

#
#\$#
#\$#\$#
#\$#\$#
#\$#
#

I have tried very hard and this is the best i could come up with

#include<iostream>
using namespace std;

int main()
{

int rows=0;
cout<<"Enter the number of rows of the diamond"<<endl;
cin>>rows;

int space=0;
int space1=0;
int space2=0;
int space3=0;
int space4=1;
int a=0;
int b=0;

space1=rows/2;
space2=space1;
space3=space1;
a=rows-2;
space=space1+a;

int count=0;
int count1=0;
int count2=0;
int count3=0;
int count4=0;
int count5=0;
int count6=0;

int char1=1;
int char2=0;

b=a-1;

char2=space1+b;

while(count1<space1)
{

count2=0;
count3=0;

while(count2<space2)
{

cout<<" ";
count2=count2+1;

}

while(count3<char1)
{

cout<<"#";
count3=count3+1;

if(count3<char1)

{

cout<<"\$";
count3=count3+1;

}
}

cout<<endl;
count1=count1+1;
char1=char1+2;
space2=space2-1;

}

while(count<=space)
{
cout<<"#";
count=count+1;
if(count<space)
{
cout<<"\$";
count=count+1;

}
}

cout<<endl;

while(count4<=space3)
{

count5=0;
count6=0;

while(count5<space4)
{

cout<<" ";
count5=count5+1;

}

while(count6<char2)
{

cout<<"#";
count6=count6+1;

if(count6<char2)
{

cout<<"\$";
count6=count6+1;

}
}

space4=space4+1;
char2=char2-2;
count4=count4+1;
cout<<endl;

}
}

This above code works fine for 3 but not for other odd values like 5
and 7. Can anyone help?
Also how to make it work for even numbers?

coinjo
Guest
Posts: n/a

 11-10-2005
I need to write a program which takes a number as an input and prints a
diamond of # and \$. The number of rows in the shape is equal to the
number entered by the user. My program should display the shape for
both even and odd value of size. For example if user enters number 7
the program should print following shape.

#
#\$#
#\$#\$#
#\$#\$#\$#
#\$#\$#
#\$#
#

If user enters a value 6, the program prints diamond in following
shape.

#
#\$#
#\$#\$#
#\$#\$#
#\$#
#

I have tried very hard and this is the best i could come up with

#include<iostream>
using namespace std;

int main()
{

int rows=0;
cout<<"Enter the number of rows of the diamond"<<endl;
cin>>rows;

int space=0;
int space1=0;
int space2=0;
int space3=0;
int space4=1;
int a=0;
int b=0;

space1=rows/2;
space2=space1;
space3=space1;
a=rows-2;
space=space1+a;

int count=0;
int count1=0;
int count2=0;
int count3=0;
int count4=0;
int count5=0;
int count6=0;

int char1=1;
int char2=0;

b=a-1;

char2=space1+b;

while(count1<space1)
{

count2=0;
count3=0;

while(count2<space2)
{

cout<<" ";
count2=count2+1;

}

while(count3<char1)
{

cout<<"#";
count3=count3+1;

if(count3<char1)

{

cout<<"\$";
count3=count3+1;

}
}

cout<<endl;
count1=count1+1;
char1=char1+2;
space2=space2-1;

}

while(count<=space)
{
cout<<"#";
count=count+1;
if(count<space)
{
cout<<"\$";
count=count+1;

}
}

cout<<endl;

while(count4<=space3)
{

count5=0;
count6=0;

while(count5<space4)
{

cout<<" ";
count5=count5+1;

}

while(count6<char2)
{

cout<<"#";
count6=count6+1;

if(count6<char2)
{

cout<<"\$";
count6=count6+1;

}
}

space4=space4+1;
char2=char2-2;
count4=count4+1;
cout<<endl;

}
}

This above code works fine for 3 but not for other odd values like 5
and 7. Can anyone help?
Also how to make it work for even numbers?

Jim Kafka Ninte
Guest
Posts: n/a

 11-10-2005
On 10 Nov 2005 08:44:45 -0800, "coinjo" <(E-Mail Removed)> wrote:

>I need to write a program which takes a number as an input and prints a
>diamond of # and \$. The number of rows in the shape is equal to the

*snip*

>
>This above code works fine for 3 but not for other odd values like 5
>and 7. Can anyone help?
>Also how to make it work for even numbers?

I've been learning C++ for 3 days. This is what I came up with. I
would like for experienced programmers to critique my code so that I

#include <iostream>
#include [itex]
#include <vector>

// prints a row of diamonds
void PrintRow(const int numRows, const int lengthRow, bool
switchStartCharacter = false)
{
std::string rowCharacters = "#\$";

// figure out offset (to 'center' row)
int lineOffset = (numRows - lengthRow) / 2;

int currentCharacter = 0;

if( switchStartCharacter )
++ currentCharacter;

// shift by offset
for(int i = 0; i < lineOffset; i++)
std::cout << " ";

// print row
for(int i = 0; i < lengthRow; ++ i)
std::cout << rowCharacters[(currentCharacter
++)%2];

std::cout << std::endl;
}

int PrintDiamond(const int numRows)
{
// it doesn't make sense to have rows less than 1
if( numRows < 1 )
return -1;

// create a vector containing the number of entries
// for each row in half a diamond
std::vector<int> halfDiamond;

// store a variable reminding us if diamond is even
bool isEven = numRows % 2 == 0;

// calculate half the diamond
for(int currentRow = 1; currentRow <= ceil(numRows / 2.0f); ++
currentRow)
halfDiamond.push_back(currentRow*2 - 1);

// print out the top half of the diamond
for(int currentRow = 0; currentRow < halfDiamond.size(); ++
currentRow)
PrintRow(numRows, halfDiamond[currentRow]);

// if even, repeat the middle row
if( isEven )
PrintRow(numRows, halfDiamond[halfDiamond.size()-1],
isEven);

// print out the bottom half of the diamond
for(int currentRow = halfDiamond.size() - 2; currentRow >= 0;
-- currentRow)
PrintRow(numRows, halfDiamond[currentRow], isEven);

return 0;
}

int main()
{
int rowCount;

std::cout << "How many rows in the diamond?" << std::endl;
std::cin >> rowCount;
std::cout << std::endl;

// action
return PrintDiamond(rowCount);
}

W Marsh
Guest
Posts: n/a

 11-10-2005
On Thu, 10 Nov 2005 20:56:00 +0000, Jim Kafka Ninte <(E-Mail Removed)> wrote:

>On 10 Nov 2005 08:44:45 -0800, "coinjo" <(E-Mail Removed)> wrote:
>
>>I need to write a program which takes a number as an input and prints a
>>diamond of # and \$. The number of rows in the shape is equal to the

>
>*snip*
>
>>
>>This above code works fine for 3 but not for other odd values like 5
>>and 7. Can anyone help?
>>Also how to make it work for even numbers?

>
>I've been learning C++ for 3 days. This is what I came up with. I
>would like for experienced programmers to critique my code so that I

Here's that code again without choppy line lengths (sorry):

#include <iostream>
#include [itex]
#include <vector>

// prints a row of diamonds
void PrintRow(const int numRows, const int lengthRow, bool switchStartCharacter = false)
{
std::string rowCharacters = "#\$";

// figure out offset (to 'center' row)
int lineOffset = (numRows - lengthRow) / 2;

int currentCharacter = 0;

if( switchStartCharacter )
++ currentCharacter;

// shift by offset
for(int i = 0; i < lineOffset; i++)
std::cout << " ";

// print row
for(int i = 0; i < lengthRow; ++ i)
std::cout << rowCharacters[(currentCharacter ++)%2];

std::cout << std::endl;
}

int PrintDiamond(const int numRows)
{
// it doesn't make sense to have rows less than 1
if( numRows < 1 )
return -1;

// create a vector containing the number of entries
// for each row in half a diamond
std::vector<int> halfDiamond;

// store a variable reminding us if diamond is even
bool isEven = numRows % 2 == 0;

// calculate half the diamond
for(int currentRow = 1; currentRow <= ceil(numRows / 2.0f); ++ currentRow)
halfDiamond.push_back(currentRow*2 - 1);

// print out the top half of the diamond
for(int currentRow = 0; currentRow < halfDiamond.size(); ++ currentRow)
PrintRow(numRows, halfDiamond[currentRow]);

// if even, repeat the middle row
if( isEven )
PrintRow(numRows, halfDiamond[halfDiamond.size()-1], isEven);

// print out the bottom half of the diamond
for(int currentRow = halfDiamond.size() - 2; currentRow >= 0; -- currentRow)
PrintRow(numRows, halfDiamond[currentRow], isEven);

return 0;
}

int main()
{
int rowCount;

std::cout << "How many rows in the diamond?" << std::endl;
std::cin >> rowCount;
std::cout << std::endl;

// action
return PrintDiamond(rowCount);
}

Bob Hairgrove
Guest
Posts: n/a

 11-10-2005
On Thu, 10 Nov 2005 20:56:00 +0000, Jim Kafka Ninte <(E-Mail Removed)>
wrote:

>On 10 Nov 2005 08:44:45 -0800, "coinjo" <(E-Mail Removed)> wrote:
>
>>I need to write a program which takes a number as an input and prints a
>>diamond of # and \$. The number of rows in the shape is equal to the

>
>*snip*
>
>>
>>This above code works fine for 3 but not for other odd values like 5
>>and 7. Can anyone help?
>>Also how to make it work for even numbers?

>
>I've been learning C++ for 3 days. This is what I came up with. I
>would like for experienced programmers to critique my code so that I

I must say ... after only three days of learning C++, you have
presented us with a program that not only compiles cleanly, with only
1 warning, on Borland C++ Builder v. 5 ... and runs correctly! And
your comments are also just enough to be useful. And I like your
variable names which are self-documenting.

My hat is off to you, sir! Many who post uncompileable, untested, and
obfuscated code here (including myself, from time to time) can learn

Nevertheless, there are a few things worth considering, and I have
written my suggestions "inline":

>#include <iostream>
>#include [itex]
>#include <vector>

You don't have to #include [itex] for this ... works OK without it.

>// prints a row of diamonds
>void PrintRow(const int numRows, const int lengthRow, bool
>switchStartCharacter = false)

The "const" for the arguments, which you pass by value, have no effect
on the caller; they are only constant within the scope of PrintRow().
IOW, you cannot change the value passed by the caller anyway, so you
might want to drop the "const" qualifiers here. But some people like
to document the "constness" of the arguments within the function, so
it is really a matter of taste. It's not wrong, in any case.

Also, "numRows" and "lengthRow" should be unsigned IMHO because it
discourages users of PrintRow() from passing scurrilous negative
values. Besides, it would get rid of that nasty warning at line 50
<g>.

>{
> std::string rowCharacters = "#\$";
>
> // figure out offset (to 'center' row)
> int lineOffset = (numRows - lengthRow) / 2;
>
> int currentCharacter = 0;
>
> if( switchStartCharacter )
> ++ currentCharacter;
>
> // shift by offset
> for(int i = 0; i < lineOffset; i++)
> std::cout << " ";
>
> // print row
> for(int i = 0; i < lengthRow; ++ i)
> std::cout << rowCharacters[(currentCharacter
>++)%2];
>
> std::cout << std::endl;
>}
>
>int PrintDiamond(const int numRows)

Same comments regarding const and unsigned as above...

>{
> // it doesn't make sense to have rows less than 1
> if( numRows < 1 )
> return -1;

This is unnecessary if your argument "numRows" is unsigned ... you
might also (or instead of) want to check for a maximum value here.

You also return the value returned from PrintDiamond() in your main()
function. Now I know this is "air code", and as such we shouldn't try
to bust a gut trying to implement custom exception classes for
something like this, etc. ... but the "-1" has some problems.

First of all, your program should only return something other than 0
from main() if it hasn't run properly to completion (for whatever
reason ... out of memory error, etc.). Here, it would come merely as
the result of invalid user input. IMHO you should fail more gracefully
here and perhaps give the user a second chance. Of course, this
complicates the code a bit, because you would have to perform sanity
checking on the input (which you don't). Then again, this is only "air
code"...

Secondly, -1 is what most people would consider a "magic number". That
has nothing to do with the value -1, but with the fact that you have
hard-coded this number into your code without any documentation as to
what it means. Most programmers would provide a constant here which
would be defined in some other place, either as a static const
variable in your .cpp file, in a header file, or as an "extern"
variable. The name of the constant should indicate something about the
error condition here. Other potential errors would have different
values, e.g.:

static const int ERROR_INVALID_INPUT = -1;
// have to catch std::bad_alloc for this one:
static const int ERROR_OUT_OF_MEMORY = -2;

Thirdly, if your argument is unsigned, you needn't return anything at
all from this function. The exceptional case would be if the argument
passed were too big, in which case you would usually have two choices:

(a) substitute the value with some predetermined maximum, and perhaps
notify the caller with a message, and continue processing;
(b) throw a C++ exception which you could catch in main() by
surrounding the function call in a try{} block. In the catch{}
statement block, you could output an error message, log the error to
some other device or file, and (optionally) return some value from
main() != 0.

> // create a vector containing the number of entries
> // for each row in half a diamond
> std::vector<int> halfDiamond;
>
> // store a variable reminding us if diamond is even
> bool isEven = numRows % 2 == 0;

bool isEven = !(numRows % 2);

There is an implicit conversion from int to bool here, but that is OK
since bool is also an integral type in C++ ... You might consider
making this a stand-alone function if you see it being used a lot.

> // calculate half the diamond
> for(int currentRow = 1; currentRow <= ceil(numRows / 2.0f); ++
>currentRow)
> halfDiamond.push_back(currentRow*2 - 1);
>
> // print out the top half of the diamond
> for(int currentRow = 0; currentRow < halfDiamond.size(); ++
>currentRow)

Here is where the warning appears: you compare a signed type
(currentRow) with the return value from std::vector<int>::size(),
which returns an unsigned integral type (99% of the time it is
unsigned int, but it really depends on your implementation's
definition of std::vector::size_type).

> PrintRow(numRows, halfDiamond[currentRow]);
>
> // if even, repeat the middle row
> if( isEven )
> PrintRow(numRows, halfDiamond[halfDiamond.size()-1],
>isEven);
>
> // print out the bottom half of the diamond
> for(int currentRow = halfDiamond.size() - 2; currentRow >= 0;
>-- currentRow)
> PrintRow(numRows, halfDiamond[currentRow], isEven);
>
> return 0;
>}
>
>int main()
>{
> int rowCount;
>
> std::cout << "How many rows in the diamond?" << std::endl;
> std::cin >> rowCount;
> std::cout << std::endl;
>
> // action
> return PrintDiamond(rowCount);
>}

--
Bob Hairgrove
http://www.velocityreviews.com/forums/(E-Mail Removed)

coinjo
Guest
Posts: n/a

 11-11-2005
I am not allowed to use vectors in this program.

int2str@gmail.com
Guest
Posts: n/a

 11-11-2005

coinjo wrote:
> I am not allowed to use vectors in this program.

Don't wait for a complete piece of code you can hand in.

Neil etc. have given you more than enough help to restructure your code
and come up with a good algorithm. Use your brain now and don't wait
for a verbatum solution.

Report back with what you came up with.

Cheers,
Andre

Karl Heinz Buchegger
Guest
Posts: n/a

 11-11-2005
coinjo wrote:
>
> I am not allowed to use vectors in this program.

You don't need to.
If you look at Jim's code you will notice, that he used
that vector only to cache the individual lines.

Just do the calculations 2 times (in opposite order) and

--
Karl Heinz Buchegger
(E-Mail Removed)

gottlobfrege@gmail.com
Guest
Posts: n/a

 11-11-2005

Bob Hairgrove wrote:
> On Thu, 10 Nov 2005 20:56:00 +0000, Jim Kafka Ninte <(E-Mail Removed)>
> wrote:
>
>
> Also, "numRows" and "lengthRow" should be unsigned IMHO because it
> discourages users of PrintRow() from passing scurrilous negative
> values. Besides, it would get rid of that nasty warning at line 50
> <g>.
>
> --
> Bob Hairgrove
> (E-Mail Removed)

And since we are influencing a newbie here, or just to keep balance to
the force, or something like that, I'll speak for those wishing to
abolish unsigned numbers:

Basically, IMO, they should only be used for bit-flags, not for
numbers. Without starting a religious flamewar, let's just leave it by
noting exactly that - it is a bit of a religious arguement. If you (ie
the OP) have only been programming for 3 days, I suggest trying both
(and mostly doing whatever a supervisor or coding standard says,
if/when employed as a programmer) and then waiting until you have years
of experience before making a decision . It might come down to
which way gets you 'burnt' more. I've been burnt more by negative
numbers. I've yet to be burnt by numbers that are 'too big' (unless
they are negative turned to unsigned).

That for me is the essense of it - I don't know what 'too big' is. I
used to think images with dimensions greater than 16K or 32K were too
big, but they aren't any more. 'What is 'too big' today, won't be
tomorrow, and I want my code to last for years - I have 15 year old
code still in use today. For me, 'too big' is typically if the
allocation failed. If I had to test for 'too big' I'd test for as big
as possible without looking negative . Which means I should just
check for negative. Maybe it depends on what kind of code you are
writing - ie for me it is usually image processing code.

Ah, but I didn't mean to argue it. I see the value of unsigned: It
tries to express the 'reality' of what your code is modeling, which is
a good thing - for example, images can't have negative widths, so why
allow it (in the prototype) only to disallow it with a check? If
a warning, I would probably use unsigned properly. etc etc. Google the
groups for 'religion signed unsigned' or something like that to see the
arguments, or wait until you are old and cynical like us...

P.S. yeah, passing in 'const int x' to a function bugs me too, but
again, some have their reasons (i have yet to understand them, whereas
I find both sides of signed/unsigned easy to understand). If anything,
I could see 'const int & x', which also seems silly, but at least it is
consistent with 'const Foo & x', which is good practice if Foo is a
large object...

Tony