Print repeating diamond shapes with custom rows, columns and length - c

I am new to C, and I am trying to print diamond shapes according to the rows(2~10), columns(2~10) and the length(3, 5, 7, 9) of the diamond input from the user.
Using the code below I can print diamond and number of diamonds correctly, but I just can't get the correct distance between them.
void printDiamondWith(int diamondlength, int numberOfDiamonds) {
int i, j, k;
int star, space;
star = 1;
space = diamondlength;
for (i = 1; i < diamondlength * 2 - 1; i++) {
for (k = 0; k < numberOfDiamonds; k++) {
for (j = 0; j < space; j++) {
printf(" "); // Print the distance for the previous star
}
for (j = 1; j < star * 2; j++) {
printf("*");
}
for (j = 0; j < space; j++) {
printf(" "); // Print the distance for the next star
}
}
printf("\n");
// Check if length is equal 3, else length -1 to get the correct rows of second half of the diamond
if (diamondlength == 3) {
// Loops until the first half of the diamond is finished, then reverse the process to print the second half
if(i < (diamondlength - diamondlength / 3)) {
space--;
star++;
} else {
space++;
star--;
}
} else if (diamondlength >= 3) {
if (i < (diamondlength - 1 - diamondlength / 3)) {
space--;
star++;
} else {
space++;
star--;
}
}
}
}
Actual running result:
Expected result:

