Simulate Matrix background - c++

I am traying to simulate the the background of Matrix film and I wrote the code below:
#include <iostream>
#include<windows.h>
#include <conio.h>
using namespace std;
void CursorPosition(short x, short y) {
COORD coordScreen = {x, y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coordScreen);
}
void color(int nb) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), nb);
}
int main(int argc, char *argv[]) {
unsigned int y[79];
unsigned int ymin[79];
unsigned int a, b;
char i[36] = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
88, 89, 90};
system("title The Matrix !");
color(10);
for (a = 0; a < 79; a++) {
y[a] = 0;
ymin[a] = 1;
}
do {
for (unsigned int x = 0; x < 79; x++) {
for (unsigned int j = 0; j < 5; j++) {
a = rand() % 79;
if (y[a] != 0) {
b = rand() % y[a] + ymin[a];
if (b < 26) {
if (b < ymin[a] + 2 & b > 2) color(2);
CursorPosition(a + 1, b);
cout << i[rand() % 36];
color(10);
}
}
}
if (y[x] != 0 || (rand() % 50) == 0) {
if ((rand() % (y[x] + 1)) < 20 & ymin[x] == 1) {
y[x]++;
} else {
CursorPosition(x + 1, ymin[x]);
cout << " ";
ymin[x]++;
if (ymin[x] < 25) {
color(2);
CursorPosition(x + 1, ymin[x] + 1);
cout << i[rand() % 36];
color(10);
}
}
if ((y[x] + ymin[x]) < 26) {
CursorPosition(x + 1, y[x] + ymin[x]);
color(15);
cout << i[rand() % 36];
color(10);
}
if ((y[x] + ymin[x]) < 27) {
CursorPosition(x + 1, y[x] + ymin[x] - 1);
cout << i[rand() % 36];
}
}
if (ymin[x] > 25) {
ymin[x] = 1;
y[x] = 0;
}j
}
Sleep(35);
} while (!kbhit());
return 0;
}
Do you have any recommendation to improve the code ?
My purpose is like this:

Your code is not writing those chars. It is writing simple alphabet chars numbers 0-9.
What you need is half-width Kana Characters:
。 「 」 、 ・ ヲ ァ ィ ゥ ェ ォ ャ ュ ョ ッ
ー ア イ ウ エ オ カ キ ク ケ コ サ シ ス セ ソ
タ チ ツ テ ト ナ ニ ヌ ネ ノ ハ ヒ フ ヘ ホ マ
ミ ム メ モ ヤ ユ ヨ ラ リ ル レ ロ ワ ン ゙ ゚
You need boost libraries' boundary part to get these i think.
Some example i found:
boost::locale::generator gen;
using namespace boost::locale::boundary;
std::string text="生きるか死ぬか、それが問題だ。";
ssegment_index map(word,text.begin(),text.end(),gen("ja_JP.UTF-8"));
for(ssegment_index::iterator it=map.begin(),e=map.end();it!=e;++it) {
std::cout << "Segment " << *it << " contains: ";
if(it->rule() & word_none)
std::cout << "white space or punctuation marks ";
if(it->rule() & word_kana)
std::cout << "kana characters ";
if(it->rule() & word_ideo)
std::cout << "ideographic characters";
std::cout<< std::endl;
}
output:
Segment 生 contains: ideographic characters
Segment きるか contains: kana characters
Segment 死 contains: ideographic characters
Segment ぬか contains: kana characters
Segment 、 contains: white space or punctuation marks
Segment それが contains: kana characters
Segment 問題 contains: ideographic characters
Segment だ contains: kana characters
Segment 。 contains: white space or punctuation marks
Source

Related

How to use data from array for math equations and terminal display? C++

Complete beginner to C++
Having trouble using data from a primitive array in other places. Do i just call them as if they are integers in the math and display output lines? Making a simple Fahrenheit to Celsius converter program.
#include <iostream>
#include <array>
int main() {
//Display name of program
std::cout << "Farenheit to Celsius Converter";
//Temperature array
int temp[] = {51, 42, 46, 36, 46, 33, 47, 34, 48, 36, 46, 34, 45, 36};
//Math stuff
int temp1 = temp[1] - 32 * .5556;
int temp2 = temp[2] - 32 * .5556;
int temp3 = temp[3] - 32 * .5556;
int temp4 = temp[4] - 32 * .5556;
int temp5 = temp[5] - 32 * .5556;
int temp6 = temp[6] - 32 * .5556;
int temp7 = temp[7] - 32 * .5556;
int temp8 = temp[8] - 32 * .5556;
int temp9 = temp[9] - 32 * .5556;
int temp10 = temp[10] - 32 * .5556;
int temp11 = temp[11] - 32 * .5556;
int temp12 = temp[12] - 32 * .5556;
int temp13 = temp[13] - 32 * .5556;
int temp14 = temp[14] - 32 * .5556;
//Display output
std::cout << temp1"," << temp2"," << temp3"," << temp4"," << temp5"," << temp6"," << temp7"," << temp8"," << temp9"," << temp10"," << temp11"," << temp12"," << temp13"," << temp14",";
return 0;
}
I suggest that you use the standard std::transform algorithm to transform the array. You can then create a function or functor (like a lambda) for converting from Fahrenheit to Celcius and supply that to std::transform.
Example:
#include <algorithm> // std::transform
#include <iostream>
#include <iterator> // std::begin, std::end
int main() {
int temp[] = {51, 42, 46, 36, 46, 33, 47, 34, 48, 36, 46, 34, 45, 36};
// a lambda for the conversion:
auto F2C = [](int F) { return (F - 32) * 5 / 9; };
std::transform(std::begin(temp), std::end(temp), std::begin(temp), F2C);
for (int v : temp) std::cout << v << '\n';
}
Demo
In C++ use vector for an array with flexible size.
To get a good conversion use floating point numbers.
And repeated calculations should really be functions.
use range based for loops where you can, to avoid index problems
#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
double fahrenheid_to_celcius(const double t)
{
return (t - 32.0) * .55556;
}
int main()
{
//Display name of program
std::cout << "Farenheit to Celsius Converter\n";
//Temperature array
std::vector<double> temperatures{ 51.0, 42.0, 46.0, 36.0, 46.0, 33.0, 47.0, 34.0, 48.0, 36.0, 46.0, 34.0, 45.0, 36.0 };
// convert temperatures one by one (using a range based for loop)
// double& is a reference to one of the temperatures in the vector, so the value can be changed within the loop
for (double& temperature : temperatures)
{
temperature = fahrenheid_to_celcius(temperature);
}
bool comma = false;
for (const double& temperature : temperatures)
{
if (comma) std::cout << ", ";
std::cout << temperature;
comma = true;
}
return 0;
}
First: I recommended using the std::array, instead of the C-array:
const size_t tempValues = 14;
std::array<int, tempValues> temp = {51, 42, 46, 36, 46, 33, 47,
34, 48, 36, 46, 34, 45, 36};
Second: you can operate via a for loop directly on the values. You don't have to write 14 variables:
for (size_t i = 0; i < tempValues; i++) {
temp[i] = (temp[i]-32) * .5556;
}
Prining to the output goes similarly:
for (size_t i = 0; i < tempValues - 1; i++) {
std::cout << temp[i] << ", ";
}
std::cout << temp[tempValues - 1] << std::endl;
Note that the loop ends with the second last value, because we do not need for the last value a comma separator.
This isn't the most elegant way, but probably the most beginner-friendly.

Finding the most divisible number in a 100,000 range

