Python: max() not working as expected

On the level Mountain Mercenaries in Cloudrip Mountain, I’m attempting to collect coins based on their value per distance.
Using max() fails to select the highest value per distance coin out of all found coins.

def valueOverDistance(coin):
    return coin.value / hero.distanceTo(coin)

useMax = False
useMax = True # comment this line out to use the working solution, which doesn't use max

while True:
    coins = hero.findItems()
    if len(coins) > 0:
        if useMax: # these don't work as expected
            #bestCoin = max(coins, key=valueOverDistance)
            #bestCoin = max(coins, key=lambda coin: valueOverDistance(coin))
            bestCoin = max(coins, key=lambda coin: coin.value / hero.distanceTo(coin)) # how does this not work???
            #bestCoin = max(coins) # all the lines above using max() have the same result as this line!
        else: # this works perfectly as expected, but it doesn't use max()
            bestCoin = coins[0]
            for coin in coins:
                if valueOverDistance(coin) > valueOverDistance(bestCoin):
                    bestCoin = coin
        #worstCoin = min(coins, key=valueOverDistance) #doesn't work as expected either

Is there a way to use max() so that it works as expected?

I don’t have an answer for you, but I have been playing around with your code and I noticed something.

max() is returning a coin, just not the coin you expect.

I am pretty sure your program is collecting coins by reverse alphabetical order of the coin id.

For example, it would go in this order

Silver Coin 9
Silver Coin 8
Silver Coin 7
Silver Coin 6
Silver Coin 5
Silver Coin 4
Silver Coin 3
Silver Coin 2
Silver Coin 12
Silver Coin 11
Gold Coin 4
Gold Coin 3
Gold Coin 2
Gold Coin 1
Bronze Coin 42
Bronze Coin 41

I have no idea what this means, but I hope it helps someone else figure out what is going on.

1 Like

I have a couple more attempts inspired from stackoverflow:

# doesn't work as xrange doesn't seem to be implemented yet:
bestCoin = coins[max(xrange(len(coins)),
                     key = lambda index:
                         coins[index]['value'] / hero.distanceTo(coins[index]))

# doesn't work; this collects coins in reverse alphabetical order like the previous attempts:
bestCoin = max(enumerate(coins),
               key = lambda indexCoinTuple:
                   indexCoinTuple[1]['value'] / hero.distanceTo(indexCoinTuple[1])
           )[1] # selects the dictionary part of the (index, dict) tuple that comes from enumeration items

Still a bug in 2020, with apologies for the necro.

As an example, findFarthest could be minimally implemented as the following:

def findFarthest(items):
  if items:
    return max(items, key = hero.distanceTo)
  return None

Except it doesn’t work as expected. Indeed, max(items, key = hero.distanceTo) returns precisely the same result as max(items). This is not Python 3 specific either; this functionality was added in 2.5. min and sorted are also likewise affected.

Since Python in CodeCombat was converted from JavaScript, some functions may not work.

@Chaboi_3000 So the Python used is home brew (or transpiled to JS)? Still, it would be nice if core functionality could be implemented.