I am trying to print the right hemisphere of a matrix. If we draw the main and the secondary diagonals in a matrix we see that we got 4 equal parts, the right part is called (in my algorithms textbook) the right hemisphere of a square matrix.
For example, in the following 5 x 5 matrix, the right hemisphere is made of the elements: -1, -3, -2, 0.
The way I have tried to solve this problem is by starting and composing half of the secondary diagonal and then print each element on the right of the element on the left diagonal. After I reach the middle of the secondary diagonal I repeat this process on the lower part of the main diagonal.
Something like that (at least, this is how I see it in my head):
Here is some working code that prints the right hemisphere of a 5 x 5 matrix. It works, but it is ugly and it doesn't work properly of matrices that have even number of lines and columns, for example a 4 x 4 matrix.
#include <iostream>
#define N 5
#define M 5
void printHemisphere(int matrix[N][M], int n, int m)
{
int i = 1;
for(int j = n - 1; j > n / 2; i++, j--)
{
for (int k = j + 1; k < m; ++k)
{
std::cout << matrix[i][k] << " ";
}
std::cout << std::endl;
}
for(int j = n / 2; j < n; i++, j++)
{
for (int k = j + 1; k < m; ++k)
{
std::cout << matrix[i][k] << " ";
}
std::cout << std::endl;
}
}
int main(int argc, char const *argv[])
{
int matrix5[N][M] =
{
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15},
{16, 17, 18, 19, 20},
{21, 22, 23, 24, 25}
};
printHemisphere(matrix5, N, M);
return 0;
}
How would you approach this problem?
I think this should work for square matrices:
void printHemisphere(int matrix[N][M], int n, int m)
{
int mid = n / 2;
for(int i = 1; i < mid; i++)
{
for (int j = n - i; j < m; ++j)
{
std::cout << matrix[i][j] << " ";
}
std::cout << std::endl;
}
for(int i = mid; i < n - 1; i++)
{
for (int j = i + 1; j < m; ++j)
{
std::cout << matrix[i][j] << " ";
}
std::cout << std::endl;
}
}
The outer loops skip the first and last rows because no output can come from them.
This is a way to get out with just a double for loop:
void printHemisphere(int matrix[N][M], int n, int m)
{
for(int i = 1; i < n - 1 ; i++)
{
for (j = max(i, n - i) ; j < m ; j++)
{
std::cout << matrix[i][k] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
In pseudo-code... :
for row in 1 -> height - 2 // Indices between 0 -> height - 1
distance = min(row, height - 1 - row)
for cell in (width - distance) -> width - 1
print matrix[row][cell]
Here's my take on it. I am coming a little late, as you have already accepted a solution; still, I would like to show you some things. For example, that if you treat these matrices as monodimensional arrays you can test matrices of all sizes with just one function, because the size doesn't have to be "built into" the data type in your function definition. And I have commented it a lot, hoping to make it as clear as possible.
#include <iostream>
#include <algorithm>
// I store matrices as a monodimensional array, so that it is easier to deal
// with matrices of different sizes in the same program, because you can do
// everything with one function. Moreover, I use only one argument here, to make
// it clear that we are dealing with square matrices.
void printHemisphere(int* matrix, int last_row)
{
int last_column = last_row; // It's a square matrix, so they are the same.
// Still, distinguishing between last_column
// and last_row can make the algorithm clearer,
// so I have kept both
// In general I prefer to use "row" and "column" as variable names, instead
// of "i" and "j"
// Our rows go from 0 to last_row-1, but since the first and last one can
// certainly not be used, we can skip them: we start at row = 1, and we stop
// at last_row - 2 (that is, the last one for which row < last_row - 1)
for(int row = 1; row < last_row - 1 ; row++)
{
// We want to start from the cell to the right of the rightmost diagonal.
// The main diagonal has column = row;
// The secondary diagonal has column = last_row - 1 - row
// The rightmost one is the maximum of these 2.
// Then, we want to take the cell to the right of the diagonal, so we
// have to add 1 more.
// All in all we have:
for (int column = std::max(row, last_row - 1 - row) + 1;
column < last_column;
column++)
{
// since this is a 1-D array we have to access it this way
std::cout << matrix[row*last_row+column] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
int main(int argc, char const *argv[])
{
// Since I am working with monodimensional arrays, I don't store them as
// int matrix3[3][3], but rather as int matrix3[9], which I have expressed as
// int matrix3[3*3] for clarity.
//For each one I have indicated the expected output.
// Expected output:
// 6
int matrix3[3*3] =
{
1, 2, 3,
4, 5, 6,
7, 8, 9
};
// Expected output:
// 8
// 12
int matrix4[4*4] =
{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16
};
// Expected output:
// 10
// 14 15
// 20
int matrix5[5*5] = {
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
21, 22, 23, 24, 25
};
// Expected output:
// 12
// 17 18
// 23 24
// 30
int matrix6[6*6] = {
1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36
};
// Expected output:
// 14
// 20 21
// 26 27 28
// 34 35
// 42
int matrix7[7*7] = {
1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49
};
printHemisphere(matrix3, 3);
printHemisphere(matrix4, 4);
printHemisphere(matrix5, 5);
printHemisphere(matrix6, 6);
printHemisphere(matrix7, 7);
return 0;
}
I have verified it on ideone and it works. The only thing I would like to add is: to make sure the code works, make sure you test it with an odd-sized and with an even-sized matrix.
Related
Question:
Using the following unfinished function (finish it), call it in the main function with an anonymous lambda function as a parameter and print all numbers that are NOT divisible by 2, 3 and 5.
vector<int> izdvoji(vector<int>& x, function<bool(int)> kriterij);
int main()
{
vector<int> brojevi = { 1, 4, 5, 7, 3, 6, 12, 65, 32, 8, 87, 55, 23, 22, 1, 1, 433, 66, 7, 433, 3, 32, 76, 8, 72, 256, 42 };
vector<int> rez = izdvoji(brojevi, /*lambda function*/);
for (int i = 0; i < rez.size(); i++)
cout << rez[i] << " ";
//output: 1 7 23 1 1 433 7 433
return 0;
}
My Answer:
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <iterator>
#include <functional>
using namespace std;
//2 3 5 djeljivvost
vector<int> izdvoji(vector<int>& x, function<bool(int)> kriterij) {
vector<int> rez;
for (int i = 0; i < x.size(); i++) {
if (kriterij(x[i])) {
rez.push_back(x[i]);
}
}
return rez;
}
int main()
{
vector<int> brojevi = { 1, 4, 5, 7, 3, 6, 12, 65, 32, 8, 87, 55, 23, 22, 1, 1, 433, 66, 7, 433, 3, 32, 76, 8, 72, 256, 42 };
vector<int> rez = izdvoji(brojevi, [](int x)->bool {
return !(x % 2 || x % 3 || x % 5);
});
for (int i = 0; i < rez.size(); i++)
cout << rez[i] << " ";
//output: 1 7 23 1 1 433 7 433
return 0;
}
When I compile it, it says there are no issues found, but also it informs me from the build output (VS 2019) that there is a signed/unsigned mismatch in my for loops, and it doesn't print anything. I have no clue why.
Your condition is wrong. Try for example 31, which is not divisible by 2, 3 or 5:
return !(31 % 2 || 31 % 3 || 31 % 5);
return !( 1 || 1 || 1 );
return !( true );
return false;
Check divisiblity by x % n == 0:
return !(x % 2 == 0 || x % 3 == 0 || x % 5 == 0);
For the warning about unsigned vs signed comparison, you need to consider that size() returns an unsigned value. Use size_t as the type of the loop counter.
This code has been developed to solve a wooden puzzle problem that I found at a thrift shop, which has numerous wooden wheels inscribed with numbers. These wheels have for the purposes of this program been translated to a two-dimensional matrix, with some additional rules describing the bounds of their relative movement.
The calculational part of the code is working. The configuration layouts that I am receiving from the console are valid within the physical and mathematical bounds of the puzzle. However, there should only be 16^4 possible configurations, and after over 75,000 iterations, each of which being unique (insofar as I can look at what literally approaches a million lines of output), there is still no valid solution.
How could I be missing one?
Bottom line, the rows need to stay ordered in the same sequence, but can be shifted ("rotated") by any number of spaces, though 16 shifts of one space each covers the entire rotary layout of each wheel.
A wheel consists of two concentric radial sets of numbers, some having spaces (null values, but indicated in this code as an "N", and the out set of numbers on a wheel above overlaps the inner set of numbers on a wheel below, such that rows one and two are one wheel (the one that remains mathematically stationary because all other wheels can move relative to it), rows three and four are one wheel (dial is probably a more apt term), hence the turnDial() function is called for two rows of numbers at the same time-ish, except for the final row, which is an independent dial with only one set of values, half of them null (indicative of an open space on the physical wheel, wherin the number on the wheel below it would be the value on the "data_Output" array, representative of the actual physical layout of the dials when stacked according to factory configuration. This sorting out as to whether a value comes from a wheel above or a wheel below is done in checkSum(), which also generates a sum for each column to compare to the required solution (that the numbers of each column must add up to "50" for the puzzle to be solved), and outputs a sum of those sums which on any valid solution would equal 800 (50 * 16) columns, and makes for an easy narrowing down of whether a solution is valid (if there weren't 100,000 of them to sort through).
Anyway, it runs. It outputs data, I just don't see it ever outputting a valid solution, so I'm probably missing something. Wits end. Help would be appreciated.
Console Screen Grab
Pictures of the Puzzle
#include "pch.h"
#include <iostream>
using namespace System;
using namespace std;
using namespace System::IO;
const int depth = 9; // (ROWS)
const int length = 16; // (COLUMNS)
int target_Column_Total = 50;
int The_Grail[length] = { 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50 };
int Sum[16];
int sum_Total;
long int Iteration;
int data_Input[depth][length] =
{ {16, 4, 7, 0, 16, 8, 4, 15, 7, 10, 1, 10, 4, 5, 3, 15},
{2, 9, 27, 13, 11, 13, 10, 18, 10, 10, 10, 10, 15, 7, 19, 18},
{ 6, 'N', 10, 'N', 8, 'N', 10, 'N', 9, 'N', 8, 'N', 8, 'N', 9, 'N'},
{ 5, 1, 24, 8, 10, 20, 7, 20, 12, 1, 10, 12, 22, 0, 5, 8 },
{ 0, 'N', 11, 'N', 8, 'N', 8, 'N', 8, 'N', 10, 'N', 11, 'N', 10, 'N' },
{ 20, 8, 19, 10, 15, 20, 12, 20, 13, 13, 0, 22, 19, 10, 0, 5 },
{ 14, 'N', 11, 'N', 8, 'N', 12, 'N', 11, 'N', 3, 'N', 8, 'N', 10, 'N' },
{ 8, 17, 4, 20, 4, 14, 4, 5, 1, 14, 10, 17, 10, 5, 6, 18 },
{ 8, 'N', 16, 'N', 19, 'N', 8, 'N', 17, 'N', 6, 'N', 6, 'N', 8, 'N' } };
int data_Output[5][length];
void checkSum();
void turnDial(int x);
void main()
{
while (true) {
for (int i = 0; i < length; i++) {
turnDial(2);
turnDial(3);
checkSum();
for (int j = 0; j < length; j++) {
turnDial(4);
turnDial(5);
checkSum();
for (int k = 0; k < length; k++) {
turnDial(6);
turnDial(7);
checkSum();
for (int l = 0; l < length; l++) {
turnDial(8);
checkSum();
}
}
}
}
}
}
void checkSum() {
Iteration++;
for (int i = 0; i < 5; i++) {
for (int j = 0; j < length; j++) {
if (i == 0) {
data_Output[i][j] = data_Input[i][j];
}
if (i == 1) {
if (data_Input[2][j] != 'N') {
data_Output[i][j] = data_Input[2][j];
}
else {
data_Output[i][j] = data_Input[1][j];
}
}
if (i == 2) {
if (data_Input[4][j] != 'N') {
data_Output[i][j] = data_Input[4][j];
}
if (data_Input[4][j] == 'N') {
data_Output[i][j] = data_Input[3][j];
}
}
if (i == 3) {
if (data_Input[6][j] != 'N') {
data_Output[i][j] = data_Input[6][j];
}
if (data_Input[6][j] == 'N') {
data_Output[i][j] = data_Input[5][j];
}
}
if (i == 4) {
if (data_Input[8][j] != 'N') {
data_Output[i][j] = data_Input[8][j];
}
if (data_Input[8][j] == 'N') {
data_Output[i][j] = data_Input[7][j];
}
}
}
}
cout << "Data:" << "\n\n";
for (int x = 0; x < depth; x++) {
for (int y = 0; y < length; y++) {
cout << data_Input[x][y] << "\t";
}
cout << endl;
}
cout << endl;
cout << "Orienation:" << "\n\n";
for (int x = 0; x < 5; x++) {
for (int y = 0; y < length; y++) {
cout << data_Output[x][y] << "\t";
}
cout << endl;
}
cout << "\n";
for (int y = 0; y < 5; y++) {
for (int x = 0; x < length; x++) {
if (y == 0) {
Sum[x] = 0;
}
Sum[x] += data_Output[y][x];
if (y == (4)) {
cout << Sum[x] << "\t";
}
}
}
sum_Total = { 0 };
for (int i = 0; i < length; i++) {
sum_Total += Sum[i];
}
cout << " Sum: " << sum_Total;
cout << "\t#: " << Iteration << "\n\n";
if (Sum != The_Grail) {
cout << "NO DICE." << "\n\n";
}
if (Sum == The_Grail) {
cout << "SUCCESS!" << "\n\n";
exit(888);
}
// int Sum[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
}
void turnDial(int x) {
int holder = data_Input[x][(length - 1)];
for (int i = (length - 1); i > 0; i--) {
data_Input[x][i] = data_Input[x][i - 1];
}
data_Input[x][0] = holder;
}
I haven't dug through everything in detail, but the final comparisons (Sum == The_Grail) will always fail as this is comparing two array pointers not (as one might reasonably expect) each value in the arrays. I would start by looping through the arrays, comparing each element.
Also, are you sure the input data is guaranteed to result in a solution? In other words, is the input data known to be good data or is it just random?
Finally!
Pstephan, thanks for your help, nailed it on iteration 58344.
I currently have an iterator that randomly increments through a vector, I want to be able to return back to the top of the vector once the end has been reached. I have a seed placed in my random generator so I have the same sequence. Obviously at the moment the vector just goes out of scope
int main()
{
vector<int> vectorTest = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20};
vector <int>::iterator it;
for (it = vectorTest.begin(); it != vectorTest.end(); it = it + rand() % 6)
{
cout << *it << endl;
}
}
This is a not a use case for iterator. I suggest using common indexing bounded by modulo of vector length.
int j = 0;
for (int i = 0; j < 20 ; i = (i + rand() % 6) % vectorTest.size(), j++) {
cout << vectorTest[i] << endl;
}
You could use ranges::view::cycle to repeat the vector elements indefinitely.
int main()
{
std::vector<int> vectorTest = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
auto repeating = vectorTest | ranges::view::cycle;
for (auto it = repeating.begin(); /* how to end? */; it = it + rand() % 6)
{
std::cout << *it << std::endl;
}
}
I'm attempting to cout the elements of input array "arr" that was used to determine max sum of a subarray, hereinafter named "maxSum" (which is determined elsewhere, and confirmed to be correct). The function showSubArray() accepts as parameters the array arr, the length of the array n, and maxSum. Input array is positive and negative ints. Below is a set of test arrays with the result. Fail means that arr[0] is printed to the screen with a space separating them INFINITELY. I can't see any discernable pattern in the input that would cause this. Any help greatly appreciated and I am not beholden to the unordered_map approach. Getting the indices from the function that determined the maxSum is not an acceptable solution.
#include <unordered_map>
#include <iostream>
using std::cout;
int main() {
//int arr[] = { 1, 4, -9, 8, 1, 3, 3, 1, -1, -4, -6, 2, 8, 19, -10, -11 };
// runs ok, inputs: n=16, maxSum = 34
//int arr[] = { 2, 9, 8, 6, 5, -11, 9, -11, 7, 5, -1, -8, -3, 7, -2 };
// ***fails, inputs: n=15, maxSum = 30
//int arr[] = { 10, -11, -1, -9, 33, -45, 23, 24, -1, -7, -8, 19 };
// runs ok, n=12, maxSum = 50
//int arr[] = { 31, -41, 59, 26, -53, 58, 97, -93, -23, 84 };
// runs ok n=10 maxSum = 187
//int arr[] = { 3, 2, 1, 1, -8, 1, 1, 2, 3 };
// ***fails, inputs: n=9 maxSum = 7
int arr[] = { 12, 99, 99, -99, -27, 0, 0, 0, -3, 10 };
// ***fails, n=10 maxSum = 210
//int arr[] = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
// runs ok, inputs: n=9 maxSum = 6
showSubArray(arr, n, maxSum);
return 0;
}
void showSubArray(int arr[], int n, int maxSum) {
std::unordered_map<int, int> aMap;
int accumulator = 0;
for (int i = 0; i < n; i++) {
accumulator += arr[i];
if (accumulator == maxSum) {
for(int j = 0; j <= i; j++) {
// ACB found error here ^ (I had it as "i")
cout << arr[j];
cout << " ";
}
cout << '\n';
return;
}
if (aMap.find(accumulator - maxSum) != aMap.end()) {
for (int j = aMap[accumulator - maxSum] + 1; j <= i; j++) {
cout << arr[j];
cout << " ";
}
cout << '\n';
return;
}
aMap[accumulator] = i;
}
cout << "Subarray not found!\n";
}
if (accumulator == maxSum) {
for(int j = 0; j <= i; i++) {
you are incrementing i here but you want to increment j cause 0 will always be smaller i for i > 0 until it overflows
Let's say I have this array:
int oldv[10] = {16, 12, 24, 96, 45, 22, 18, 63, 47, 56};
and another one like
int newv[8];
and I want to fill new from alternating ends of old until a certain condition is met such that I'd have:
newv = [16, 56, 12, 47, 24, 63 ...]
Let's say I want to put in new only 3 numbers taken from old (that is: 16, 56, 12).
I've tried with the following for loop, but of course is not enough...
for(int i = 0; i < 3; i++)
newv[i] = oldv[i*(sizeof(oldv)-1)];
Any help?
int _old[10] = {16, 12, 24, 96, 45, 22, 18, 63, 47, 56};
int _new[8];
const int old_size = sizeof(_old)/sizeof(int);
const int new_size = sizeof(_new)/sizeof(int);
for (int i = 0; i < new_size; ++i)
{
if (i % 2)
_new[i] = _old[old_size - i / 2 - 1];
else
_new[i] = _old[i / 2];
std::cout << _new[i] << " ";
}
std::cout << std::endl;
Returns 16 56 12 47 24 63 96 18
See it live
Enjoy.
#include <algorithm>
#include <iostream>
#include <iterator>
using namespace std;
int main(int, char**)
{
int oldv[] = { 16, 12, 24, 96, 45, 22, 18, 63, 47, 56 };
int newv[8];
size_t numbers_i_want = 3;
size_t oldv_b = 0;
size_t oldv_e = sizeof oldv / sizeof *oldv;
size_t newv_e = sizeof newv / sizeof *newv;
for(size_t i = 0;
i != min(numbers_i_want, newv_e) && oldv_b != oldv_e;
++i)
{
newv[i] = (i % 2) ? oldv[--oldv_e] : oldv[oldv_b++];
}
copy(newv, newv + min(numbers_i_want, newv_e),
ostream_iterator<decltype(*newv)>(cout, " "));
return 0;
}