I'm a student in the 10th grade and our teacher assigned some exercises. I'm pretty advanced in my class but one exercise is just isn't coming together as I want. The exercise is as follows:
Given the numbers between 100,000 and 200,000, find the number with the most divisors (as in which number can be divided with the most numbers, any number).
I wrote something but it executes in 32 seconds(!) and I just can't figure out the logic behind it (I can't even check if the answer is correct).
This is the code that I wrote:
void f3() {
int mostcount = 0, most, divisors = 0;
for (int i = 100000; i <= 200000; i++) {
for (int j = 1; j<=i/2; j++) {
if (i % j == 0) {
divisors++;
}
}
if (divisors > mostcount) {
mostcount = divisors;
most = i;
}
divisors = 0;
}
cout << most << endl;
return;
}
The output:
166320
Edit: My question is how can I reduce the runtime?
I'd be really thankful if you could explain your answer if you do decide to help, instead of just saying that I could do this with an XYZ type binary tree.
Since you tagged this with performance...
You can find all the prime factors of your input value (and the number of times they occur), and calculate the number of ALL divisors by multiplying those counts+1. This example cut the time by almost 5 times!
void f() {
int mostcount = 0, most = 0;
for (int i = 100000; i <= 200000; i++) {
int divisors = 1;
int x = i;
int limit = sqrt(i);
int count = 0;
for (int j = 2; j <= limit; j++) {
int count = 0;
while (x % j == 0) {
count++;
x /= j;
limit = sqrt(x);
}
divisors *= count + 1;
if (j > 2)
++j;
}
if (x > 1)
divisors *= 2;
if (divisors > mostcount) {
mostcount = divisors;
most = i;
}
}
cout << most << ", " << mostcount << endl;
return;
}
If you find a list of prime numbers, you can cut that time in half:
static vector<int> primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,
83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449 };
void f() {
int mostcount = 0, most;
for (int i = 100000; i <= 200000; i++) {
int divisors = 1;
int x = i;
int limit = sqrt(i);
for (int j: primes) {
if (j > limit) break;
int count = 0;
while (x % j == 0) {
count++;
x /= j;
}
limit = sqrt(x);
divisors *= count + 1;
}
if(x > 1)
divisors *= 2;
if (divisors > mostcount) {
mostcount = divisors;
most = i;
}
}
cout << most << ", " << mostcount << endl;
return;
}
Explanation: let's take 166320. It's prime factors are:
2 (4 times)
3 (3 times)
5 (once)
7 (once)
11 (once)
Here, 2 produces 5 combination (it may go into the divisor 0 to 4 times), 3 - 3 combinations, and so on.
So you get 5 * 4 * 2 * 2 * 2 = 160 divisors. Strictly speaking, you should add one more - the input number itself.
Using #AhmedAEK 's response:
replace j<=i/2 with j<=sqrt(i), you only need to loop up to that, also #include <math.h> at the top, you also need to multiply the total divisors by 2, since there is a number above the sqrt that reflects the number below the sqrt. ie: 1000 is 10 x 100.
void f3() {
int mostcount = 0, most, divisors = 0;
for (int i = 100000; i <= 200000; i++) {
for (int j = 2; j<=sqrt(i); j++) {
if (i % j == 0) {
divisors++;
}
}
if (divisors > mostcount) {
mostcount = divisors;
most = i;
}
divisors = 0;
}
cout << most << endl;
return;
}

Hole-Filling Filter in OpenCV C++

