Project Euler in PL/SQL: Problem 11

  • by

Problem 11 of Project Euler presents us a brute-force challenge of checking multiple products from a number grid.

Problem 11:

Largest Product in a Grid

In the 20×20 grid below, four numbers along a diagonal line have been marked in red.

08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 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 03 45 02 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 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48

The product of these numbers is 26 × 63 × 78 × 14 = 1788696.

What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the 20×20 grid?

Working with arrays is a pain in PL/SQL compared to other languages like Ruby, so you’ll see a lot of the code below is devoted to just setting up the array. Then the program loops through each set of number of each line and calculates the product based on our criteria. Since I removed the spaces from the lines of numbers, I made a helper function get_num that will make retrieving the numbers easy.

DECLARE
TYPE grid IS VARRAY(20) OF VARCHAR2(40);
num_grid grid := grid();
answer NUMERIC := 0;
product NUMERIC;
    FUNCTION get_num(line_in VARCHAR2, num_in INTEGER) 
    RETURN VARCHAR2
    AS
    numz NUMERIC;
    BEGIN
        numz := num_in * 2 - 1;
        RETURN substr(line_in, numz, 2);
    END;
BEGIN
num_grid.EXTEND(20);
num_grid(1) := '0802229738150040007504050778521250779108';
num_grid(2) := '4949994017811857608717409843694804566200';
num_grid(3) := '8149317355791429937140675388300349133665';
num_grid(4) := '5270952304601142692468560132567137023691';
num_grid(5) := '2231167151676389419236542240402866331380';
num_grid(6) := '2447326099034502447533537836842035171250';
num_grid(7) := '3298812864236710263840675954706618386470';
num_grid(8) := '6726206802621220956394396308409166499421';
num_grid(9) := '2455580566739926971778789683148834896372';
num_grid(10) := '2136230975007644204535140061339734313395';
num_grid(11) := '7817532822753167159403800462161409535692';
num_grid(12) := '1639054296353147555888240017542436298557';
num_grid(13) := '8656004835718907054444374460215851541758';
num_grid(14) := '1980816805944769287392138652177704895540';
num_grid(15) := '0452088397359916079757321626267933279866';
num_grid(16) := '8836688757622072034633674655123263935369';
num_grid(17) := '0442167338253911249472180846293240627636';
num_grid(18) := '2069364172302388346299698267598574043616';
num_grid(19) := '2073352978319001743149714886811623570554';
num_grid(20) := '0170547183515469169233486143520189196748';

FOR i IN 1..num_grid.count LOOP --for each line
    FOR n IN 1..20 LOOP --for each individual number
        IF i < 17 THEN
            --handles the up/down cases
            product := get_num(num_grid(i),n) * get_num(num_grid(i+1),n) * get_num(num_grid(i+2),n) * get_num(num_grid(i+3),n);
            
            IF product > answer
            THEN
                answer := product;
            END IF;
            
            --handles diagnol left-to-right
            product := get_num(num_grid(i),n) * get_num(num_grid(i+1),n+1) * get_num(num_grid(i+2),n+2) * get_num(num_grid(i+3),n+3);
            
            IF product > answer
            THEN
                answer := product;
            END IF;
            
            IF n > 3
            THEN
                 --handles diagnol right-to-left
                product := get_num(num_grid(i),n) * get_num(num_grid(i+1),n-1) * get_num(num_grid(i+2),n-2) * get_num(num_grid(i+3),n-3);
                
                IF product > answer
                THEN
                    answer := product;
                END IF;
            END IF;
        END IF;  
          
        IF n <17 THEN
            --handles left/right cases
            product := get_num(num_grid(i),n) * get_num(num_grid(i),n+1) * get_num(num_grid(i),n+2) * get_num(num_grid(i),n+3);
            --dbms_output.put_line(product);
            
            IF product > answer
            THEN
                answer := product;
            END IF;
        END IF;
    END LOOP;    
END LOOP;
dbms_output.put_line(answer);
END;
--output: 70600674

Questions or comments? Feel free to leave them below or reach out to me on Twitter!

Leave a Reply

Your email address will not be published. Required fields are marked *