I'm trying to experiment with 2D arrays in C++ and I'm working on a project that makes a 4x4 2D array that holds a number of student grades but it is partially filled via a text file. Only 3 out of the 4 columns are filled. I want to filled the last column with an average of the grades in the previous rows of each column.
The problem is I can't figure out exactly how to fill the last column.
This my code for calculating the average.
const int SIZE = 4;
const int ROWS = 4;
const int COLS = 4;
int total = 0;
for (int i = 0; i < ROWS; i++)
{
total = 0;
for (int j = 0; j < COLS - 1; j++)
{
total += studentGrades[i][j];
average = total / (COLS - 1);
studentGrades[0][3] = average;
studentGrades[1][3] = average;
studentGrades[2][3] = average;
studentGrades[3][3] = average;
}
}
It seems like I'm close because I'm getting good results but the last column isn't displaying the right values and I feel like there's a more efficient way to fill the last column instead of manually inserting into each index.
You are assigning the last computed average to all rows every time. This means at the end you will have the average of row 4 in all 4 columns. Also consider changing your variables (studentGrades and total) to a floating point type for more accuracy.
const int SIZE = 4;
const int ROWS = 4;
const int COLS = 4;
for (int i = 0; i < ROWS; i++)
{
int total = 0;
for (int j = 0; j < COLS - 1; j++)
total += studentGrades[i][j];
studentGrades[i][COLS - 1] = total / (COLS - 1);
}
You could also make use of the standard library:
#include <numeric>
// ...
constexpr int Rows = 4, Cols = 4, NGrades = Cols - 1;
for (int i = 0; i < Rows; i++)
studentGrades[i][NGrades] = std::accumulate(studentGrades[i], studentGrades[i] + NGrades, 0) / NGrades;
As in my first solution, consider using floating point types. To enable float arithmetic change the 0 of std::accumulate to 0.0 or 0.0f.
Here is an explanation of std::accumulate.
The logic is wrong. You can only calculate the average and fill the last column after you have totaled the other columns, and you can only fill one row at a time, instead of trying to do all four rows together. This is the correct loop
for (int i = 0; i < ROWS; i++)
{
total = 0;
for (int j = 0; j < COLS - 1; j++)
{
total += studentGrades[i][j];
}
average = total / (COLS - 1);
studentGrades[i][3] = average;
}
It's just a matter of doing things in the right order and at the right time.
Plus you should pay attention to the integer division problem that Yksisarvinen pointed out.
Related
Given an m x n integer grid, return the size (i.e., the side length k) of the largest magic square that can be found within this grid.
The question can be found here on leetcode
I first wanted to see if a naive brute force approach would pass, so I came up with the following algorithm
Iterate through all values of k (from min(rows,cols) of the matrix to 1)
For each of the k values, check if it's possible to create a magic of square of dimensions kxk by checking all possible sub matrices and
return k if it's possible. This would be O(rows*cols*k^2)
So that would make the overall complexity O(k^3*rows*cols). (Please correct me if I am wrong)
I have attached my code in C++ below
class Solution {
public:
int largestMagicSquare(vector<vector<int>>& grid) {
int rows = grid.size(),cols = grid[0].size();
for(int k = min(rows,cols); k >= 2; k--){ // iterate over all values of k
for(int i = 0; i < rows-k+1; i++){
for(int j = 0; j < cols-k+1; j++){
int startX = i, startY = j, endX = i+k-1, endY = j+k-1;
int diagSum = 0, antiDiagSum = 0;
bool valid = true;
// calculate sum of diag
for(int count = 0; count < k; count++){
diagSum += grid[startX][startY];
startX++,startY++;
}
// this is the sum that must be same across all rows, cols, diag and antidiag
int sum = diagSum;
// calculate sum of antidiag
for(int count = 0; count < k; count++){
antiDiagSum += grid[endX][endY];
endX--,endY--;
}
if(antiDiagSum != sum) continue;
// calculate sum across cols
for(int r = i; r <=i+k-1; r++){
int colSum = 0;
for(int c = j; c <= j+k-1; c++){
colSum += grid[r][c];
}
if(colSum != sum){
valid = false;
break;
}
}
if(!valid) continue;
// calculate sum across rows
for(int c = j; c <= j+k-1; c++){
int rowSum = 0;
for(int r = i; r <= i+k-1; r++){
rowSum += grid[r][c];
}
if(rowSum != sum){
valid = false;
break;
}
}
if(!valid) continue;
return k;
}
}
}
return 1;
}
};
I thought I would optimize the solution once this works (Maybe binary search over the values of k). However, my code is failing for a really large test case for a matrix of dimension 50x50 after passing 74/80 test cases on Leetcode.
I tried to find out the source(s) that could be causing it to fail, but I am not really sure where the error is.
Any help would be appreciated. Thanks!
Please do let me know if further clarification about the code is needed
The calculation of antiDiagSum is wrong: it actually sums the values on the same diagonal as diagSum, just in reverse order. To traverse the opposite diagonal, you need to increment the Y coordinate and decrement the X coordinate (or vice versa), but your code decrements both of them.
It is probably easiest if you fix this by calculating both diagonal sums in the same loop:
for(int count = 0; count < k; count++){
diagSum += grid[startX][startY];
antiDiagSum += grid[endX][startY];
startX++, startY++, endX--;
}
I have tried to create a C++ program to solve Project Euler's 8th problem. However, my program is not outputting the correct answer. I have tried to trace through it, but I can't locate my logical error.
Project Euler's 8th problem is about finding the value of the highest product of thirteen adjacent digits in a number with 1000 digits.
My code outputs 9223372019204292608 as the answer. The correct answer is I believe 23514624000.
My code is the following :
#include <iostream>
#include <cassert>
using namespace std;
int main() {
//Declare input number as a string. Declare variables
string input = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
char initialArray[1000];
int finalArray[1000];
long products[987];
long highestProduct = 0L;
//Divide input string into an array of single characters
for(int i = 0; i < 1000 ; i++){
initialArray[i] = input.at(i);
}
//Translate the array of characters into an array of single-digit integers
for(int i = 0; i < 1000 ; i++){
finalArray[i] = input.at(i) - '0';
}
//Initialize each element in the products array to 1
for (int i = 0; i < 100 ; i++){
products[i] = 1L;
}
//Perform multiplications
for(int i = 0; i < 987; i++){
for( int j = 0; j < 13; j++){
products[i] = products[i] * finalArray[j+i];
}
}
for(int i = 0; i < 987; i++){
if (products[i] > highestProduct){
highestProduct = products[i];
}
}
cout << "The highest product of 13 adjacent digits from the input is: " << highestProduct << endl;
return 0;
}
//Correct answer is supposed to be 23514624000
You are not initializing all of the products array. Ideally you shouldn't be initializing them separately at all.
//Perform multiplications
for(int i = 0; i < 987; i++)
{
products[i] = 1L; // initialize
for( int j = 0; j < 13; j++)
{
products[i] = products[i] * finalArray[j+i];
}
}
This way, you can't go wrong with initializing all the elements.
Look here:
//Initialize each element in the products array to 1
for (int i = 0; i < 100 ; i++){
Also note you can use the only loop through array using update of product at every step like this:
product = (product / finalArray[i - 13]) * finalArray[i]
I'm trying to take the product of all of the diagonal numbers in a 4x4 array. I know how to grab the numbers and print them, but I'm not sure how to take the product of them, how would I make it calculate the product of the 8 numbers?
#include <iostream>
using namespace std;
for (int row = 0; row < 4; row++)
{
for (int column = 0; column < 4; column++)
{
if (row==column || row == 3 - column)
{
double product = 1;
product *= arr[row][column]
cout << product << ".";
}
}
}
Note:
There are only 7 diagonal elements. You are counting the element in the centre of the matrix twice.
you don't need to iterate the whole array in order to know about the diagonals. The diagonals have a nice property of row == column as you have observed and you only need to iterate along the diagonals.
To make things clearer and easier, calculate the two diagonal products separately:
double product = 1;
for (int row = 0; row < 4; row++) {
product *= arr[row][row]
}
for (int row = 0; row < 4; row++) {
product *= arr[row][4 - (row + 1)]
}
If you consider both entries in each row at a time, you'll have to also account for the fact that the middle element appears in both diagonals which makes the code unnecessarily messy.
why you are defining the variable product inside the loop,thats why the previous data stored in the variable is lost when it goes out of scope.
#include <iostream>
using namespace std;
double product = 1; // var product should be defined out of the loop
for (int row = 0; row < 4; row++)
{
for (int column = 0; column < 4; column++)
{
if (row==column || row == 3 - column)
{
product *= arr[row][column];
}
}
}
cout << product << ".";
I am asked to find the largest product of 4 adjacent numbers horizontally, diagonally, or vertically, in a 20x20 grid for project euler problem 11. The grid can be found here:http://projecteuler.net/problem=11.
I could not find a more efficient approach than to loop over the entire array 4 times. I made a variable max that was initially set equal to 0. I then looped over the array horizontally, and found the products. If a product was greater than max, max was set to that product, etc. I did this for all 4 loops. However, my answer is wrong, and probably too big.
#include <iostream>
using namespace std;
int main () {
int twenty_grid[20][20] =
{
{ 8, 2, 22, /* data elided since the question links to it */ },
…
}
int max = 0;
// Pass 1: This determines the greatest element horizontally
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 17; ++j) {
// j stops at 17 to avoid a segmentation fault.
int n = twenty_grid[i][j] *
twenty_grid[i][j+1] *
twenty_grid[i][j+2] *
twenty_grid[i][j+2] *
twenty_grid[i][j+3];
if (n > max)
max = n;
}
}
// Now we do the same loop, except we do i + 1, i + 2, etc,
// rather than j +1, j+2. This does it vertically. Pass 2:
for (int i = 0; i < 17; ++i) {
for (int j = 0; j < 20; ++j) {
int n = twenty_grid[i][j] *
twenty_grid[i+1][j] *
twenty_grid[i+2][j] *
twenty_grid[i+3][j];
if (n > max) {
max = n;
}
}
}
// Finally, we increment both i and j to get the diagonals.
for (int i = 0; i < 17; ++i) {
for (int j = 0; j < 20; ++j) {
int n = twenty_grid[i][j] *
twenty_grid[i+1][j+1] *
twenty_grid[i+2][j+2] *
twenty_grid[i+3][j+3];
if (n > max) {
max = n;
}
}
}
// For diagonals, 2 passes are needed to account for both directions.
for (int i = 0; i < 17; i++) {
for (int j = 3; j < 20; j++) {
int n = twenty_grid[i][j] *
twenty_grid[i + 1][i -1] *
twenty_grid[i + 2][i -2] *
twenty_grid[i + 3][i -3];
if (n > max)
max = n;
}
}
cout << max << endl;
return 0;
}
To take a look at why my answer was constantly wrong, I began to print out each individual product as it was calculated. To my surprise, many of them were negative. After checking my loops, it doesn't seem like they access any data out of the array. Could someone lead me in the right direction for fixing this code?
I found several problems.
The first block of code multiplies twenty_grid[i][j+2] twice.
In the third block of code the end condition for the inner loop should be j < 17.
The last block of code uses i as an array index instead of j in three places.
It produces the correct answer after fixing these issues.
I am currently using the following code to get the current row and column of an element in a 2D int array:
const int num_rows = 5;
const int num_columns = 7;
int a[num_rows][num_columns];
int *p = &a[2][4];
int row = (p - &a[0][0]) / num_columns;
int col = (p - &a[row][0]);
This works fine but now I need to change the code to take the number of rows and columns as a parameter. As far as I know, this means I need to create the 2D array dynamically:
int** ary = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
ary[i] = new int[sizeY];
If I create the 2D array this way, the above code to find the row/column breaks. What can I do?
int *ary = new int [sizeX * sizeY]; // allocate memory for the 2d array
for(int i = 0; i < sizeX; ++I)
for(j = 0; j < sizeY; ++j)
ary[i * sizeY + j] = 0;
// to get the value of collumn c and row r: use ary[c * sizeY + r];
int row = (p - &a[0][0]) / num_columns;
int col = (p - &a[row][0]);
It's a very good idea to stay way from pointer arithmetic. Don't do this! You are essentially subtracting the pointer and divide that number by num_columns, and that number will be random.
If you want to get the row/column of an element, search the array one element at a time.
for(int row=0; row<num_rows; ++row) {
for(int column=0; column<num_columns; ++column) {
if (a[row][column] == element) {
// we got it!
}
}
}