I have a basic implementation of hole-filling filter as shown below:
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char** argv)
{
// please note that the depthImg is (720 x 576) 8UC1
// let's make a smaller one for testing
uchar flatten[6 * 8] = { 140, 185, 48, 235, 201, 192, 131, 57,
55, 87, 82, 0, 6, 201, 0, 38,
6, 239, 82, 142, 46, 33, 172, 72,
133, 0, 232, 226, 66, 59, 10, 204,
214, 123, 202, 100, 0, 32, 6, 147,
105, 191, 50, 21, 87, 117, 118, 244};
cv::Mat depthImg = cv::Mat(6, 8, CV_8UC1, flatten);
// please ignore the border pixels in this case
for (int i = 1; i < depthImg.cols - 1; i++) {
for (int j = 1; j < depthImg.rows - 1; j++) {
unsigned short sumNonZeroAdjs = 0;
uchar countNonZeroAdjs = 0;
if (depthImg.at<uchar>(j, i) == 0) {
uchar iMinus1 = depthImg.at<uchar>(j, i - 1);
uchar iPlus1 = depthImg.at<uchar>(j, i + 1);
uchar jMinus1 = depthImg.at<uchar>(j - 1, i);
uchar jPlus1 = depthImg.at<uchar>(j + 1, i);
if (iMinus1 != 0) {
sumNonZeroAdjs += iMinus1;
countNonZeroAdjs++;
}
if (iPlus1 != 0) {
sumNonZeroAdjs += iPlus1;
countNonZeroAdjs++;
}
if (jMinus1 != 0) {
sumNonZeroAdjs += jMinus1;
countNonZeroAdjs++;
}
if (jPlus1 != 0) {
sumNonZeroAdjs += jPlus1;
countNonZeroAdjs++;
}
depthImg.at<uchar>(j, i) = sumNonZeroAdjs / countNonZeroAdjs;
}
}
}
std::cout << depthImg << std::endl;
return 0;
}
// prints the following:
[140, 185, 48, 235, 201, 192, 131, 57;
55, 87, 82, 116, 6, 201, 135, 38;
6, 239, 82, 142, 46, 33, 172, 72;
133, 181, 232, 226, 66, 59, 10, 204;
214, 123, 202, 100, 71, 32, 6, 147;
105, 191, 50, 21, 87, 117, 118, 244]
The above filter computes an average of adjacent pixels to fill the 0 pixels. The output from this implementation is satisfactory. However, as we can see, the above prototype is not elegant and painfully slow.
I am looking for a similar logic (using adjacent pixels to fill 0 pixels) but faster (execution time) hole-filling filter inbuilt in OpenCV
PS: I am using OpenCV v4.2.0 on Ubuntu 20.04 LTS.
Update 1
Based on the suggestions, I designed pointer style access. Complete code is shown below:
#include <iostream>
#include <opencv2/opencv.hpp>
void inPlaceHoleFillingExceptBorderPtrStyle(cv::Mat& img) {
typedef uchar T;
T* ptr = img.data;
size_t elemStep = img.step / sizeof(T);
for (int i = 1; i < img.rows - 1; i++) {
for (int j = 1; j < img.cols - 1; j++) {
T& curr = ptr[i * elemStep + j];
if (curr != 0) {
continue;
}
ushort sumNonZeroAdjs = 0;
uchar countNonZeroAdjs = 0;
T iM1 = ptr[(i - 1) * elemStep + j];
T iP1 = ptr[(i + 1) * elemStep + j];
T jM1 = ptr[i * elemStep + (j - 1)];
T jP1 = ptr[i * elemStep + (j + 1)];
if (iM1 != 0) {
sumNonZeroAdjs += iM1;
countNonZeroAdjs++;
}
if (iP1 != 0) {
sumNonZeroAdjs += iP1;
countNonZeroAdjs++;
}
if (jM1 != 0) {
sumNonZeroAdjs += jM1;
countNonZeroAdjs++;
}
if (jP1 != 0) {
sumNonZeroAdjs += jP1;
countNonZeroAdjs++;
}
if (countNonZeroAdjs > 0) {
curr = sumNonZeroAdjs / countNonZeroAdjs;
}
}
}
}
void inPlaceHoleFillingExceptBorder(cv::Mat& img) {
typedef uchar T;
for (int i = 1; i < img.cols - 1; i++) {
for (int j = 1; j < img.rows - 1; j++) {
ushort sumNonZeroAdjs = 0;
uchar countNonZeroAdjs = 0;
if (img.at<T>(j, i) != 0) {
continue;
}
T iM1 = img.at<T>(j, i - 1);
T iP1 = img.at<T>(j, i + 1);
T jM1 = img.at<T>(j - 1, i);
T jP1 = img.at<T>(j + 1, i);
if (iM1 != 0) {
sumNonZeroAdjs += iM1;
countNonZeroAdjs++;
}
if (iP1 != 0) {
sumNonZeroAdjs += iP1;
countNonZeroAdjs++;
}
if (jM1 != 0) {
sumNonZeroAdjs += jM1;
countNonZeroAdjs++;
}
if (jP1 != 0) {
sumNonZeroAdjs += jP1;
countNonZeroAdjs++;
}
if (countNonZeroAdjs > 0) {
img.at<T>(j, i) = sumNonZeroAdjs / countNonZeroAdjs;
}
}
}
}
int main(int argc, char** argv) {
// please note that the img is (720 x 576) 8UC1
// let's make a smaller one for testing
// clang-format off
uchar flatten[6 * 8] = { 140, 185, 48, 235, 201, 192, 131, 57,
55, 87, 82, 0, 6, 201, 0, 38,
6, 239, 82, 142, 46, 33, 172, 72,
133, 0, 232, 226, 66, 59, 10, 204,
214, 123, 202, 100, 0, 32, 6, 147,
105, 191, 50, 21, 87, 117, 118, 244};
// clang-format on
cv::Mat img = cv::Mat(6, 8, CV_8UC1, flatten);
cv::Mat img1 = img.clone();
cv::Mat img2 = img.clone();
inPlaceHoleFillingExceptBorderPtrStyle(img1);
inPlaceHoleFillingExceptBorder(img2);
return 0;
}
/*** expected output
[140, 185, 48, 235, 201, 192, 131, 57;
55, 87, 82, 116, 6, 201, 135, 38;
6, 239, 82, 142, 46, 33, 172, 72;
133, 181, 232, 226, 66, 59, 10, 204;
214, 123, 202, 100, 71, 32, 6, 147;
105, 191, 50, 21, 87, 117, 118, 244]
***/
Update 2
Based on the suggestion, the point style code is further improved as shown below:
void inPlaceHoleFillingExceptBorderImpv(cv::Mat& img) {
typedef uchar T;
size_t elemStep = img.step1();
const size_t margin = 1;
for (size_t i = margin; i < img.rows - margin; ++i) {
T* ptr = img.data + i * elemStep;
for (size_t j = margin; j < img.cols - margin; ++j, ++ptr) {
T& curr = ptr[margin];
if (curr != 0) {
continue;
}
T& north = ptr[margin - elemStep];
T& south = ptr[margin + elemStep];
T& east = ptr[margin + 1];
T& west = ptr[margin - 1];
ushort sumNonZeroAdjs = 0;
uchar countNonZeroAdjs = 0;
if (north != 0) {
sumNonZeroAdjs += north;
countNonZeroAdjs++;
}
if (south != 0) {
sumNonZeroAdjs += south;
countNonZeroAdjs++;
}
if (east != 0) {
sumNonZeroAdjs += east;
countNonZeroAdjs++;
}
if (west != 0) {
sumNonZeroAdjs += west;
countNonZeroAdjs++;
}
if (countNonZeroAdjs > 0) {
curr = sumNonZeroAdjs / countNonZeroAdjs;
}
}
}
}
There are three parts: 1) find the zeros, 2) find the mean, and 3) fill the found zeros with mean. So:
/****
* in-place fill zeros with the mean of the surrounding neighborhoods
***/
void fillHoles(Mat gray){
// find the zeros
Mat mask = (gray == 0);
// find the mean with filter2d
Mat kernel = (Mat_<double>(3,3) <<
1/8, 1/8, 1/8
1/8, 0 , 1/8
1/8, 1/8, 1/8
);
Mat avg;
cv::filter2d(gray, avg, CV_8U, kernel)
// then fill the zeros, only where indicated by `mask`
cv::bitwise_or(gray, avg, gray, mask);
}
Note I just realize that this is plainly taking the average, not the non-zero average. For that operation, you might want to do two filters, one for the sum, one for the non-zero counts, then divide the two:
// find the neighborhood sum with filter2d
Mat kernel = (Mat_<double>(3,3) <<
1, 1, 1
1, 0, 1
1, 1, 1
);
Mat sums;
cv::filter2d(gray, sums, CV_64F, kernel);
// find the neighborhood count with filter2d
Mat counts;
cv::filter2d(gray!=0, counts, CV_64F, kernel);
counts /= 255; // because gray!=0 returns 255 where true
// force counts to 1 if 0, so we can divide later
cv::max(counts, 1, counts);
Mat out;
cv::divide(sums, counts, out);
out.convertTo(gray, CV_8U);
#QuangHoang advised a fantastic kernel-based approach. Unfortunately, the result is not matching with the expected output.
Therefore, based on various comments from #CrisLuengo, I managed to design time efficient version of the filter, as shown below:
void inPlaceHoleFillingExceptBorderFast(cv::Mat& img) {
typedef uchar T;
const size_t elemStep = img.step1();
const size_t margin = 1;
for (size_t i = margin; i < img.rows - margin; ++i) {
T* ptr = img.data + i * elemStep;
for (size_t j = margin; j < img.cols - margin; ++j, ++ptr) {
T& curr = ptr[margin];
if (curr != 0) {
continue;
}
T& east = ptr[margin + 1];
T& west = ptr[margin - 1];
T& north = ptr[margin - elemStep];
T& south = ptr[margin + elemStep];
// convert to 0/1 and sum them up
uchar count = static_cast<bool>(north) + static_cast<bool>(south) +
static_cast<bool>(east) + static_cast<bool>(west);
// we do not want to divide by 0
if (count > 0) {
curr = (north + south + east + west) / count;
}
}
}
}

