How can I output the below asterisks in rhombus shape in c++ using the least number of loops and variables. Maximum no. of stars = n (input taken from the user)
*
* *
* * * = n
* *
*
I tried doing it with just 2 loops but didn't succeed plus the program is too complicated to understand so didn't include it here.
So any algorithms you can think of?
That's not a pyramid, that's a rhombus :)
Anyway let's see the star number:
n=1 -> 1 star
n=2 -> 4 stars
n=3 -> 9 stars
The pattern looks like twice the sum from 1 to n minus n (because the middle row exists once not twice), so s(n) = 2 * (1+n)/2 * n - n = (1+n)*n-n = n*n hey it's the area of a square! Well how surprising. :-)
Now how to draw a n-sized rhombus:
there will be 2*n-1 rows
each row is w = 2*n-1 characters wide
each ith row (starting from i=0) has m = min(i+1, 2*n-1-i) stars, and m-1 spaces between them
so each row needs w - (m) - (m-1) spaces of space padding at sides, i.e. w/2 on left and on right.
Now go write it! :)
This is a common question for education I believe, and thus a Google search is very helpful.
Here is a ready made solution in Visual C++ (as some people learn better from code examples, the choice is yours)...
http://www.softwareandfinance.com/Visual_CPP/Loops_Diamond_Pattern.html
EDIT: Trying to reduce the for loops and keeping the spacing between stars, this is my best effort...
int i, j;
int n = 0;
std::cout << "Enter the maximum number of *:";
std::cin >> n;
std::cout << "\n\n";
for (i = 1; i <= n; i++)
{
std::cout.width(n - i);
std::cout.fill(' ');
std::cout << "";
for (j = 1; j <= i; j++)
std::cout << "* ";
std::cout.width(n - i);
std::cout.fill(' ');
std::cout << "";
std::cout << "\n";
}
for (i = n - 1; i >= 1; i--)
{
std::cout.width(n - i);
std::cout.fill(' ');
std::cout << "";
for (j = 1; j <= i; j++)
std::cout << "* ";
std::cout.width(n - i);
std::cout.fill(' ');
std::cout << "";
std::cout << "\n";
}
std::cout << "\n";
ONLY 2 LOOPS USED:
int i, j;
int n = 0, c = 0, inc = 1;
std::cout << "Enter the maximum number of *:";
std::cin >> n;
std::cout <<"\n\n";
for (i = 1; i <= (n * 2) - 1; i++)
{
c += inc;
if(i == n)
inc = -1;
std::cout.width(n - c);
std::cout.fill(' ');
std::cout << "";
for (j = 1; j <= c; j++)
std::cout << "* ";
std::cout.width(n - c);
std::cout.fill(' ');
std::cout << "";
std::cout <<"\n";
}
std::cout <<"\n";
Two loops? Surely you can get by with just one.. Here is a rough description of the alogirthm I came up with:
Loop through the (2*n-1)^2 square
Determine the amount of stars needed on the current row (i.e. distance to the row with n stars)
Determine the distance from the middle of the current index
If the absolute distance of the current index is smaller than the amount of stars on that row, it needs a star in odd/even indices depending if n is odd/even.
Add endlines end of rows
And here's a near IOCC-worthy quick improvisation of the algorithm that draws the rhombus with 2 variables, the loop counter and n=amount of stars in the middle row.
#include <cmath>
void print_rhombus(int n)
{
for (int i = 1; i <= ((2*n-1)*(2*n-1)); ++i) {
if ((abs((((2*n-1)+1)/2)-(i%(2*n-1) == 0?2*n-1:i%(2*n-1)))) - (n-abs((i%(2*n-1)==0?(i/(2*n-1)):(i/(2*n-1))+1) - n)) < 0 && (
(n%2==1 && ((n-abs((i%(2*n-1)==0?(i/(2*n-1)):(i/(2*n-1))+1) - n))%2==1 && (i%(2*n-1) == 0?2*n-1:i%(2*n-1))%2 == 1 || (n-abs((i%(2*n-1)==0?(i/(2*n-1)):(i/(2*n-1))+1) - n))%2==0 && (i%(2*n-1) == 0?2*n-1:i%(2*n-1))%2==0)) ||
(n%2==0 && ((n-abs((i%(2*n-1)==0?(i/(2*n-1)):(i/(2*n-1))+1) - n))%2==1 && (i%(2*n-1) == 0?2*n-1:i%(2*n-1))%2 == 0 || (n-abs((i%(2*n-1)==0?(i/(2*n-1)):(i/(2*n-1))+1) - n))%2==0 && (i%(2*n-1) == 0?2*n-1:i%(2*n-1))%2==1))
)) {
std::cout << "*";
} else {
std::cout << " ";
}
if (i%(2*n-1) == 0 && (n-abs((i%(2*n-1)==0?(i/(2*n-1)):(i/(2*n-1))+1) - n)) == n) {
std::cout << " = " << n << std::endl;
}
else if (i%(2*n-1) == 0) {
std::cout << std::endl;
}
}
}
It also prints the " = N", which I suppose may not have been the requirement. As you can see, sometimes a couple of extra descriptive variables would go a long ways. And if this were homework, you'd better be prepared to explain it..
Break the task down.
1) First write a program that outputs a square of asterisks. In the example above (n = 3, I think) a five by five square will contain all the asterisks you want to output. Two loops (one inside the other) is the way to do this.
2) Now you have all the asterisks you need, work out formulas for which asterisks should be skipped to get the diamond pattern you want. If you decide an asterisk should be skipped you output a space instead.
All programming is like this, you're faced with a complex problem, you break it down into smaller sub-problems.
Not filled rhombus like this one:
*
* *
* *
* *
* *
* *
*
Code c++:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int w=7;
int h=7;
string fill("*");
string empty(" ");
for (int i = 0; i<w; i++)
{
for (int j = 0; j<h; j++)
{
if((j == h/2-i) or (j == h/2+i) or (j == -h/2+i) or (j+i == h+h/2-1) ) cout << fill;
else cout <<empty;
}
cout<<endl;
}
}
Related
Hello and thank you for coming here.
I have to do a program that will draw a number of square choosed by the user with incremental letter.
For example, if the user choose 4 square, it will return :
DDDDDDD
DCCCCCD
DCBBBCD
DCBABCD
DCBBBCD
DCCCCCD
DDDDDDD
At the time being, my code look like this ;
#include <iostream>
using namespace std;
int main()
{
int size;
int nbsquareletter;
cout << " How many square ?" << endl;
cin >> nbsquareletter;
size = nbsquareletter * 2 - 1;
char squareletter = 'a';
for (int row = 1; row <= size; ++row)
{
for (int col = 0; col <= size; ++col)
{
if (row < col) {
cout << (char)(squareletter + row - 1) << " ";
}
else if (row > col)
{
cout << (char)(squareletter + col) << " ";
}
/*
cout << col << " ";
cout << row << " ";
*/
}
cout << endl;
}
}
If you have any ideas to help me, don't hesitate, I'm struggling. it's been 3.5 hours. Thanks you for reading and have a good day !
Try to keep things simple. If you start write code before you have a clear idea of how to solve it you will end up with convoluted code. It will have bugs and fixing them will make the code even less simple.
Some simple considerartions:
The letter at position (i,j) is determined by the "distance" from the center. The distance is max(abs(i - i_0), abs(j - j_0).
The center is at (i,j) = (size-1,size-1) when we start to count at upper left corner (0,0).
The letters can be picked from an array std::string letters = "ABCDEFG...".
i and j are in the range [0,2*size-1)
Just writing this (and nothing more) down in code results in this:
#include <iostream>
#include <string>
void print_square(int size){
std::string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i_0 = size-1;
int j_0 = size-1;
for (int i=0;i< 2*size-1;++i){
for (int j=0;j< 2*size-1;++j) {
int index = std::max(std::abs(i-i_0),std::abs(j-j_0));
std::cout << letters[index];
}
std::cout << "\n";
}
}
int main() {
print_square(4);
}
Which produces output
DDDDDDD
DCCCCCD
DCBBBCD
DCBABCD
DCBBBCD
DCCCCCD
DDDDDDD
Your code cannot print the right output, because when row == col there is no output, and it misses the diagonal. I didnt look further than that.
Instead of fixing bugs in your code I decided to suggest you my own solution. Maybe some other answers will be related to bugs in your code.
On piece of paper I figured out 4 different formulas for 4 parts of a drawn picture, formulas computing what letter to take inside English alphabet. Afterwards I take this letter from array with alphabet.
Try it online!
#include <iostream>
int main() {
int n = 0;
std::cin >> n;
char const letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < 2 * n - 1; ++i) {
for (int j = 0; j < 2 * n - 1; ++j)
std::cout << letters[
i <= j && i + j < 2 * n - 1 ? n - i - 1 :
i <= j && i + j >= 2 * n - 1 ? j - n + 1 :
i > j && i + j < 2 * n - 1 ? n - j - 1 :
i > j && i + j >= 2 * n - 1 ? i - n + 1 : 25
];
std::cout << std::endl;
}
}
Input:
7
Output:
GGGGGGGGGGGGG
GFFFFFFFFFFFG
GFEEEEEEEEEFG
GFEDDDDDDDEFG
GFEDCCCCCDEFG
GFEDCBBBCDEFG
GFEDCBABCDEFG
GFEDCBBBCDEFG
GFEDCCCCCDEFG
GFEDDDDDDDEFG
GFEEEEEEEEEFG
GFFFFFFFFFFFG
GGGGGGGGGGGGG
Let's define some functions, to make the recurrence relation obvious.
std::vector<std::string> WrapInLetter(char letter, std::vector<std::string> lines)
{
for (auto & line : lines)
{
line.insert(line.begin(), letter);
line.insert(line.end(), letter);
}
std::size_t size = (lines.size() * 2) + 1;
std::string edge(size, letter); // A string formed of size copies of letter
lines.insert(lines.begin(), edge);
lines.insert(lines.end(), edge);
return lines;
}
std::vector<std::string> SquareLetter(char letter)
{
if (letter == 'A') return { "A" };
return WrapInLetter(letter, SquareLetter(letter - 1));
}
Now main just has to call that function and loop over the result.
int main()
{
std::cout << "How many square ?" << std::endl;
int size;
std::cin >> size;
for (auto line : SquareLetter('A' + size - 1))
{
std::cout << line << std::endl;
}
}
I'm trying to convert an histogram with absolute values to an histogram showing the relative frequency of letters in a string, written by the user. The letters frequency should be represented by *. So, if the letter "A" is 1% of a string, there should be two *. 1% = two *.
When trying to calculate the frequency, the output is zero. I don't really understand why.
I've tried to search the internet, but I can't really find something that helps me. I guess I'm stuck, both in my head and coding.
This is the code for my three functions:
void berakna_histogram_abs(const string inm, int arr[ANTAL_BOKSTAVER]){
int i, j = 0;
while (inm[i] != '\0'){
if (inm[i] >= 'a' && inm[i] <= 'z'){
j = inm[i] - 'a';
++arr[j];
}
if (inm[i] >= 'A' && inm[i] <= 'Z'){
j = inm[i] - 'A';
++arr[j];
}
i++;
}
}
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int (&ree)[ANTAL_BOKSTAVER]){
for(int i = 0; i < ANTAL_BOKSTAVER; i++) {
ree[i] = arr[i] / 26;
printf("%c %lf \n", i + 'a', ree[i]);
}
for (int x = 0; x < ANTAL_BOKSTAVER; x++){
}
}
void plotta_histogram_rel(int (&ree)[ANTAL_BOKSTAVER]){
cout << "Frekvensen av bokstäver i texten är: " << endl;
for (int i = 0; i < ANTAL_BOKSTAVER; i++){
cout << char(i + 'a') << " : " << ree[i] << endl;
}
}
I'm not allowed to do any calculations in the third function, that is only for writing the histogram. The whole program is pretty big, if you'd like, I'll provide all the code.
Any help forward is much appreciated.
Thanks!
So, you have some errors that need to be corrected. You do not pass the array as reference in the first function. You pass it by value. So all modifications that will be done to that arra in the first function berakna_histogram_abs will not be visible to the outside world.
You need to do the same as in you other functions -->
void berakna_histogram_abs(const std::string inm, int (&arr)[ANTAL_BOKSTAVER]) {
By the way, the string should also be passed as reference. Anyway. Not so important.
Next problem. You forgot to initialize variable i to 0 in your first function. So, it will have some random value and the program will fail, becuase you access some random index with inm[i].
In your calculation function abs_till_rel you are using the wrong formular. You need to multiply with 100 to get integer results between 0 and 100 for the percentage. And you divide by 26, which makes the result relative to the amount of the number of letters in an alphabet. My guess is that you want to have the relations to the number of letters in the string.
For that, you first need to calculate all counts of letters to get the overall count. Like for example with:
int sum = 0;
for (int i = 0; i < ANTAL_BOKSTAVER; i++) sum += arr[i];
and then divide by this sum, like so:
ree[i] = (arr[i] * 100) / sum;
And to output the histogram, you can simply build a string with stars, using the std::string constructor number 2
Your updated program would look like this:
#include <iostream>
#include <string>
#include <stdio.h>
constexpr int ANTAL_BOKSTAVER = 26;
void berakna_histogram_abs(const std::string inm, int (&arr)[ANTAL_BOKSTAVER]) {
int i = 0, j = 0;
while (inm[i] != '\0') {
if (inm[i] >= 'a' && inm[i] <= 'z') {
j = inm[i] - 'a';
++arr[j];
}
if (inm[i] >= 'A' && inm[i] <= 'Z') {
j = inm[i] - 'A';
++arr[j];
}
i++;
}
}
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int(&ree)[ANTAL_BOKSTAVER]) {
int sum = 0;
for (int i = 0; i < ANTAL_BOKSTAVER; i++) sum += arr[i];
if (sum >0) for (int i = 0; i < ANTAL_BOKSTAVER; i++) {
ree[i] = (arr[i] * 100) / sum;
std::cout << (char)(i + 'a') << '\t' << ree[i] << '\n';
}
for (int x = 0; x < ANTAL_BOKSTAVER; x++) {
}
}
void plotta_histogram_rel(int(&ree)[ANTAL_BOKSTAVER]) {
std::cout << "Frekvensen av bokstäver i texten är: " << std::endl;
for (int i = 0; i < ANTAL_BOKSTAVER; i++) {
std::cout << char(i + 'a') << " : " << std::string(ree[i]*2,'*') << std::endl;
}
}
int main() {
std::string test{"The quick brown fox jumps over the lazy dog"};
int frequencyArray[ANTAL_BOKSTAVER] = {};
int frequencyInPercent[ANTAL_BOKSTAVER] = {};
berakna_histogram_abs(test, frequencyArray);
abs_till_rel(frequencyArray, frequencyInPercent);
plotta_histogram_rel(frequencyInPercent);
}
But in C++, we would use the standard approach and write the followin:
#include <iostream>
#include <map>
#include <string>
#include <cctype>
// Our test string. This is a standard test string that contains all letters
std::string test{ "The quick brown fox jumps over the lazy dog" };
int main() {
// Count all letters
std::map<char, size_t> counter{};
for (const auto& c : test) if (std::isalpha(c)) counter[std::tolower(c)]++;
// Show histogram
for (const auto& [letter, count] : counter)
std::cout << letter << '\t' << std::string((count * 200) / test.size(), '*') << '\n';
return 0;
}
void abs_till_rel(int arr[ANTAL_BOKSTAVER], int langd, double frekArr[ANTAL_BOKSTAVER]){
//Function to calculate the relative frequency of letters in a string.
for (int i = 0; i < ANTAL_BOKSTAVER; i++){
frekArr[i] = arr[i]; //Writes over the input from the user to a new array.
frekArr[i] = frekArr[i] * 200 / langd; //Calculates the relative frequency
//*200 since 1% should be represented by two (2) *.
}
}
void plotta_histogram_rel(double frekArr[ANTAL_BOKSTAVER], int langd){
int j = 0;
for (int i = 0; i < ANTAL_BOKSTAVER; i++){
cout << char(i + 'A') << " : ";
//Creates a histograg, horizontal, with A-Z.
if(frekArr[i] > 0){
for ( j = 0; j < frekArr[i]; j++){
cout << "*";
}
cout << endl;
}
//If the index in frekArr is NOT empty, loop through the index [i] times and
//write double the amount of *.
else {
cout << " " << endl;
//Else, leave it empty.
}
}
}
I've solved the issue. See the working code above.
I need to print a star pattern like this:
*****
** *
*** *
*****
The code that I have tried is:
#include <iostream>
using namespace std;
int main()
{
int i,j,k;
for(i=1;i<5;i++){
for(j=1;j<5;j++){
if(i==1 || j==4 || i==4 )
// if(j==4 || i==4)
cout<<"*";
if(i>1 && i<4){
for(k=1;k<3;k++){
cout<<"";
}
}
else {
cout<<"";
}
}
cout<<endl;
}
return 0;
}
This is the output I get:
****
*
*
****
So, you see I'm having trouble printing the star at the end of each line. and as you can see in the desired output I provided above, in the 2nd and 3rd line, I need to print them with gaps. Now, as I've given the code, I tried to do that but not sure why isn't it working. So, I need your help in achieving this output.
Many other questions have similar title but this is about a completely different star pattern.
P.S: On a side note, I want to mention that I've been learning C++ for over a year now, and I am still having trouble with loops. I have understood other things such as functions, if-else, structures, arrays, basic oop etc, but for some reason, loops trouble me so I thought I should do these star pattern exercises. If you guys have any suggestions how I can improve my logic in loops (especially the nested ones), then it would be very helpful for me. Thanks.
Corrected code with my comments:
#include <iostream>
using namespace std;
int main()
{
int n = 5; // columns count
for(int i = 1; i < n; i++) // i is row index
{
for(int j = 1; j <= n; j++) // j is current symbol index in line i
{ // note, you print 5 symbols per line, so j <= 5, not j < 5
if (i > 1 && i < n && j != n && j > i) // for lines 2 and 3 indexes [3-4] and [4] print space, print * for symbol #5 (last symbol in a line is always *)
{
cout << " ";
}
else
{
cout << "*";
}
}
cout << endl;
}
return 0;
}
i=1;i<5;
This runs 4 times. i=1,i=2,i=3,i=4.
You either need i<6 or i<=5
In an effort to make the "shortest, cleanest C++ code," you could do it all in a single loop:
int n = 10; //input
std::cout << std::string(n, '*') << std::endl; //First line
for (int i = 2; i < n; i++)
std::cout << std::string(i, '*');
<< std::string(n - i - 1, ' ')
<< '*' << std::endl;
The Issue is that "" does not register a space, " " will though.
int main()
{
int i, j, k;
for (i = 0; i < 4; i++) {
for (j = 0; j < 5; j++) {
if (i == 0 || i == 3)
{
cout << "*";
}
else if (i == 1) {
if (j == 2 || j == 3) {
cout << " ";
}
else {
cout << "*";
}
}
else if (i == 2) {
if (j == 3) {
cout << " ";
}
else {
cout << "*";
}
}
}
cout << endl;
}
return 0;
}
here's a solution in python. you should be able to extrapolate from that into C++
N = 10
print('*' * N)
for row in range(2, N+1):
print('*' * row, end='')
print(' ' * (N-row -1), end='')
print('*')
here's a solution in C++, which does the exact same thing but is longer than the python solution. I gave the python solution first because I believed it shows the thought process more cleanly than the C++ counterpart.
int N = 10;
for(int i=0 ; i<N ; ++i)
cout << '*';
cout << endl;
for (int row = 2; row < N; ++row) {
for(int i=0 ; i<row ; ++i)
cout << "*";
for(int i=row ; i<N-1; ++i)
cout << ' ';
cout << '*' << endl;
}
this is the output for N=10
**********
** *
*** *
**** *
***** *
****** *
******* *
******** *
**********
So, I am trying to write a program to compute the value of the series 1/0! + 1/1! + 1/2! + .. + 1/n!. I think this is a pretty easy question to solve. But, the 1/0! i.e. the 1st term of the series is where it is creating all the problems for me. Please help me out. Please pardon for the silly mistakes if I have made since I started learning C++ 2 months ago and I am trying to solve various problems ever since.
#include <iostream>
using namespace std;
int fact(int j)
{
int facto = 1;
if (j == 0) {
return facto;
}
else {
for (int i = 2; i <= j; i++) {
facto = facto * i;
}
return facto;
}
}
int main()
{
int n, p;
float sum = 0, k;
cout << "Enter the value of n: " << endl;
cin >> n;
for (int i = 0; i < n; i++) {
p = fact(i);
cout << p << endl;
k = 1 / p;
cout << k << endl;
sum = sum + k;
}
cout << "Sum is: " << sum << endl;
return 0;
}
I have 2 questions :
1) When I am giving 0 as input, I am getting 0(i.e. the value of sum) as output(but, I am expecting to get 1) and, when I am giving 1 as input, it is giving 1 as output(expecting 2 as output). Please help me in pointing out the loophole.
2) When I am giving 0 as input, it is not printing the values of 'p' and 'k' but any input greater than 0 is showing the values of 'p' and 'k' for each time it completes the loop. Why ??
Change the loop the following way
for(int i=0; i<=n; i++)
^^^^^
Or change the loop to do-while loop as for example
int i = 0;
do
{
//...
} while ( i++ < n );
Also this statement
k = 1/p ;
change like
k = 1.0f/p ;
I have to print out a triangle-star formed shape as such where the user specifies the intial number of asterisks--be it 10, 25, or 30.
***** (5)
*** (3)
* (1)
OR
********** (10)
********
******
****
**
*
I have written the code with three loops--two nested in one--using C++ Someone else claims that it can be done only using two loops but I can't seem to figure it out. In my head, its like asking to draw a triangle out of only 2 lines; it simply cannot work. I would appreciate it if someone could confirm if it can be done with only two loops and if so provide a hint or explanation.
Theoretical computer science says that every problem can be solved in one loop.
This doesn't mean that it's always easy, but in your case, it fortunately is!
How about this program, http://ideone.com/nTnTC8:
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
int startNum = 0;
cin >> startNum;
if (startNum <= 0) return 1;
cout << startNum << endl;
int numCols = startNum;
int numRows = (startNum + 1) / 2;
if (numCols % 2 == 0) {
++numRows;
}
int numFields = numCols * numRows;
for (int currentField = 0; currentField < numFields; ++currentField) {
int currentRow = currentField / numCols;
int currentCol = currentField % numCols;
if (currentCol < currentRow) cout << "-";
else if (currentCol > (numCols - currentRow - 1))
if (currentRow == numRows - 1 && currentCol == numCols / 2)
cout << "^";
else cout << "_";
else cout << "*";
if (currentCol == numCols - 1) cout << endl;
}
return 0;
}
To use 2 for loops, you will have one loop for the lines and another nested loop for the characters.
An "if" statement can be used to determine whether to print a '*' or space.
Another alternative is to use functions that create strings of repetitive characters.
Edit 1:
This may come in handy, centering formula for text:
starting_position = center_position - (character_count / 2);
One loop is sufficient, to enumerate all lines. To print N spaces on line N, use the std::string(N, ' ') constructor.
Strictly speaking, this code does the trick using 2 loops :
int n, s, z;
cout << "Enter the width \n";
cin >> n;
// for each row
for (int i = 0; i < n/2+1; i++) {
z = i; // set number of spaces to print
s = (n-i*2) + (i == n/2 ? (1-n%2) : 0); // set number of stars to print
// still something to print
while (z+s > 0) {
if ( z ) {
cout << " ";
z--;
} else if ( s ) {
cout << "*";
s--;
}
}
cout << endl;
}