Your formulas for calculating the space is off. It works for me when I change this
space = diamondlength;
to this
space = diamondlength/2+1;
And this
for (k = 0; k < numberOfDiamonds; k++) {
for (j = 0; j < space; j++) {
to this:
for (k = 0; k < numberOfDiamonds; k++) {
for (j = 0; j < space-1; j++) {
In such situations I recommend hardcoding the variable for different parameters and write down what the variable has to be for what parameter so you can try to find a function that maps the parameter to the value. For instance I saw that as diamondlength increased, the space error also increased, so the relation between parameter and variable can't be one to one.

Related

How do I properly nest these loops in C?

I need to make a program that prints this:
.......#
......##
.....###
....####
...#####
..######
.#######
########
Basically, if the n is 8. it will print 7 dots and 1 hash***. then in the next row it will print 7 dots and 2 hashes, then 6 dots and 3 hashes until there are 0 dots and 8 hashes.
So far my code looks like this:
int main(void)
{
int G = 1;
int n = 8;
int m = 0;
int k = 0;
int Z = 1;
for (m = n; m > 0; m --)
{
for (k = n - 1; k >= Z; k --)
{
printf(".");
}
printf("\n");
Z = Z + 1;
}
for (int i = 0; i < n; i ++)
{
for (int j = 0; j < G; j++)
{
printf("#");
}
printf("\n");
G = G + 1;
}
}
But the result of this comes out as this:
.......
......
.....
....
...
..
.
#
##
###
####
#####
######
#######
########
Since this is obviously homework or some self studies, I'll write how you need to think here.
The first problem is to be able to print ONE row given total number of rows and current row.
So let's start with total number or rows. I will use more descriptive variable names, which you also should.
int total = 8;
Now we need to print one row, given the current row. Let's assume that the first row has number 1. Let's start with the dots.
for(int i=0; i<(total-row); i++)
printf(".");
Then we continue with the hashes:
for(int i=0; i<row; i++)
printf("#");
And now we just need to do this total times and add a newline after each:
for(int row=1; row<total; row++) {
for(int i=0; i<(total-row); i++)
printf(".");
for(int i=0; i<row; i++)
printf("#");
printf("\n");
}
Please note that it is very common with obo (off by one) errors when doing things like this. We could let 0 be the first row instead of one, but then we need to change a few other things. You said you wanted 1 hash and 7 dots on first line and 8 hash and 0 dots on last line, which seems a bit odd, but just change row<total to row<total+1 and you get that.
You'll rather want something that does the printing from within the same loop. Here's some pseudo code of a simple way to write this algorithm:
for(int dots=n-1; dots>DOTS_MIN; dots--)
{
for(int i=0; i < dots; i++)
print dot
for(int i=dots; i < n; i++)
print hash
printf("\n");
}
First, start from naming, it's a challenging task to find out what Z stands for.
So we have
int totalRows = 4;
int totalColumns = 8;
and we should print out totalRows of rows:
for (int row = 1; row <= totalRows; ++row) {
}
from 2nd row on we should add a new line:
for (int row = 1; row <= totalRows; ++row) {
/* Start a new line from the 2nd row on */
if (row > 1)
printf("\n");
}
Time to print dots, we have totalColumns - row of them:
for (int i = 1; i <= totalColumns - row; ++i)
printf(".");
Followed by row # symbols:
for (int i = 1; i <= row; ++i)
printf("#");
Combining these chunks all together:
int main() {
int totalRows = 4;
int totalColumns = 8;
for (int row = 1; row <= totalRows; ++row) {
/* Start a new line from the 2nd row on */
if (row > 1)
printf("\n");
/* Printing dots */
for (int i = 1; i <= totalColumns - row; ++i)
printf(".");
/* Printing # */
for (int i = 1; i <= row; ++i)
printf("#");
}
return 0;
}

Continue computation in do while even if no columns exist

What I am trying to do (not very successful) is if my code detects a signal (if(matrix[i][j] ==1)) coming (1 or 0) for the next few steps I want my code to write in a new matrix: newmatrix[i][j]=10 and if not to continue with 0. Here is my code so far:
for (i = 0; i < rows; i++) {
j = 0;
do {
if (matrix[i][j] == 1) {
int m = j;
while (j < m + 3) {
newmatrix[i][j] = 10;
printf("newmatrix[%i][%i] and %f\n", i, j, newmatrix[i][j]);
j++;
continue;
}
}
if (matrix[i][j] == 0) {
newmatrix[i][j] = 0;
printf("newmatrix[%i][%i] and 0 is %f\n", i, j, newmatrix[i][j]);
j++;
continue;
}
j++;
} while (j < MAXTIME);
}
}
The problem is that if there is a signal near the end instead of stopping when to column count reaches the max number the code inserts new columns even though they are only 10:
Where is my mistake can someone point me to the right direction? Is there maybe a way to do this cleaner with goto statement?
Here is a simpler approach with a temporary variable:
for (i = 0; i < rows; i++) {
int spike = 0;
for (j = 0; j < MAXTIME; j++) {
if (matrix[i][j] == 1) {
spike = 3;
}
if (spike) {
newmatrix[i][j] = 10;
spike--;
} else {
newmatrix[i][j] = 0;
}
printf("newmatrix[%i][%i] is %f\n", i, j, newmatrix[i][j]);
}
}
Notes:
I am assuming that matrix[i][j] is either 0 or 1. If other values are possible and newmatrix[i][j] should stay unmodified for these cells, the code should be modified.
It is advisable to only modify a loop index in the for update clause. do / while loops are notoriously error prone, especially with nested loops that also modify the loop index as is the case in your code.

8 Queens puzzle with recursive deep search

I'm trying to solve the 8 queens puzzle problem in C. I'm having problems with the recursive search. The program is supposed to start at a given column:
execute(tabuleiro,8,0);
Where the 8 is the number of columns in the board, and 0 is the start column.
This works when I start at column 0. When I send any other column number to the recursive search, the program just counts to the last column. For example, if I choose to start the search from the number 5 column, the code search from the column 5 to 7, after this it should search from 0 to 4, but it doesn't do that.
If I do this:
execute(tabuleiro,8,3);
It fills in only the last 5 colummns, and does not return to column 0 to finish the solution:
Also, how can I select the initial position for the queen in this code? Like I said before, the column is assigned in the code, but I'm not sure how to pick the correct column.
The code has 3 functions: one is to display the board, a second to check if the move is legal (so one queen doesn't attack the other), and the last one to place one queen and recur for the remainder of the board.
#include <stdlib.h>
#include <windows.h>
int sol = 0;
void viewtab(int tab[][8], int N)
{
int i,j;
for( i = 0; i < N; i++)
{
for( j = 0; j < N; j++)
{
if(tab[i][j] == 1)
printf("R\t");
else
printf("-\t");
}
printf("\n\n");
}
printf("\n\n");
system("pause");
printf("\n");
}
int secury(int tab[][8], int N, int lin, int col)
{
// this function is to check if the move is secury
int i, j;
// attack in line
for(i = 0; i < N; i++)
{
if(tab[lin][i] == 1)
return 0;
}
//attack in colune
for(i = 0; i < N; i++)
{
if(tab[i][col] == 1)
return 0;
}
// attack in main diagonal
//
for(i = lin, j = col; i >= 0 && j >= 0; i--, j--)
{
if(tab[i][j] == 1)
return 0;
}
for(i = lin, j = col; i < N && j < N; i++, j++)
{
if(tab[i][j] == 1)
return 0;
}
// attack in main secondary
for(i = lin, j = col; i >= 0 && j < N; i--, j++)
{
if(tab[i][j] == 1)
return 0;
}
for(i = lin, j = col; i < N && j >= 0; i++, j--)
{
if(tab[i][j] == 1)
return 0;
}
// if arrive here the move is secury and return true
return 1;
}
void execute(int tab[][8], int N, int col)
{
int i;
if(col == N)
{
printf("Solution %d ::\n\n", sol + 1);
viewtab(tab, N);
sol++;
return;
}
for( i = 0; i < N; i++)
{
// check if is secury to put the queen at that colune
if(secury(tab, N, i, col))
{
// insert the queen (with 1)
tab[i][col] = 1;
// call recursive
execute(tab, N, col + 1);
// remove queen (backtracking)
tab[i][col] = 0;
}
}
}
int main()
{
int i, j, tabuleiro[8][8];
for (i = 0; i < 8; i = i + 1)
for (j = 0; j < 8; j = j + 1) tabuleiro[i][j] = 0;
execute(tabuleiro,8,0);
return 0;
}
The search always stops in the rightmost column because you specifically tell it to stop there:
void execute(int tab[][8], int N, int col)
{
int i;
if(col == N)
{
printf("Solution %d ::\n\n", sol + 1);
viewtab(tab, N);
sol++;
return;
}
Look at your termination condition: you check the current column against the highest column number, and stop there.
If you want to go back to column 0, you have to change your loop logic. For instance, let col reach N, at which point you reset it to 0, and let it continue until you hit the original value. Another way is to continue until the count of placed queens is N.
You choose the initial point in the same way: you pick the first one and make your recursive call. If that eventually results in a solution, you print it. If not, your top-most call continues to the next row (line) of the board and puts the first queen there.
This is already in your main logic. Just make sure that secury will return true when the board is empty, rather than false or throwing an error.
A. You can place the first Queen at (0,0).
B. And begin the search also from (0,0).
C. I do not see any need to start looking for some other index.
Successfully!!

Array element disappears

I'm trying to track a player's location with x marking their spot. When the player enters a string I increment the coordinates accordingly. However when the player is located one space from the perimeter, then attempts to move to the edge of the map, the player disappears.
Example:
.....
...x.
.....
.....
.....
Player located at 'x'
If player enters string "right" and I move player_loc, array simply returns:
.....
.....
.....
.....
.....
I attempted to add a sort of buffer by increasing the size of the array. No luck. I've been stuck on this for almost a week now. Any help would be appreciated. I apologize for messy code. I'm a total newbie at this and I'm really just futzing around in the dark with all this stuff. I've researched this across the forums here and haven't found a solution. If you know of something that I possibly (probably) missed feel free to point me in that direction.
#include <stdio.h>
#include <string.h>
char map[6][6];
char player_loc = 'x';
int row;
int col;
void init_map()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
map[i][j] = '.';
}
}
}
void print_map()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
}
int get_player_loc()
{
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
if(map[j][k] == player_loc)
{
row = k;
col = j;
}
}
}
return row;
return col;
}
void init_player_loc()
{
int check = 1;
for (int g = 0; g < 5; g++) {
for (int h = 0; h < 5; h++) {
if (map[g][h] == 'x') {
check = 0;
}
}
}
if(check == 1) {
map[0][0] = player_loc;
} else {
get_player_loc();
}
}
void move_left()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j-1] = player_loc;
map[i][j] = '.';
}
}
}
}
void move_right()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
}
}
}
}
int main(int argc, char* argv[])
{
char input[15];
printf("You enter a room...you can go left, right, or straight. Which way do you go?\n");
int done = 0;
init_map();
map[3][3] = player_loc;
//init_player_loc();
print_map();
while (!done) {
scanf("%s", input);
if (strcmp("left", input) == 0) {
move_left();
printf("You go left...\n");
print_map();
get_player_loc();
printf("%d %d\n", row, col);
done = 1;
}
else if (strcmp("right", input) == 0) {
move_right();
printf("You go right...\n");
print_map();
get_player_loc();
printf("%d %d\n", row, col);
done = 1;
}
else if (strcmp("straight", input) == 0) {
printf("You go straight...");
done = 1;
}
else {
printf("Sorry, can't do that.\n");
}
}
}
You must break the loop if you find the player location, e.g
void move_right()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
return;
}
}
}
}
In your code you move right the player, and the next loop will find the player in the new location and do the right move again, forever.
Moreover in your code you are not taking care of boundaries of your 2d matrix: j+1 is valid only if j<5.
Then a better code should be
void move_right()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
return;
}
}
}
}
The problem is that your move_right function picks up the player and moves them completely off of the map. Let's say your player is at [0, 2] and step through the code.
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
}
}
[0, 0] No player here, move along
[0, 1] No player here, move along
[0, 2] Found a player! Move them right to [0, 3]
[0, 3] Found a player! Move them right to [0, 4]
[0, 4] Found a player! Move them right to [0, 5]
At 5, the loop ends. Because of the buffer you added, your array is 6x6, so the player is stashed in the wings without crashing the program. There are a few things you should do:
Once you've found and moved the player, break or return so they'll only move once.
Make your array 5x5 (or print all 6x6) so you can see everything.
Do some bounds checking so the player isn't allowed to move right from j = 5.
Watch out for this same bug in move_up, where it would happen as you increment i.
Your loops allow for checking the position twice, once at i,j, and again at i,(j+1) (or some other variant). This probably isn't what you intend. After you find the player you should make the updates and then break out of the loops.
Also, the code as is allows for indexing passed the bounds of the array, in theory. Also not what is desired. You may consider bounds checking. I don't know what is supposed to happen when the player moves right and there is a wall to the right. Does he not move? Wrap around? LR corner could cause seg fault as it is now.
You appear to have row and column indeces transposed in the get_player_loc function, as well as having two return statements (the compiler should warn you about unreachable code), neither of which is required or used by the calling code.
At the start, initialise the row and col variables. (Values taken from your main.)
int row = 3;
int col = 3;
Change the get_player_loc function so that it just updates the globals row and col. It sets row and col to 0 if the player is not found, as per the original.
void get_player_loc(void)
{
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
if(map[j][k] == player_loc)
{
// The meaning of row and col is set by how they are used
// to index the array in the move and print functions. Keep
// the same order and meaning here.
row = j;
col = k;
return;
}
}
}
// Set row and col to 0 if the location is not found.
row = 0;
col = 0;
map[0][0] = player_loc;
}
You'll still have problems when they reach an edge, due to the index into the array going out of bounds in the move functions, but that's a different problem.

