Legends ofPythos
Claim your name
Working with Data

Hrafnkel, the Barrow Draugr

The last fight of this track

Boss · level 10

Hrafnkel

the Barrow Draugr

Health4 of 4 stages standing
Deep in the barrow on Kolfell, the draugr Hrafnkel counts his hoard every night and has done since he died. He will let a living soul take one sack of treasure, and only if they can prove they know the hoard better than he does. His ledger is kept in the old runes, which to you look a great deal like JSON.

The fight

Four stages, each building on the last. Every stage opens with your finished code from the stage before, so you pick up where you left off. This fight draws on JSON, sorting with keys, comprehensions, sets, tuples and nested data.
Stage 1: Reading the ledger. Open the ledger and find the richest treasures.
Stage 2: By kind. Sort the hoard into its kinds.
Stage 3: The counting. Weigh and value the hoard.
Stage 4: One sack. Fill one sack with the best the barrow holds.

The fight

0 of 4 stages won

Stage 1 of 4

+60 XP
Hrafnkel's ledger is LEDGER, a JSON string holding a list of treasures, each an object with item, kind, value and weight. Write load(text), which parses a JSON string and returns the result, and worth_more_than(hoard, amount), which takes the parsed list and returns the names of the treasures worth more than amount, highest value first, with ties in alphabetical order of name. For example, worth_more_than(load(LEDGER), 140) is ['crown', 'sword', 'torc'].
import json


LEDGER = """[
  {"item": "crown", "kind": "gold", "value": 300, "weight": 5},
  {"item": "jet-bead", "kind": "gem", "value": 20, "weight": 1},
  {"item": "torc", "kind": "gold", "value": 150, "weight": 4},
  {"item": "chalice", "kind": "silver", "value": 45, "weight": 3},
  {"item": "garnet", "kind": "gem", "value": 80, "weight": 1},
  {"item": "sword", "kind": "weapon", "value": 150, "weight": 7},
  {"item": "helm", "kind": "weapon", "value": 60, "weight": 6},
  {"item": "arm-ring", "kind": "gold", "value": 120, "weight": 2},
  {"item": "ingot", "kind": "silver", "value": 90, "weight": 9}
]"""




def load(text):
    # Parse the JSON text and return the result
    pass




def worth_more_than(hoard, amount):
    # Names of the treasures worth more than amount, highest value first, ties by name
    pass

Run your code to check it against the tests.

Stage 2 of 4

+60 XP
Keep stage 1 and write by_kind(hoard), which returns a dictionary mapping each kind to an alphabetically sorted list of the names of that kind, and kinds(hoard), which returns the set of kinds in the hoard. For example, by_kind(load(LEDGER))['silver'] is ['chalice', 'ingot'].
import json


LEDGER = """[
  {"item": "crown", "kind": "gold", "value": 300, "weight": 5},
  {"item": "jet-bead", "kind": "gem", "value": 20, "weight": 1},
  {"item": "torc", "kind": "gold", "value": 150, "weight": 4},
  {"item": "chalice", "kind": "silver", "value": 45, "weight": 3},
  {"item": "garnet", "kind": "gem", "value": 80, "weight": 1},
  {"item": "sword", "kind": "weapon", "value": 150, "weight": 7},
  {"item": "helm", "kind": "weapon", "value": 60, "weight": 6},
  {"item": "arm-ring", "kind": "gold", "value": 120, "weight": 2},
  {"item": "ingot", "kind": "silver", "value": 90, "weight": 9}
]"""




def load(text):
    return json.loads(text)




def worth_more_than(hoard, amount):
    rich = [t for t in hoard if t['value'] > amount]
    rich = sorted(rich, key=lambda t: (-t['value'], t['item']))
    return [t['item'] for t in rich]




def by_kind(hoard):
    # Map each kind to a sorted list of the names of that kind
    pass




def kinds(hoard):
    # The set of kinds in the hoard
    pass

Run your code to check it against the tests.

Stage 3 of 4

+60 XP
Keep everything and write value_by_kind(hoard), which returns a dictionary of each kind's total value, built with a dictionary comprehension over kinds(hoard), and heaviest(hoard), which returns a tuple (item, weight) for the heaviest treasure, choosing the alphabetically first name when weights tie, or None for an empty hoard. For example, value_by_kind(load(LEDGER))['gem'] is 100 and heaviest(load(LEDGER)) is ('ingot', 9).
import json


LEDGER = """[
  {"item": "crown", "kind": "gold", "value": 300, "weight": 5},
  {"item": "jet-bead", "kind": "gem", "value": 20, "weight": 1},
  {"item": "torc", "kind": "gold", "value": 150, "weight": 4},
  {"item": "chalice", "kind": "silver", "value": 45, "weight": 3},
  {"item": "garnet", "kind": "gem", "value": 80, "weight": 1},
  {"item": "sword", "kind": "weapon", "value": 150, "weight": 7},
  {"item": "helm", "kind": "weapon", "value": 60, "weight": 6},
  {"item": "arm-ring", "kind": "gold", "value": 120, "weight": 2},
  {"item": "ingot", "kind": "silver", "value": 90, "weight": 9}
]"""




def load(text):
    return json.loads(text)




def worth_more_than(hoard, amount):
    rich = [t for t in hoard if t['value'] > amount]
    rich = sorted(rich, key=lambda t: (-t['value'], t['item']))
    return [t['item'] for t in rich]




def by_kind(hoard):
    groups = {}
    for treasure in hoard:
        kind = treasure['kind']
        if kind not in groups:
            groups[kind] = []
        groups[kind].append(treasure['item'])
    return {kind: sorted(names) for kind, names in groups.items()}




def kinds(hoard):

Run your code to check it against the tests.

Stage 4 of 4

+60 XP
Hrafnkel lets you carry one sack. Keep everything and write fill_sack(hoard, capacity). Go through the treasures in order of value per unit of weight (value / weight), highest first, with ties by name, and take each one that fits without the total weight going over capacity; one that does not fit is skipped and the next is tried. Return the JSON string json.dumps({'items': taken, 'value': total_value, 'weight': total_weight}, sort_keys=True), where taken lists the names in the order you took them. For example, with a capacity of 3 you take the garnet and then the arm-ring, for a value of 200.
import json


LEDGER = """[
  {"item": "crown", "kind": "gold", "value": 300, "weight": 5},
  {"item": "jet-bead", "kind": "gem", "value": 20, "weight": 1},
  {"item": "torc", "kind": "gold", "value": 150, "weight": 4},
  {"item": "chalice", "kind": "silver", "value": 45, "weight": 3},
  {"item": "garnet", "kind": "gem", "value": 80, "weight": 1},
  {"item": "sword", "kind": "weapon", "value": 150, "weight": 7},
  {"item": "helm", "kind": "weapon", "value": 60, "weight": 6},
  {"item": "arm-ring", "kind": "gold", "value": 120, "weight": 2},
  {"item": "ingot", "kind": "silver", "value": 90, "weight": 9}
]"""




def load(text):
    return json.loads(text)




def worth_more_than(hoard, amount):
    rich = [t for t in hoard if t['value'] > amount]
    rich = sorted(rich, key=lambda t: (-t['value'], t['item']))
    return [t['item'] for t in rich]




def by_kind(hoard):
    groups = {}
    for treasure in hoard:
        kind = treasure['kind']
        if kind not in groups:
            groups[kind] = []
        groups[kind].append(treasure['item'])
    return {kind: sorted(names) for kind, names in groups.items()}




def kinds(hoard):

Run your code to check it against the tests.