I am working on this problem from the CS50 class. I am still a beginner. What I need to program is this:
Toward the end of World 1-1 in Nintendo’s Super Mario Brothers, Mario
must ascend right-aligned pyramid of blocks, a la the below.
screenshot of Mario jumping up a right-aligned pyramid
Let’s recreate that pyramid in C, albeit in text, using hashes (#) for
bricks, a la the below. Each hash is a bit taller than it is wide, so
the pyramid itself is also be taller than it is wide.
#
##
###
####
#####
######
#######
########
The program we’ll write will be called mario. And let’s allow the user
to decide just how tall the pyramid should be by first prompting them
for a positive integer between, say, 1 and 8, inclusive.
However I have tried many ways, two of which are these:
code mariov1
After looking at some Stack Overflow attempts, it now looks like this:
#include <cs50.h>
#include <stdio.h>
string hash(int);
int main(void)
{
int n;
do
{
n = get_int("Height: ");
}
while (n < 0 || n > 8);
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n-1-i; j++)
{
for(int j = 0; j < i+1; j++)
{
printf(".");
}
printf("#");
}
printf("\n");
}
}
What can I try next?
Suriyu, to add to what Weather Vane said. To pass it through Check50, you'll still need to make small tweaks to the code so that it passes through all CS50 tests.
For the do-while loop, n <=0 instead of n < 0 to ask for an input when n = 0, because the specification demands a minimum of one brick (1 to 8 both inclusive).
You need only the two loops, don't print extra characters not specified in the problem set, ex: printf(".");
All the best with CS50, it's going to be a fun experience!
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int n;
do
{
n = get_int("Height: ");
}
while (n < 1 || n > 8);
// this for loop makes new lines
for (int i = 0; i < n; i++)
{
// here I have two for loops nested inside the above for loop,
// I previously made the mistake of having two inner loops nested.
// this 2nd for loop prints n-1-i spaces
// because if n=5, then in the 4th row, there will be 5-1-3 spaces/dots
for (int j = 0; j < n - 1 - i; j++)
{
printf(" ");
}
// this 3rd for loop prints i+1 hashes
// because if n=5, then in the 4th row, there will be 3+1 hashes.
// (3 because you count from 0)
for (int j = 0; j < i + 1; j++)
{
printf("#");
}
printf("\n");
}
}
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int n;
do
{
n = get_int("Height of the pyramid is:\n");
}
while (n < 1 || n > 8); //condition to get a number from 1-8 from the user
for (int i = 0; i < n; i++) //loop for height
{
for (int j = 0; j < n - 1 - i; j++) //loop for spaces on left pyramid
{
printf(" ");
}
for (int k = 0; k < i + 1; k++) // loop for hashes on left pyramid
{
printf("#");
}
printf(" "); // spacing between pyramids
for (int p = 0; p <= i; p++) //loop for right pyramid
{
printf("#");
}
printf("\n");
}
}
This is the advanced version of the problem if you decide to try it.
Here's a different approach. Instead of iteratively printing blanks, followed by iteratively printing number signs, this version creates a buffer (size defined by a precompiler constant - currently set to 8, change it if you want to allow bigger pyramids), then for each row in the pyramid it first fills the buffer with number signs, then overlays the beginning of the line with the proper number of spaces, and then prints it:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#define MAXSIZE 8
int main(void)
{
int size, spaces;
char buf[MAXSIZE+1];
do
size = get_int("Height: ");
while (size < 0 || size > MAXSIZE);
buf[size] = '\0';
for(spaces = size-1 ; spaces >= 0 ; --spaces)
printf("%s\n", (char *)memset(memset(buf, '#', size), ' ', spaces));
}
EDIT
And here's yet another approach which builds the entire output block in an array in memory and then prints it using a single call to puts:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#define MAXSIZE 8
#define TOTSIZE ((MAXSIZE+1) * MAXSIZE)
int main(void)
{
int size, spaces;
char buf[TOTSIZE+1];
do
size = get_int("Height: ");
while (size < 0 || size > MAXSIZE);
memset(buf, '\n', (size+1)*size);
buf[((size+1)*size)] = '\0';
for(char *p = buf, spaces = size-1 ; *p != '\0' ; p += size+1, --spaces)
memset(memset(p, '#', size), ' ', spaces);
puts(buf);
}
This is an option that likely works best:
from cs50 import get_int
while True:
n=get_int("Enter Height: ")
if n>=1 and n<=8:
break
for i in range(0, n-1):
print(" " * (n - (i+1)) + "#" * (i+1))
Related
in the cs50 project, we have to make a Mario hash pyramid then right align it to the left and I'm having a pretty hard time doing it and I hope someone could give me some advice
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int h = 0;
int l = 0;
int c = 0;
do {
h = get_int("Height: ");
} while (h > 8 || h < 1);
{
for (int w = 0; w < h; w++)
{
for (int j = -1; j < w; j++)
{
printf("#");
}
printf("\n");
}
}
}
output:
what is needed:
try to make two-loop one for the empty space you can also use - and second for #..
after the align become to left del the -
Before checking the code that I'll provide, I strongly advise you to do hard coding for every single line of pyramide. This is the only way you will see and understand the design pattern of the following algorithm. Then, feel free to check the following code snippet.
Here is the code that builds pyramid right-aligned.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int height = 0;
do
{
height = get_int("Please enter a height between 1 and 8 (inclusive)\nHeight: ");
}
while (height > 8 || height < 1);
for(int i = 0; i < height; i++)
{
for(int j = height - i; j > 1; j--)
{
printf(" "); // print empty spaces.
}
for(int k = 0; k <= i; k++)
{
printf("#"); // print hashes.
}
printf("\n"); // go to next line.
}
}
I wanted to print a rhombus shape with only 1 loop. The furthest I have gone is using 2 for loops.
The result shape is as follows:
rhombus shape
*
* *
* *
* *
* *
* *
* *
* *
*
The code for using 3 loops is as follows:
#include <iostream>
int main() {
int i, j;
int columns = 4;
for(i = 0; i < columns; i++){
for(j = 0; j <= (columns-1) - i;j++){
printf(" ");
}
for(j = 0;j<=2*i;j++){
if(i == 0||j == 0||j == 2*i){
printf("*");
}else{
printf(" ");
}
}
printf("\n");
}
for(i = columns; i >= 0; i--){
for(j = 0; j <= (columns-1) - i;j++){
printf(" ");
}
for(j = 0;j<=2*i;j++){
if(i == 0||j == 0||j == 2*i){
printf("*");
}else{
printf(" ");
}
}
printf("\n");
}
}
My code is as follows:
int main() {
int i, j;
int columns = 4;
for(i = 0; i < columns; i++){
for(j = 0;j<=(2*i+(columns) - i);j++){
if(j==columns/2+(columns/2-i)||(j == (2*i+(columns) - i))){
printf("*");
}else{
printf(" ");
}
}
printf("\n");
}
for(i = columns; i >=0; i--){
for(j = 0;j<=(2*i+(columns) - i);j++){
if(j==columns/2+(columns/2-i)||(j == (2*i+(columns) - i))){
printf("*");
}else{
printf(" ");
}
}
printf("\n");
}
}
I have the following questions:
Does less loop in rhombus shape printing always faster than using more loops?
Is there a way to print rhombus shape using 1 loop? Without using predefined functions like string().
Sorry for my English, looking forward to hearing from you guys.
Let's address the questions in order...
Does less loop in rhombus shape printing always faster than using more loops?
Firstly, you should not be concerned about speed in a program like this. Except maybe if you are trying to print a HUGE rhombus or this is intended to run on a small battery-operated embedded device requiring low power consumption.
I don't think you're doing any of these.
The answer really is no: both your approaches are doing roughly the same amount of looping. They're not very efficient, because they are calling a fairly expensive function once for each character output.
More importantly, the code is overly complicated, unclear and difficult to read. You should be focusing here, instead of worrying about trivial performance considerations.
Is there a way to print rhombus shape using 1 loop? Without using predefined functions like string().
Yes, I posted an example in the comments where you can just use a specifier in the printf call to output some amount of padding. Internally, that does basically the same thing as your own loops, but it makes shorter, clearer code and fewer printf calls.
Here, you just work out how many spaces are required before the * and then how many after it. You can then ask printf to output the string "*" padded with some number of spaces. Use %*s to indicate there are two parameters: the total width of the string, and the string itself. The width will be the number of spaces you want, plus 1 for the actual string.
#include <stdio.h>
#include <math.h>
int main(void)
{
const int N = 4;
for (int i = 0; i <= N*2; i++)
{
int space_before = abs(N - i);
int space_after = 2 * (N - space_before ) - 1;
if (space_after > 0)
printf("%*s%*s\n", space_before + 1, "*", space_after + 1, "*");
else
printf("%*s\n", space_before + 1, "*");
}
return 0;
}
Now, this is easier to understand, but it's still a bit clunky. How about we move it into a function, and then get rid of the branching in the loop. All the loop iterations output two stars except the first and last ones which are simpler. So, here:
#include <stdio.h>
#include <math.h>
void display_rhombus(int size)
{
if (size > 0)
{
printf("%*s\n", size + 1, "*");
for (int i = 1; i < size*2; i++)
{
int space_before = abs(size - i);
int space_after = 2 * (size - space_before ) - 1;
printf("%*s%*s\n", space_before + 1, "*", space_after + 1, "*");
}
}
printf("%*s\n", size + 1, "*");
}
int main(void)
{
display_rhombus(4);
return 0;
}
Now, you have a function with a name that describes what it does, has simple-to-understand code, and is re-usable. You can call it many times to draw whatever sizes of rhombus you want.
int main(void)
{
for (int size = 0; size < 10; size++)
{
display_rhombus(size);
}
return 0;
}
Finally, I should also mention that it's possible to output a rhombus with no loops, using a technique called recursion. I will leave that as a learning exercise for you.
Well, apart from paddy's excellent answer, here's another one:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
void printStar(int size) {
int j = size / 2;
int i = size % 2 == 0 ? j - 1 : j;
bool flag = false;
while (i <= j) {
std::vector<char> vec(size, ' ');
vec.at(i) = '*';
vec.at(j) = '*';
std::copy(vec.begin(), vec.end(), std::ostream_iterator<char> {std::cout});
std::cout << "\n";
if (!flag) {
i--;
j++;
}
else {
i++;
j--;
}
if (i == -1) {
flag = true;
i += 2;
j -= 2;
}
}
}
int main() {
printStar(5);
return 0;
}
I thought long and hard before asking this in here but I've spent too much time now trying to figure this one out without cheating.
The CS50 mario ps1 (less comfortable) asks for a *simple left align (at first) pyramid, but my code is giving me it upside down and I can't figure why.
#include <cs50.h>
#include <stdio.h>
int main (void)
{
int n;
do
{
n = get_int("Pyramid Height: ");
}
while (n < 1 || n > 8);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - i ; j++)
printf("#");
for (int j = 0; j < n - i; j++)
{
printf(" ");
}
printf("\n");
}
}
I'm sorry if this type of questioning shows up regularly here but I really do need your help.
Thanks in advance.
edit:
expected result:
........#
.......##
......###
.....####
....#####
...######
..#######
.########
I can change the dots to spaces afterwards, this is just for visualisation;
the restriction for height is 8, so I guess that each line has always eight characters;
I actually added trailing spaces so that the pyramid could be right aligned, I've metioned wrong before;
I'm going to check the How to debug small programs?;
Sorry, I'm new to this, I didn't know there was a difference between here and stack exchange, gonna look into that.
*Sorry for the "meh" english, it is not my native language.
See what is the difference between my and your code (especially how to count):
void draw(int n, int align, int dir)
{
for (int i = 1; i <= n; i++)
{
if(align)
{
for(int s = 0; s < (dir ? (n - i) : i - 1); s++)
{
printf(" ");
}
}
for (int j = 0; j < (dir ? i : (n - i + 1)) ; j++)
{
printf("#");
}
printf("\n");
}
}
int main (void)
{
draw(8,1,0);
printf("\n");
draw(8,1,1);
printf("\n");
draw(8,0,0);
printf("\n");
draw(8,0,1);
}
https://godbolt.org/z/7YT16j
my code is giving me it upside down and I can't figure why
Let's see what the code looks like
// There's a loop executed n times. The body prints a line, so n lines are printed.
// In case you have doubts, the characters are normally printed top to bottom and
// left to right.
for (int i = 0; i < n; i++)
{
// The following loop prints (n - i) characters '#' at the beginning
// of each line. That's NOT what you are supposed to do, kind the opposite.
for (int j = 0; j < n - i ; j++)
printf("#");
// You should first print the spaces, then the '#'s, starting from 1 '#' at
// the first line and increasing the number by one at each line (so you have
// to change the condition in the loop accordingly).
// This loop prints the right amount of spaces, but only after
// all the '#'s and just before the end of the line, so that you just
// can't see them (change the printed char to '.' to visualize those).
for (int j = 0; j < n - i; j++)
{
printf(" ");
}
// Note that you could use putchar('\n'), here and previously, to print
// only one char, instead of using printf() to print string literals.
printf("\n");
}
When I print out a pyramid, the last line of the pyramid or the base prints out an integer which represents how many hashes, instead of a string of hashes.
like such:
Height: 3
#
##
3
when its supposed to be:
Height 3:
#
##
###
I'm supposed to print out a pyramid with a height based on the user's input, but instead of the base being printed out as a string it prints out an integer of how many hashes there should be for the base. I understand that this is because I'm returning n but I don't know how to go about it in a way where it still returns the loop.
I've tried changing the class to void instead of int, but that throws an error as it's conflicting types. I'm thinking I should print out an empty string but it messes with my bounds.
#include <cs50.h>
#include <stdio.h>
int get_height(string prompt);
int main(void)
{
int ask = get_height("Height: ");
printf("%i\n", ask);
}
int get_height(string prompt) {
int n;
do {
n = get_int("%s", prompt);
}
while (n < 1 || n > 8);
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
printf("#");
}
printf("\n");
}
return n;
}
The last line of output is the height because that is the last thing printed in your main function:
printf("%i\n", ask);
get_height will actually only print n-1 lines because the first iteration (i=0,j=0) is skipped.
the 3 should be output
The problem is this statement;
for (int j = 0; j < i; j++) {
which stops too early. Suggest:
for (int j = i; j >=0; j--) {
The output after making the above change:
#
##
###
3
I was working though some beginning problem sets with Harvard's online CS50 class. I got the problem to work correctly but I was wondering if there would possibly be a cleaner or better way to get the program to work.
The goal of the program is to print a right-aligned pyramid comprised of hash-tags and space characters. Any guidance in regards to style or tricks would be very welcome.
/* Creating the mario program, whose goal is to create a
* pyramid by accepting input from the user to get the
* height then aligning the pyrimid to the right.
*
*/
#include <stdio.h>
#include <cs50.h>
int main(void)
{
// get user input and set to variable
printf("Height: ");
int height = GetInt();
int i, j, k;
for(i = 1 ; i < height; i++)
{
// create n-1 spaces
for(k = (height - 2); k > (i-1); k--)
{
printf("%c", ' ');
}
// create n+1 hash tags
for(j = 0; j < (i+1); j++)
{
printf("#");
}
printf("\n");
}
return 0;
}
I'm assuming by cleaner you mean "spiffy and fancyer".
This looks spiffy to me:
#include <stdio.h>
#include <cs50.h>
int main(void) {
// get user input and set to variable
printf("Height: ");
int height = GetInt();
int hm2 = height - 2;
int j, k;
for(int i = 1 ; i < height; i++) {
// create n-1 spaces
for(k = hm2; k > (i-1); k--)
printf("%c", ' ');
// create n+1 hash tags
for(j = 0; j < (i+1); j++)
printf("#");
printf("\n");
}
return 0;
}
However, don't get too caught up in making your code fancy. Although it's nice if you're working with others, or yourself really. Your example looked fine.
Now, optimization-wise, that's something to worry about. Just remember that too much optimization can potentially break your program.
For everyone's consideration: this is what "all style and no readability" looks like :)
i = 0;
while (i++ < height*height)
printf ("%c%s", (i-1)/height < height-(i-1)%height-1 ? ' ' : '#',
i % height ? "" : "\n");
It is nigh on impossible to see what the code does without running it. If there is to be a follow-up exercise, this is hard to re-write to form, say, an even-sided pyramid. I'd probably throw this away and start again with the basics, before concatenating it again into a little monster such as this.
(later) Ever so slightly more neat to put the i++ at the end, so two times (i-1) gets traded for a slightly more complicated end-of-line test:
i = 0;
do
printf ("%c%s", i/height < height-i%height-1 ? ' ' : '#',
i % height==height-1 ? "\n" : "");
while (++i < height*height);
I think by cleaner and better way you mean to be a perfect shaped right angled triangle pyramid.
For this you should do as
Change
printf("Height: ");
to
printf("Height: \n\n");
and
for(i = 1 ; i < height; i++)
to
for(i = 0 ; i < height; i++)
And see the sample output.
Here's a suggestion:
#include <stdio.h>
#include <cs50.h>
int main(void) {
//initialize variables
int height, hm2, j, k, i;
printf("Height: \n");
// Get user input
height = GetInt();
hm2 = height - 1;
for(i = 0; i < height; i++) {
// create n spaces
for(k = hm2; k > i; k--)
printf("%c", ' ');
// create n+1 hash tags
for(j = 0; j < i+1; j++)
printf("#");
printf("\n");
}
return 0;
}
Result if the user entered a 5 for the height:
Height:
#
##
###
####
#####
A couple things I considered with this version of the code:
-In C, it's good practice to declare all variables separately from giving them a value and assign values later. Some compilers may bring up this error if you to declare and assign a value in a for loop: "error: ‘for’ loop initial declarations are only allowed in C99 mode". These changes are considered with what I have provided.
//initialize variables
int height, hm2, j, k, i;
-I added a newline here
printf("Height: \n");
-Instead of hm2 = height - 2 I changed it to:
hm2 = height - 1;
-First loop, now we give i a value and set it to 0 to meet the other changes that were made:
for(i = 0; i < height; i++) {
-For the loop creating n spaces I changed it to:
for(k = hm2; k > i; k--)
-Finally removed parenthesis (no need in this case) in last for loop:
for(j = 0; j < i+1; j++)
Cheers