简体   繁体   English

用于 ProjectEuler 问题 11 的程序优化

[英]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.这是我用来解决 ProjectEuler 问题 11 的代码。它非常大,当我看到它的四分之一大小的代码做同样的事情时,我有点担心,呵呵。

#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() .因此,例如,您可以调用traverse(1, 0)traverse(0, -1)而不是up() ,而不是调用right() up()

Your traverse() function declaration might look like:您的traverse()函数声明可能如下所示:

int traverse(int dx, int dy)

with the appropriate changes inside to adapt its behaviour for different values of dx and dy .在内部进行适当的更改以使其行为适应dxdy不同值。

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 "abcd" in one direction, you'll find "dcba" in the opposite direction, and you get the same result when multiplying those numbers together).乘法是可交换的,所以从给定的对往哪个方向走并不重要(如果你在一个方向找到“abcd”,你会在相反的方向找到“dcba”,并且在将它们相乘时得到相同的结果数在一起)。

Secondly, use more descriptive variable names.其次,使用更具描述性的变量名称。 A variable name like s is meaningless;s这样s变量名是没有意义的; something like maximum is better, because that tells you what that variable is for.maximum这样的东西更好,因为它告诉你那个变量是做什么的。 That doesn't mean you should never ever use a single-character variable name - eg, 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.这并不意味着你永远不应该使用单字符变量名——例如,使用i作为 for 循环计数器是非常好的,如果你正在处理坐标, xy也可以,但是在可能的情况下,您应该使用描述性名称来使代码更具自文档性。

Thirdly, you can look into what Greg suggests and refactor your methods to take a direction instead.第三,您可以查看 Greg 的建议并重构您的方法以取而代之。 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).这将允许您放弃所有类似的方法(只需使用不同的参数调用该方法 4 次即可涵盖所有必要的方向)。

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:要理解我在这里的意思,请仔细查看取自down()方法的这段代码:

        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.请注意如何在 ifs 的左大括号之前放置换行符,但将}else{写在一行中。 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++; ).此外,第一个else ,您还有另一个 if 块,其中您不在大括号之前放置换行符,并且右括号与块内容 ( 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
   
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM