DIAMOND SHAPE

C

coinjo

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?
 
C

coinjo

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?
 
C

coinjo

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?
 
J

Jim Kafka Ninte

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
can learn, please:

#include <iostream>
#include <math>
#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

W Marsh

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
can learn, please:

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

#include <iostream>
#include <math>
#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);
}
 
B

Bob Hairgrove

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
can learn, please:

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
from your example.

Nevertheless, there are a few things worth considering, and I have
written my suggestions "inline":
#include <iostream>
#include <math>
#include <vector>

You don't have to #include said:
// 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
{
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;

Shorter and, IMHO, more readable:

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

int2str

coinjo said:
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
 
K

Karl Heinz Buchegger

coinjo said:
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
your diamond should be perfect.
 
G

gottlobfrege

Bob said:
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>.

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
compilers made implicit signed/unsigned conversions an error instead of
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
 
B

Bob Hairgrove

That for me is the essense of it - I don't know what 'too big' is.

In the case we have here of printing out a diamond on the console
screen, I would say that any number larger than the width of the
screen in characters is probably too big.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top