Printing out a Diamond with nested for loops

For my java class one of the exercises is to print out a diamond using nested for loops. In the exercise you need to use the minimum amount of outputs, while using nested for loops. The other stipulation is that each output can only output 1 character such as a single space, a single asterisk, or a single end line statement.
I've finished it but i was wondering if there was an easier way to do it, or if anyone has tips on cleaning up my code. It just seems like ended up writing way more than was needed. Any help and tips are greatly appreciated. :)
Here is what the end result needs to look like:
Here is my code:
public class Diamond
{
public static void main(String args[])
{
int b = 11; // secondary asterisk loop counter
int ac = 2; // asterisk count
int sc = 5; // space count
int elc = 2; // end line count
int slc = 1; // space loop count
int sslc = 1; // secondary space loop count
for(int e = 1; e < elc && elc < 12;e++)
{
if(elc <= 6)
{
for(int a = 1; a < ac; a++)
{
for(;sc <= 5 && sc > 0; sc--)
{
System.out.print(" ");
}
System.out.print("*");
}
ac += 2;
sc = 5 - slc;
slc += 1;
}
else if (elc > 6)
{
ac -= 2;
sc = 1;
for (; b < ac ; b++)
{
for(;sc <= sslc && sc > -2; sc++)
{
System.out.print(" ");
}
System.out.print("*");
}
b = 1;
sslc += 1;
}
if(elc != 6)
{
System.out.println();
}
elc += 1;
}
}
}
You may try writing down the 4 edges of the diamond as equations (x+y=4; x-y=2... for example). Then just make a nested loop through each of the cell in the grid to see if you should print a space or a star. The test would look like
If f1(x,y) or f2(x,y) or f3(x,y) or f4(x,y): print '*' else print ' '
where f1,f2,f3,f4 are the equations for the 4 diagonals.
If you are required to minimize the number of characters to be printed, either use an array to prepare, then ignore the trailing spaces; or use some ad-hoc rule (like every row only 2 stars except the 1st and last...)
public class ASultan
{
public static void main(String[] args) {
int size = 9;
for (int i = 1; i < size; i += 2) {
for (int k = size; k >= i; k -= 2) {
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
System.out.println();
}
for (int i = 1; i <= size; i += 2) {
for (int k = 1; k <= i; k += 2) {
System.out.print(" ");
}
for (int j = size; j >= i; j--) {
System.out.print("*");
}
System.out.println();
}
}
}

Resources