Maximize the Gold

In the grid above, the number of gold coins in each cell is given. Adam needs to start in the bottom-left square and move to the top-right square, moving only up and to the right.

What is the maximum number of gold coins he can collect?


This can be solved using a recursive approach ( dynamic programming ).

  • I've set up the grid ( coins ), where the bottom-left cell is (0,0) and the top-right is (7,6) ; i.e., coins[(1,2)] = 5 .
  • I've also computed max_coins , the maximum number of coins Adam can collect along the way to a given cell, for the first column and row.
  • You need to fill in the logic in line 19 - the recursive step for max_coins for the rest of the cells - and run the code !

Hint: What are the possible states just before you reach a given cell?

from brilliant import goldgrid
coins = goldgrid.grid()
height, width = goldgrid.height(coins), goldgrid.width(coins)

#Initializing the dictionary for the maximum coins up to a certain cell
max_coins = {(0,0) : coins[(0,0)]}

#Computing the max_coins values for the first column and row
#The maximum coins is the maximum for the cell prior to it, plus the coins in that cell
for row in range(1,height):
    max_coins[(0,row)] = max_coins[(0,row-1)] + coins[(0,row)]

for column in range(1,width):
    max_coins[(column,0)] = max_coins[(column-1,0)] + coins[(column,0)]

#Using recursion / dynamic programming to find the remaining maximums
for row in range(1,height):
    for column in range(1,width):
        max_coins[(column,row)] = #FILL ME IN

#Print the maximum value for the top right cell
print(max_coins[(width-1,height-1)])
Python 3
You need to be connected to run code

Bonuses: How can you initialize max_coins differently to avoid the separate cases for the first column and row, and just have a single recursive loop? Also, can you modify the code to return the actual path that gives the maximum gold?


The answer is 33.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

7 solutions

Kunal Gupta
Sep 23, 2017

Relevant wiki: Dynamic Programming

The Key to find the answer here is that , if you want to know the max number of coins to reach cell (i,j) then you can compute it recursively by knowing the no max coins to reach cell(i+1,j) and cell(i,j-1) ( assuming Adam starts from bottom left and goes to top right). Recursively:
Let F ( i , j ) F(i,j) be the function that gives max number of coins to reach cell (i,j) then, F ( i , j ) = m a x ( F ( i + 1 , j ) , F ( i , j 1 ) ) + c o i n s ( i , j ) F(i,j) = max(F(i+1,j) ,F(i,j-1)) + coins(i,j) Giving the answer to be 33 33 Using DP can help avoid recalculate already calculated values and solve in O ( n m ) \mathcal{O}(n*m) Time Complexity ( where m , n m,n are rows and columns ) Hence Line 19 may be: (Note that the code has been written by taking rows and columns from topleft and so the condition has been modified accordingly!)

1
max_coins[(column,row)] = max(max_coins[(column-1,row)],max_coins[(column,row-1)]) + coins[(column,row)] 

Am I to weird if I say this problem wasn't hard to crack without programming? Did use a same kind of algorithm on my head though.

Peter van der Linden - 3 years, 8 months ago

Log in to reply

No - I solved it in my head as well.

Thomas Sutcliffe - 3 years, 8 months ago

Log in to reply

Gonna be a hell if a job if the grid would increase though... :)

Peter van der Linden - 3 years, 8 months ago

Yeah , it's intuition more importantly! In fact intuition is the birth of most algorithms and procedure in CS! :)

Kunal Gupta - 3 years, 8 months ago

I keep getting 32!!!!!!!!! Someone please explain it to why the answer is 33(in easy words, I am only a 7 grader)

Taeho Bang - 3 years, 8 months ago

Log in to reply