C++ iteration on first and last elements of array

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;
}

Optimization of program used for ProjectEuler problem 11

I've been learning to program for quite a bit and it seems that one of the greatest competitions between programmers is how few lines one can do a procedure in. Noticing this trend, I'd like to learn to make my programs a bit tighter, cleaner, and preferring functionality without excess. Here's the code I used to solve ProjectEuler problem 11. It's quite large which kinda worries me when I see code a fourth of its size doing the same thing, hehe.
#include <iostream>
using namespace std;
int array[20][20] = {{8,2,22,97,38,15,0,40,0,75,4,5,7,78,52,12,50,77,91,8},
{49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,4,56,62,0},
{81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,3,49,13,36,65},
{52,70,95,23,4,60,11,42,69,24,68,56,1,32,56,71,37,2,36,91},
{22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80},
{24,47,32,60,99,3,45,2,44,75,33,53,78,36,84,20,35,17,12,50},
{32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70},
{67,26,20,68,2,62,12,20,95,63,94,39,63,8,40,91,66,49,94,21},
{24,55,58,5,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72},
{21,36,23,9,75,0,76,44,20,45,35,14,0,61,33,97,34,31,33,95},
{78,17,53,28,22,75,31,67,15,94,3,80,4,62,16,14,9,53,56,92},
{16,39,5,42,96,35,31,47,55,58,88,24,0,17,54,24,36,29,85,57},
{86,56,0,48,35,71,89,7,5,44,44,37,44,60,21,58,51,54,17,58},
{19,80,81,68,5,94,47,69,28,73,92,13,86,52,17,77,4,89,55,40},
{4,52,8,83,97,35,99,16,7,97,57,32,16,26,26,79,33,27,98,66},
{88,36,68,87,57,62,20,72,3,46,33,67,46,55,12,32,63,93,53,69},
{4,42,16,73,38,25,39,11,24,94,72,18,8,46,29,32,40,62,76,36},
{20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,4,36,16},
{20,73,35,29,78,31,90,1,74,31,49,71,48,86,81,16,23,57,5,54},
{1,70,54,71,83,51,54,69,16,92,33,48,61,43,52,1,89,19,67,48},
};
int s = 0;
int right()
{
int a = 1;
int i = 0;
int n = 0;
int r = 0;
int c = 0;
for(n = 0;n <= 359;n++)
{
if(c <= 16)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[r][(c + i)] << " ";
a *= array[r][(c + i)];
};
//cout << a << " ";
i = 0; c++;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 0; r++;};
};
return s;
};
int left()
{
int a = 1;
int i = 0;
int n = 0;
int r = 0;
int c = 19;
for(n = 0;n <= 359;n++)
{
if(c >= 3)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[r][(c - i)] << " ";
a *= array[r][(c - i)];
};
//cout << a << " ";
i = 0; c--;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 19; r++;};
};
return s;
};
int down()
{
int n = 0;
int i = 0;
int r = 0;
int c = 0;
int a = 1;
for(n = 0;n <= 356;n++)
{
if(c <= 19)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[(r + i)][c] << " ";
a *= array[(r + i)][c];
};
//cout << a << " ";
i = 0; c++;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 0;
if(r <= 16){
r++;
}else{break;};
};
};
return s;
};
int up()
{
int n = 0;
int i = 0;
int r = 19;
int c = 0;
int a = 1;
for(n = 0;n <= 356;n++)
{
if(c <= 19)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[(r - i)][c] << " ";
a *= array[(r - i)][c];
};
//cout << a << " ";
i = 0; c++;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 0;
if(r >= 3){
r--;
}else{break;};
};
};
return s;
};
int diag_left_up()
{
int n = 0;
int i = 0;
int r = 19;
int c = 19;
int a = 1;
for(n = 0;n <= 304;n++)
{
if(c >= 3 && r >= 3)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[(r - i)][(c - i)] << " ";
a *= array[(r - i)][(c - i)];
};
//cout << a << " ";
i = 0; c--;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 19;
if(r >= 3){
r--;
}else{break;};
};
};
return s;
};
int diag_left_down()
{
int n = 0;
int i = 0;
int r = 0;
int c = 19;
int a = 1;
for(n = 0;n <= 304;n++)
{
if(c >= 3 && r <= 16)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[(r + i)][(c - i)] << " ";
a *= array[(r + i)][(c - i)];
};
//cout << a << " ";
i = 0; c--;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 19;
if(r <= 16){
r++;
}else{break;};
};
};
return s;
};
int diag_right_up()
{
int n = 0;
int i = 0;
int r = 19;
int c = 0;
int a = 1;
for(n = 0;n <= 304;n++)
{
if(c <= 16 && r >= 3)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[(r - i)][(c + i)] << " ";
a *= array[(r - i)][(c + i)];
};
//cout << a << " ";
i = 0; c++;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 0;
if(r >= 3){
r--;
}else{break;};
};
};
return s;
};
int diag_right_down()
{
int n = 0;
int i = 0;
int r = 0;
int c = 0;
int a = 1;
for(n = 0;n <= 304;n++)
{
if(c <= 16 && r <= 16)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[(r + i)][(c + i)] << " ";
a *= array[(r + i)][(c + i)];
};
//cout << a << " ";
i = 0; c++;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 0;
if(r <= 16){
r++;
}else{break;};
};
};
return s;
};
int main()
{
cout << "Result from right():" << '\t' << right();
cout << endl;
cout << "Result from left():" << '\t' << left();
cout << endl;
cout << "Result from down():" << '\t' << down();
cout << endl;
cout << "Result from up():" << '\t' << up();
cout << endl;
cout << "Result from diag_right_up(): " << '\t' << diag_right_up();
cout << endl;
cout << "Result from diag_right_down(): " << '\t' << diag_right_down();
cout << endl;
cout << "Result from diag_left_up(): " << '\t' << diag_left_up();
cout << endl;
cout << "Result from diag_left_down(): " << '\t' << diag_left_down();
cout << endl << endl << "Greatest result: " << s;
return 0;
}
The first thing I notice is that you've got a lot of functions that do basically the same thing (with some numbers different). I would investigate adding a couple of parameters to that function, so that you can describe the direction you're going. So for example, instead of calling right() you might call traverse(1, 0) and traverse(0, -1) instead of up().
Your traverse() function declaration might look like:
int traverse(int dx, int dy)
with the appropriate changes inside to adapt its behaviour for different values of dx and dy.
Well, for starters, you only need four of those directions: right/left, up/down, right-up/down-left and right-down/up-left. Multiplication is commutative, so it doesn't matter which direction you go from a given pair (if you find "a b c d" in one direction, you'll find "d c b a" in the opposite direction, and you get the same result when multiplying those numbers together).
Secondly, use more descriptive variable names. A variable name like s is meaningless; something like maximum is better, because that tells you what that variable is for. That doesn't mean you should never ever use a single-character variable name - e.g., using i as a for-loop counter is perfectly fine, and if you're dealing with coordinates, x and y can also be just fine, but when at all possible, you should use a descriptive name to make the code more self-documenting.
Thirdly, you can look into what Greg suggests and refactor your methods to take a direction instead. This would allow you to ditch all of the similar methods (and just call that one method 4 times with different parameters to cover all of the necessary directions).
And finally, you may want to be more consistent about your formatting - I know that can be hard to start doing, but it helps you in the long run. To understand what I mean here, take a good look at this snippet, taken from your down() method:
if(c <= 19)
{
for(i = 0;i <= 3;i++)
{
//cout << " " << array[(r + i)][c] << " ";
a *= array[(r + i)][c];
};
//cout << a << " ";
i = 0; c++;
if(a > s)
{
s = a;
a = 1;
};
//cout << s << " " << endl;
a = 1;
}else{c = 0;
if(r <= 16){
r++;
}else{break;};
};
Notice how you place a line break before the opening curly bracket of your ifs, but write }else{ on a single line. Additionally, inside the first else, you have another if-block where you don't place a line break before the curly bracket, and the closing bracket has the same indent level as the block content (r++;). This is quite inconsistent, and makes it harder to read.
static void largestProduct11() {
int[][] arr = {
{8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8},
{49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56,
62, 0},
{81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 3, 49, 13,
36, 65},
{52, 70, 95, 23, 4, 60, 11, 42, 69, 24, 68, 56, 1, 32, 56, 71, 37, 2, 36,
91},
{22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33,
13, 80},
{24, 47, 32, 60, 99, 3, 45, 2, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17,
12, 50},
{32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38,
64, 70},
{67, 26, 20, 68, 2, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94,
21},
{24, 55, 58, 5, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89,
63, 72},
{21, 36, 23, 9, 75, 0, 76, 44, 20, 45, 35, 14, 0, 61, 33, 97, 34, 31, 33,
95},
{78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 3, 80, 4, 62, 16, 14, 9, 53, 56,
92},
{16, 39, 5, 42, 96, 35, 31, 47, 55, 58, 88, 24, 0, 17, 54, 24, 36, 29, 85,
57},
{86, 56, 0, 48, 35, 71, 89, 7, 5, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17,
58},
{19, 80, 81, 68, 5, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 4, 89, 55,
40},
{4, 52, 8, 83, 97, 35, 99, 16, 7, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98,
66},
{88, 36, 68, 87, 57, 62, 20, 72, 3, 46, 33, 67, 46, 55, 12, 32, 63, 93,
53, 69},
{4, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76,
36},
{20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 4,
36, 16},
{20, 73, 35, 29, 78, 31, 90, 1, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 5,
54},
{1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67,
48}
};
/*
* |A11 A12 A13 * * A1N|
* |A21 A22 A23 * * A2N|
* |A31 A32 A33 A3N|
* * *
* * *
* |An1 A2N A3N * * ANN|
*
* */
String line;
int[] temp = new int[4];
int compre = 1;
int result = 1;
for (int i = 0; i < arr.length - 3; i++) { // optimize:- the condition is true
// if the remaining index are at least four therefore the length should be reduced by
// three that means only the first 16 members can can satisfy the condition
for (int j = 0; j < arr[0].length - 3; j++) {
result = arr[i][j] * arr[i + 1][j + 1] * arr[i + 2][j + 2] * arr[i + 3][j + 3];
if (compre < result) {
compre = result;
}
}
}
//
System.out.println(compre + " Right sie test ");
for (int i = 0; i < arr.length - 3; i++) {
line = "{";
for (int j = arr[0].length - 1; j > 3; j--) {
result = arr[i][j] * arr[i + 1][j - 1] * arr[i + 2][j - 2] * arr[i + 3][j
- 3];
if (compre < result) {
compre = result;
}
}
}
System.out.println(compre + " final result"); // solution= 70600674
}