[Algorithm Programming] It is difficult for a doctor to solve a primary school mathematics problem, but for a primary school mathematics problem.
Yesterday, I learned from the science internet that this news, "Doctor of mathematics in Vietnam's primary school is difficult." It is reported that the question came from the three-year class of Paul's primary school in Vietnam. However, it was reported that the question was difficult for the doctor to go to the parent, it's too much to say.
Description
Students must enter 1 ~ in the table in the order from top to bottom and from left to right ~ The number of 9, which can be repeated, and the entire formula is completed by first multiplication, division, and addition or subtraction (the colon represents division in the figure.
Solution
Obviously, this question is not a problem for programmers like ours. As long as we have a C-language student in freshman year (all of our schools have studied C, even for liberal arts majors) basically, we can use a nine-for loop to solve this problem. Below I use C and Matlab respectively, and I have improved the Matlab algorithm.
C language implementation:
# Include <stdio. h> # include <time. h> void main () {clock_t start, finish; // used for timing double duration; start = clock (); double result = 0; // store the computing result to see if it is equal to 66. int index = 0; int num = 0; for (int a = 1; a <10; a ++) for (int B = 1; B <10; B ++) for (int c = 1; c <10; c ++) for (int d = 1; d <10; d ++) for (int e = 1; e <10; e ++) for (int f = 1; f <10; f ++) for (int g = 1; g <10; g ++) for (int h = 1; h <10; h ++) for (int I = 1; I <10; I ++) {result = a + 13 * B/float (c) + d + 12 * e-f-11 + g * h/float (I)-10; if (result = 66) {// you can print the solution result num = num + 1 ;}}finish = clock (); duration = (double) (finish-start) /CLOCKS_PER_SEC; printf ("% d results in total \ n elapsed time: % f seconds \ n", num, duration );}
The result is as follows:
Matlab implementation
- The most direct method: It takes 4911.131591 seconds.
clear all;ans=[];ticfor a=1:9 for b=1:9 for c=1:9 for d=1:9 for e=1:9 for f=1:9 for g=1:9 for h=1:9 for i=1:9 result=a+13*b/c+d+12*e-f-11+g*h/i-10; if result==66; answer=[a b c d e f g h i]; ans=[ans;answer]; end end end end end end end end endend toc
In the above algorithm, the operation of answer storing the result is very time-consuming. We can find a way to optimize it. So,After I comment out the stored result process (remove the if statement block), the duration is 16.814298 seconds., The time is shortened from one hour to more than 10 seconds. However, even if you do not store the results, it takes 16.814298 seconds, which is still different from 4 seconds in C Language (and no results are stored!Next, let's talk about how to improve algorithms.
Improved matlab implementation
In the previous article "Matlab efficient programming skills", I mentionedAvoid multiple loops and use vectorized functions as much as possible.. Therefore, I decided to use a matrix instead of the 9-round loop.
First, let's start with a simple example.: Assume that there are two one-dimensional arrays a and B, whose elements are. Obviously, four arithmetic operations are performed between any elements of the two arrays (Here we assume that they are multiplied) there are 9*9 items in the result, which can be expressed by a 9*9 two-dimensional array. Similarly, assume that there are three one-dimensional arrays a, B, c, and their elements are, we need to calculate the result of four arithmetic operations between any elements of the three arrays. In this way, there are 9*9*9 items in total, and a 9*9*9 3D array is used for storage; and so on, we can obtain nine one-dimensional array elements and perform four arithmetic operations, which can be expressed in a 9-dimensional array of 9*9*9*9*9*9*9*9.
However, in matlab, * can only be used to multiply two-dimensional arrays. Fortunately, we can use the bsxfun function to calculate arrays of different dimensions.The following example demonstrates the usage of bsxfun:
Clear alla = ones (); % note that the one-dimensional column vector is equivalent to a two-dimensional vector of 9*1 B = ones (); c = ones (, 9 ); a () = 1: 9b (: 9) = 1: 9c (,) =; temp1 = bsxfun (@ times, a, B) % multiply a * B temp1 is a two-dimensional array of 9*9 temp2 = bsxfun (@ plus, a, B) % Add a + btemp3 = bsxfun (@ times, temp1, c) % multiply a * B * c 9*9*9 3D Array
By running the above results, you can find that,Bsxfun completes the result of performing a four-Rule operation between any element, and does not require equal dimensions.. Of course, for the calculation principles and functions of bsxfun, you can view the built-in documentation of Matlab. Our algorithms only need the above functions,In the program, I calculated according to the formula a + 13 * B/c + d + 12 * e-f-11 + g * h/I-10 when A, B, clerk, I And stored in abcdefghi. Finally, find the subscript index of the element with the value of 66 in the abcdefghi array. The index is the solution to the problem.. The specific Matlab program implementation is as follows:
Clear alltic % makes a, B, c, d, e, f, g, h, I 1, 2, 4, 5, 6, 7, 8, 9-dimensional vector a = ones (); % note that one-dimensional column vector is equivalent to a two-dimensional vector of 9*1 B = ones (); c = ones, 9); d = ones (,); e = ones (, 9); f = ones (,); g = ones,, 9); h = ones (,); I = ones (,);) =; B (: 9) =; c (,) =; d (,: 9) =; e) =; f (,: 9) =; g (,) =; h: 9) =; I (,) =; % mainly use bsxfun function to implement the four arithmetic operations of different dimension functions % a + 13 * B/c + d + 12 * e-f-11 + g * h/I-10 = 66b = bsxfun (@ times, b, 13); bc = bsxfun (@ rdivide, B, c); gh = bsxfun (@ times, g, h); ghi = bsxfun (@ rdivide, gh, i); abc = bsxfun (@ plus, a, bc); abcd = bsxfun (@ plus, abc, d); e = bsxfun (@ times, e, 12 ); abcde = bsxfun (@ plus, abcd, e); abcdef = bsxfun (@ minus, abcde, f); abcdef = bsxfun (@ minus, abcdef, 11 ); abcdefghi = bsxfun (@ plus, abcdef, ghi); abcdefghi = bsxfun (@ minus, abcdefghi, 10); toccounter = find (abcdefghi = 66 ); % locate the subscript index [l1, l2, l3, l4, l5, l6, l7, l8, d9] = ind2sub (size (abcdefghi), counter (1 )) % This is a possible solution
The running result is as follows:
As you can see, this method takes 4.183608 seconds. In the figure, I only show the top 10 results and only calculate the value of abcdefghi corresponding to the first result 45. Its value is in the variable space:
We can see that,The counter size is 442232, that is, there are a total of 442232 solutions. When counter (1) = 45, the corresponding solution is abcdefghi = 9 5 1 1 1 1 1 1 1 1.
Note: This program fails to run in a computer with a small memory because of insufficient memory. I am running on a lab workstation (with 128 GB memory.
Result Analysis
When using matlab programming, avoid using multiple loops and try to think about the problem from the matrix perspective. It can be seen from the time consumption comparison of the above program that it takes about 4 seconds to use the C language implementation and my improved algorithm, and the C language implementation is without storing the solution results, if you want to store the same results (the storage results can use different data structures: linked lists, queues, and so on), it may be time-consuming! The two matlab implementations mentioned in this article show that the first method occupies a small amount of memory and can be run on a common computer, but it takes a long time. However, our improved algorithm takes a short time, however, the machine that occupies a large amount of memory cannot run. This is the so-called time for space, space for time!
Original article: http://blog.csdn.net/tengweitw/article/details/46012217
Author: nineheadedbird