(R = move right, U = move up) 2R-1U-2R-3U-1R-2U-2R, which gives 0+0+4+6+1+6+1+4+5+0+3+1+2+0 = 33 ( If you fill out the grid as per the algorithm, then you can determine a path that gives the maximum by working backwards from the upper right, going left or down to the box with the highest number of that pair. If they are both equal, you can take either path.

Kevin Lehmann - 3 years, 8 months ago

Log in to reply

Thanks!!! I understand now.

Taeho Bang - 3 years, 8 months ago

I get that the computer-generated answer is 33, but while trying to figure it out in head, I only got 32 as best route. Can somebody please point out the route that gives 33? No need for drawing, a 13 character long sequence of U (for up) and R (for right) is good enough for me ^_^

edit: Nevermind, found it. It's RRURRUUU RU URR. The italicized part can be inverted, so two solutions :D

József Inczefi - 3 years, 8 months ago

I love that you made that programming interface just for this problem, it honestly made it 10x better than it would've otherwise been.

Alex Li - 3 years, 8 months ago

Log in to reply

It's not just for this problem, in the weekly problems for this week, they started popping up on other problems as well.

József Inczefi - 3 years, 8 months ago

Your python code is correct but the comments explaining it above should have a “-“ instead of a “+”.

Marc Becraft - 3 years, 8 months ago

Log in to reply

I have specifically stated that the code is written assuming that we are starting from top left. But since the problem initially stated that we begin from bottom left, I gave the explanation accordingly.

Kunal Gupta - 3 years, 8 months ago

im getting 31

Sourjyo Deb - 3 years, 8 months ago

Log in to reply

recheck you working. If you're still getting same answer it might be that your implementation of the algorithm is wrong.

Kunal Gupta - 3 years, 8 months ago

Great solution but this doesn’t work for arbitrary grids. The problem has to do with the decision if both paths have the same value. One could construct a grid where the choice between ‘a tie’ matters.

Anwar Rohillah - 3 years, 8 months ago

Log in to reply

Yes in fact it does, this solution calculates the max possible value for every grid location (that is, the max value of every possible path to every single grid location).

Jack Sormaz - 3 years, 8 months ago

to those that say they solved it "in my head", if you did it without writing anything down, that's very impressive. But if you wrote down the numbers(as most of us would have to) I'd call that "manually" and less impressive. In fact it's tedious, so that's where the programming really shines and makes it much more fun. Also, the solution is iterative, not recursive. Recursive would require calling a function recursively and (starting in the top-right) would probably just blow the stack. to print out the path you have to initialize a path variable e.g. on line 7 path = "" then replace the max function with separate paths of code e.g. replace lines 19 to 29 with

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
        colmax,rowmax = max_coins[(column-1,row)],max_coins[(column,row-1)]
        cell_value = coins[(column,row)]
        if colmax > rowmax:
            max_coins[(column,row)] = colmax + cell_value
            path += "R"
        else:
            max_coins[(column,row)] = rowmax + cell_value
            path += "U"

#Print the maximum value for the top right cell
print(max_coins[(width-1,height-1)],path)

this assumes colmax and rowmax are unequal and there's only one maximum path, but it will always print a valid path.

Gary Scarr - 3 years, 8 months ago

Log in to reply

I have formatted your code correctly. You can click on "edit" to see how to do this.

Agnishom Chattopadhyay - 3 years, 8 months ago
Flávio de Sousa
Sep 28, 2017

Relevant wiki: Dynamic Programming

Solved with a spreadsheet (LibreOffice Calc).

Placed the numbers as shown on the A1..H7 grid.

In the cell J7 I placed the formula =MAX(I7,J8)+A7 and copied it to the J1..Q7 grid.

The result was in the cell Q1.

Matthew Civil
Oct 1, 2017

If you are interested in these problems have a look at the literature on Operational Research.

Matthew, isn't there an error? Moving from 22 to 6 is 28, not 29. I am only able to obtain 32 coins.

Timothy Jordan - 3 years, 7 months ago

Log in to reply

If you move from 23 to 6 the total is 29.

Venkatachalam J - 3 years, 6 months ago

Relevant wiki: Dynamic Programming

I think it is a bit self explanatory, but anyway, let me explain:

The idea to get rid of the corners is not to define coordinates at -1, as this is ugly and quite a messy workaround. Instead, a function filters valid coordinates to retrieve from max_coins. Better yet would be to instead write a recursive function that would not even try values smaller than 0, but as Python is not tail-call optmized I don't think it would be very performant.

Then, to unravel the path, the concept is a lot similar from the one used in generating the max_coins list: just look from where there are the most coins and append it.

 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
from brilliant import goldgrid
coins = goldgrid.grid()
height, width = goldgrid.height(coins), goldgrid.width(coins)

#Initializing the dictionary for the maximum coins up to a certain cell

max_coins = {(0,0): coins[0,0]}

def get_max_coins(coord):
    if coord[0] >= 0 and coord[1] >= 0:
        return max_coins[coord]
    else:
        return 0

for row in range(height):
    for column in range(width):
        if not (column, row) == (0,0):
            left_coin = get_max_coins((column - 1, row))
            down_coin = get_max_coins((column, row - 1))

            max_coins[(column,row)] = max(left_coin, down_coin) + coins[column,row]


def trace_path(coord, accumulator):
    accumulator.append(coord)

    left_coord = (coord[0] - 1, coord[1])
    down_coord = (coord[0], coord[1] - 1)

    max_coord = (left_coord, down_coord)[get_max_coins(down_coord) > get_max_coins(left_coord)]

    if coord != (0,0):
        return trace_path(max_coord, accumulator)
    else:
        return accumulator

#Print path and maximum value
print(trace_path((width - 1, height - 1), []))
print(get_max_coins((width - 1, height - 1)))

I believe the solution of either using pythons default dictionary value, or for more explicit and easily commendable code, setting the negative coordinates to 0, is less bulky and more efficient that calling an if statement for every lookup, especially if the grid size is large. The implementation of a default value also calls an if statement, though in C in a good implementation, but since we have prior knowledge of our own algorithm which python doesn't, we know that the only non positive values we'll call are -1 in some direction, then the most efficient solution is actually setting the negative edges to be 0. Get gud m8

Jonny Powell - 3 years, 8 months ago

The idea to get rid of initializing the cases for the first column and row can be accomplished using a feature of the implemented Python dictionary which allows you to return 0 for any non-existing coordinates like -1.

1
2
3
4
#Using recursion / dynamic programming to find the remaining maximums
for row in range(0,height):
    for column in range(0,width):
        max_coins[(column,row)] = max( max_coins.get((column-1,row),0), max_coins.get((column,row-1),0) ) + coins[(column,row)]

Roger Thiede - 3 years, 8 months ago

What is the path that you got?

Agnishom Chattopadhyay - 3 years, 8 months ago
Jonny Powell
Sep 28, 2017

Here is my solution:

 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
    from brilliant import goldgrid
    coins = goldgrid.grid()
    height, width = goldgrid.height(coins), goldgrid.width(coins)

    #Initializing the dictionary, including making edges exist but undesirable
    max_coins = {(-1,n) : 0 for n in range(0,height)}
    max_coins.update({(n,-1) : 0 for n in range(0,width)})

    #Using recursion / dynamic programming to find the remaining maximums
    for row in range(0,height):
        for column in range(0,width):
                max_coins[(column,row)] = max(max_coins[(column,row-1)], max_coins[(column-1,row)]) + coins[(column,row)]

    #Print the maximum value for the top right cell
    print(max_coins[(width-1,height-1)])

    #Initializing the path list
    path = []
    #Starting at the top right, descend backwards
    current_row = height-1
    current_column = width-1
    #Note there will be 14 moves in total
    for move in range(0,14):
        path.append((current_column,current_row))
        if max_coins[(current_column-1,current_row)] >= max_coins[(current_column,current_row-1)]:
            current_column -= 1
        else:
            current_row -= 1
    #Reverse the path to start it from the bottom left
    path.reverse()
    #Print the path taken
    print(path)

Shreyas Belwalkar
Sep 28, 2017

On closely examining the grid, you will notice that the grid has 6 only three times, out of which you can go through any two. You just have to now pick up the path that gives you the max. sum. The grid is so arranged that it supports this logic.

Prasit Sarapee
Sep 29, 2017

from brilliant import goldgrid
...
...
for column in range(1,width):
if max coins[(column-1,row)]> max coins[(column,row-1)]:
max coins[(column,row)] = max coins[(column-1,row)]+coins[(column,row)];
else:
max coins[(column,row)] = max coins[(column,row-1)]+coins[(column,row)];
..
print(max_coins[(width-1,height-1)])







0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...