translating algorithm for C++ nested while loop diamond pattern - c++

Here is my homework problem for C++:
The following algorithm is a solution to a problem that uses nested loops to display a diamond pattern. Translate the algorithm below in to a C++ program. Build, run and test the program.
Algorithm Solution:
Start
Declare numRows as constant integer = 7
Declare maxPlus as constant integer = 7
Declare numSpaces as integer
Declare numPluses as integer
Declare row as integer
Declare space as integer
Declare plus as integer
Set row = 1
Repeat while row >= 1 AND row <= numRows
Set numPluses = 2 * row - 1
if(numPluses > maxPlus) then
Set numPluses = 14 - numPluses
endif
Set numSpaces = (maxPlus - numPluses) / 2
Set space = 1
Repeat while space >= 1 AND space <= numSpaces
Display( ' ')
Set space = space + 1
End Repeat
Set plus = 1
Repeat while plus >= 1 AND plus <= numPluses
Display( '*')
Set plus = plus + 1
End Repeat
Set row = row + 1
Display a new line
End Repeat
Stop
My code:
#include <iostream>
using namespace std;
int main() {
const int numRows = 7;
const int maxPlus = 7;
int numSpaces;
int numPluses;
int row;
int space;
int plus;
row = 1;
while((row >=1) && (row <= numRows)){
numPluses = 2 * row - 1;
if(numPluses > maxPlus){
numPluses = 14 - numPluses;
}
numSpaces = (maxPlus - numPluses)/ 2;
space = 1;
while((space >= 1) && (space <= numSpaces)){
cout << " ";
space++;
}
while((plus >= 1) && (plus <= numPluses)){
cout << "*";
plus++;
}
row++;
cout << endl;
}
return 0;
}
My question is why am I not getting the diamond pattern? I feel like I translated the algorithm correctly, but all I get is a bunch of blank space. Did I read the problem wrong or did I code wrong? screenshot of C++ code

Before the last while loop:
Set plus = 1
You missed that in your translation.

The code did not initialize plus.
There's a habit that saves much grief. Never declare a variable without giving it a meaningful initial value at the point of definition. Limit the scope of variables to where they are actually used. When translating pseudo-code, that can mean doing a little bit of re-writing. Diggit.
int main() {
const int numRows = 7;
const int maxPlus = 7;
for (int row = 1; row <= numRows; ++row) {
const int trianglePluses = 2 * row - 1;
const int numPluses = trianglePluses <= maxPlus
? trianglePluses
: 2 * numRows - trianglePluses;
const int numSpaces = (maxPlus - numPluses) / 2;
for(int space=1; space <= numSpaces; ++space) {
cout << " ";
}
for (int plus = 1; plus <= numPluses; ++plus) {
cout << "*";
}
cout << endl;
}
return 0;
}

Related

Code to convert decimal to hexadecimal without using arrays

I have this code here and I'm trying to do decimal to hexadecimal conversion without using arrays. It is working pretty much but it gives me wrong answers for values greater than 1000. What am I doing wrong? are there any counter solutions? kindly can anyone give suggestions how to improve this code.
for(int i = num; i > 0; i = i/16)
{
temp = i % 16;
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
num = num * 100 + temp;
}
cout<<"Hexadecimal = ";
for(int j = num; j > 0; j = j/100)
{
ch = j % 100;
cout << ch;
}
There's a couple of errors in the code. But elements of the approach are clear.
This line sort of works:
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
But is confusing because it's using 48 and 55 as magic numbers!
It also may lead to overflow.
It's repacking hex digits as decimal character values.
It's also unconventional to use ?: in that way.
Half the trick of radix output is that each digit is n%r followed by n/r but the digits come out 'backwards' for conventional left-right output.
This code reverses the hex digits into another variable then reads them out.
So it avoids any overflow risks.
It works with an unsigned value for clarity and a lack of any specification as how to handle negative values.
#include <iostream>
void hex(unsigned num){
unsigned val=num;
const unsigned radix=16;
unsigned temp=0;
while(val!=0){
temp=temp*radix+val%radix;
val/=radix;
}
do{
unsigned digit=temp%16;
char c=digit<10?'0'+digit:'A'+(digit-10);
std::cout << c;
temp/=16;
}while(temp!=0);
std::cout << '\n';
}
int main(void) {
hex(0x23U);
hex(0x0U);
hex(0x7U);
hex(0xABCDU);
return 0;
}
Expected Output:
23
0
8
ABCD
Arguably it's more obvious what is going on if the middle lines of the first loop are:
while(val!=0){
temp=(temp<<4)+(val&0b1111);
val=val>>4;
}
That exposes that we're building temp as blocks of 4 bits of val in reverse order.
So the value 0x89AB with be 0xBA98 and is then output in reverse.
I've not done that because bitwise operations may not be familiar.
It's a double reverse!
The mapping into characters is done at output to avoid overflow issues.
Using character literals like 0 instead of integer literals like 44 is more readable and makes the intention clearer.
So here's a single loop version of the solution to the problem which should work for any sized integer:-
#include <iostream>
#include <string>
using namespace std;
void main(int argc, char *argv[1])
{
try
{
unsigned
value = argc == 2 ? stoi(argv[1]) : 64;
for (unsigned i = numeric_limits<unsigned>::digits; i > 0; i -= 4)
{
unsigned
digit = (value >> (i - 4)) & 0xf;
cout << (char)((digit < 10) ? digit + 48 : digit + 55);
}
cout << endl;
}
catch (exception e)
{
cout << e.what() << endl;
}
}
There is a mistake in your code, in the second loop you should exit when j > original num, or set the cumulative sum with non-zero value, I also changed the cumulative num to be long int, rest should be fine.
void tohex(int value){
long int num = 1;
char ch = 0;
int temp = 0;
for(int i = value; i > 0; i = i/16)
{
temp = i % 16;
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
num = num * 100 + temp;
}
cout<<"Hexadecimal = ";
for(long int j = num; j > 99; j = j/100)
{
ch = j % 100;
cout << ch;
}
cout << endl;
}
If this is a homework assignment, it is probably related to the chapter on Recursivity. See a solution below. To understand it, you need to know
what a lookup table is
what recursion is
how to convert a number from one base to another iteratively
basic io
void hex_out(unsigned n)
{
static const char* t = "0123456789abcdef"; // lookup table
if (!n) // recursion break condition
return;
hex_out(n / 16);
std::cout << t[n % 16];
}
Note that there is no output for zero. This can be solved simply by calling the recursive function from a second function.
You can also add a second parameter, base, so that you can call the function this way:
b_out(123, 10); // decimal
b_out(123, 2); // binary
b_out(123, 8); // octal

How the code output is different when you compute it mentally? when the j = 2 the output should be 1, but the computer display 3

I was searching a method to print a pascal triangle, but when I tried to compute mentally it doesn't look right.
the output of this is 1 3 3 1.
but when you mentally calculate the iteration one by one the output is 1 3 1 0.
is there something that I was missing?
#include <iostream>
using namespace std;
int main()
{
coef = 1;
int i = 3;
int j = 0;
while (j <= i)
{
if (j == 0)
coef = 1;
else
coef = coef * (i - j + 1)/j;
cout << coef << " ";
j++;
}
return 0;
}
Your mental computation is bit wrong as I am sure you are not updating the value of "coef" mentally which is being changed to 3 rather than 1 which you seem to have missed after the 2nd iteration of the loop.

Shifting Objects Up in an Array

I'm creating a program that creates an array of objects in random positions in an array size 8. Once created, I need them to sort so that all the objects in the array are shifted up to the top, so no gaps exist between them. I'm almost there, but I cannot seem to get them to swap to index 0 in the array, and they instead swap to index 1. Any suggestions? (Must be done the way I'm doing it, not with other sorting algorithms or whatnot)
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
struct WordCount {
string name = "";
int count = 0;
};
int main() {
cout << "Original random array: " << endl;
srand(static_cast<int>(time(0)));
int i = 0;
WordCount wordArr[8];
while (i < 4) {
int randomNum = 0 + (rand() % static_cast<int>(7 + 1));
if(wordArr[randomNum].name == "") {
wordArr[randomNum].name = "word" + static_cast<char>(i);
wordArr[randomNum].count = i;
i++;
}
}
int j = 0;
while (j < 8) {
cout << wordArr[j].name << " " << wordArr[j].count << endl;
j++;
}
cout << "\n\nSorted array: " << endl;
for (int i = 7; i >= 0; i--) {
for (int j = 0; j <= 7; j++) {
if (wordArr[i].name != "") {
if (wordArr[j].name == "") {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
}
int k = 0;
while (k < 8) {
cout << wordArr[k].name << " " << wordArr[k].count << endl;
k++;
}
return 0;
}
If I understand your requirement correctly, you want to move all the non-blank entries to the start of the array. To do this, you need an algorithm like this for example:
for i = 0 to 7
if wordArr[i].name is blank
for j = i + 1 to 7
if wordArr[j].name is not blank
swap [i] and [j]
break
So, starting from the beginning, if we encounter a blank entry, we look forward for the next non-blank entry. If we find such an entry, we swap the blank and non-blank entry, then break to loop again looking for the next blank entry.
Note, this isn't the most efficient of solutions, but it will get you started.
Note also I'd replace the 4 and 8 with definitions like:
#define MAX_ENTRIES (8)
#define TO_GENERATE_ENTRIES (4)
Finally:
wordArr[randomNum].name = "word" + static_cast<char>(i);
That will not do what you want it to do; try:
wordArr[randomNum].name = "word" + static_cast<char>('0' + i);
To append the digits, not the byte codes, to the end of the number. Or perhaps, if you have C++11:
wordArr[randomNum].name = "word" + std::to_string(i);
I see couple of problems.
The expression "word" + static_cast<char>(i); doesn't do what you are hoping to do.
It is equivalent to:
char const* w = "word";
char const* p = w + i;
When i is 2, p will be "rd". You need to use std::string("word") + std::to_string(i).
The logic for moving objects with the non-empty names to objects with empty names did not make sense to me. It obviously does not work for you. The following updated version works for me:
for (int i = 0; i <= 7; ++i) {
// If the name of the object at wordArr[i] is not empty, move on to the
// next item in the array. If it is empty, copy the next object that
// has a non-empty name.
if ( wordArr[i].name == "") {
// Start comparing from the object at wordArr[i+1]. There
// is no need to start at wordArr[i]. We know that it is empty.
for (int j = i+1; j <= 7; ++j) {
if (wordArr[j].name != "") {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
}
There was two problems as :
wordArr[randomNum].name = "word" + static_cast<char>(i); this is not what your are looking for, if you want that your names generate correctly you need something like this :
wordArr[randomNum].name = "word " + std::to_string(i);
Your sorting loop does not do what you want, it's just check for the "gaps" as you said, you need something like this :
for (int i = 0; i < 8; ++i) {
for (int j = i+1; j < 8; ++j) {
if (wordArr[i].name == "" || (wordArr[i].count < wordArr[j].count)) {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
Your algorithm sorts the array, but then looses the sorting again.
You want to swap elements only when i > j, in order to push elements to the top only. As a result, you need to change this:
if (wordArr[j].name == "")
to this:
if (wordArr[j].name == "" && i > j)
Consider this array example:
0
ord 1
0
0
rd 2
word 0
d 3
0
Your code will sort it to:
d 3
ord 1
word 0
rd 2
0
0
0
0
but when i = 3, it will try to populate the 5th cell, and it will swap it with rd 2, which is not what we want.
This will push rd 2 down, but we don't want that, we want gaps (zeroes) to go to the end of the array, thus we need to swap eleemnts only when they are going to go higher, not lower, which is equivalent to say when i > j.
PS: If you are a beginner skip that part.
You can optimize the inner loop by using one if statement and a break keyword, like this:
for (int j = 0; j <= 7; j++) {
if (wordArr[i].name != "" && wordArr[j].name == "" && i > j) {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
break;
}
}

How to make array with cells numbered from negative number to positive?

I'd like to make non-graphic (text) C++ game (you move your character using n, s, w, e and every location is described). Locations will be an array of an objects (there will be location description and other information in this array). I've started making this game, but I have a question: Is it possible to make arrays with dimensions x - from -100 to 100 and z - from -100 to 100? If it is not possible, are there other ways to do it? (I don't want a [0][0] position in one of 4 corners, but on the middle.)
An Array can have only positive indexes:
Location loc[201][201];
define a Funktion that returns your desired Location:
Location getLocation(int xCoord, int yCoord)
{
if (abs(x)>100 || abs(y)>100)
throw std::invalid_argument( "value out of range");
return loc[xCoord+100][yCoord+100];
}
Then you can get the Location by calling the function getLocation(x,y)
One common (but rather sketchy) method is to do something like this (example for 21 x 21 board):
#include <iostream>
using namespace std;
int main()
{
typedef int (*board_ptr)[21];
int board_data[21][21];
board_ptr board = (board_ptr)&board_data[10][10];
for (int i = -10; i <= 10; ++i)
for (int j = -10; j <= 10; ++j)
board[i][j] = 0;
board[-10][-10] = 1;
board[-10][10] = 2;
board[10][-10] = 3;
board[10][10] = 4;
board[0][0] = 5;
for (int i = -10; i <= 10; ++i)
{
for (int j = -10; j <= 10; ++j)
{
cout << " " << board[i][j];
}
cout << endl;
}
return 0;
}
This creates a normal 21x21 array but then it also creates a pointer to a fake array which is initialised to point at the centre of the real array. You can then use this fake pointer as if it were a real array with indices ranging from -10 to +10 (inclusive).
LIVE DEMO

Project Euler #8 - C++ code failed to work

I know there are multiple topic regarding Project Euler #8. But I am using a different approach, no STL.
#include <iostream>
using namespace std;
int main(){
char str[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int size = strlen(str);
int number = 1;
int max = 0;
int product = 0;
int lowerBound = 0;
int upperBound = 4;
for (int i = 0; i <= size/5; i++)
{
for (int j = lowerBound; j <= upperBound; j++)
{
number = number * str[j];
}
product = number;
number = 1;
lowerBound += 5;
upperBound += 5;
if (product > max)
{
max = product;
}
}
cout << "the largest product: " << max << endl;
return 0;
}
the answer is : 550386080, which is way too big and incorrect.
Please tell me what's wrong with my code. No advanced pointers or template technique, just control flow statement and some basic stuff.
Part of your problem is the expression
number = number * str[j];
The str[j] is an ASCII character and you are incorrectly assuming it's a numeric value in the range 0..9. A cheap way to convert a single numeric character to a number would be to say
number = number * (str[j] - '0');
That gets you closer to the correct answer but there is another problem. You are testing each index range like [0..4], [5..9], [10..14], [15..19], etc. You should instead be testing indices [0..4], [1..5], [2..6], [3..7], etc. I'll leave that for you to correct.