In Dark Souls, players level up trading souls for stats. 8 stats are upgradable this way: vitality, attunement, endurance, strength, dexterity, resistance, intelligence, and faith. Each level corresponds to adding one point to a stat of the player's choice. Also, there are 10 possible classes each having their own starting level and stats:

```
Warrior     (Level 4):  11, 8, 12, 13, 13, 11, 9, 9
Knight      (Level 5):  14, 10, 10, 11, 11, 10, 9, 11
Wanderer    (Level 3):  10, 11, 10, 10, 14, 12, 11, 8
Thief       (Level 5):  9, 11, 9, 9, 15, 10, 12, 11
Bandit      (Level 4):  12, 8, 14, 14, 9, 11, 8, 10
Hunter      (Level 4):  11, 9, 11, 12, 14, 11, 9, 9
Sorcerer    (Level 3):  8, 15, 8, 9, 11, 8, 15, 8
Pyromancer  (Level 1):  10, 12, 11, 12, 9, 12, 10, 8
Cleric      (Level 2):  11, 11, 9, 12, 8, 11, 8, 14
Deprived    (Level 6):  11, 11, 11, 11, 11, 11, 11, 11
```

From level 1, the necessary souls to level up each time up to 11 are `673`, `690`, `707`, `724`, `741`, `758`, `775`, `793`, `811`, and `829`. Then from 11 to 12 and onwards the amount is defined by the expression `round(pow(x, 3) * 0.02 + pow(x, 2) * 3.06 + 105.6 * x - 895)` where `x` is the number corresponding to the next level.

Your function will receive a string with the character class and a list of stats. It should calculate which level is required to get the desired character build and the amount of souls needed to do so. The result should be a string in the format: `'Starting as a [CLASS], level [N] will require [M] souls.'` where `[CLASS]` is your starting class, `[N]` is the required level, and `[M]` is the amount of souls needed respectively.

Difficulty: introductory

Starter code:

def souls(character, build):
	

Solutions:
from itertools import accumulate

CHARACTERS = {
    "warrior": (4, [11, 8, 12, 13, 13, 11, 9, 9]),
    "knight": (5, [14, 10, 10, 11, 11, 10, 9, 11]),
    "wanderer": (3, [10, 11, 10, 10, 14, 12, 11, 8]),
    "thief": (5, [9, 11, 9, 9, 15, 10, 12, 11]),
    "bandit": (4, [12, 8, 14, 14, 9, 11, 8, 10]),
    "hunter": (4, [11, 9, 11, 12, 14, 11, 9, 9]),
    "sorcerer": (3, [8, 15, 8, 9, 11, 8, 15, 8]),
    "pyromancer": (1, [10, 12, 11, 12, 9, 12, 10, 8]),
    "cleric": (2, [11, 11, 9, 12, 8, 11, 8, 14]),
    "deprived": (6, [11, 11, 11, 11, 11, 11, 11, 11]),
}
REQUIRED_SOULS = list(
    accumulate(
        [0, 0, 673, 690, 707, 724, 741, 758, 775, 793, 811, 829]
        + [
            round(pow(x, 3) * 0.02 + pow(x, 2) * 3.06 + 105.6 * x - 895)
            for x in range(12, 1000)
        ]
    )
)

def souls(character, build):
    starting_level, stats = CHARACTERS[character]
    delta = sum(b - s for b, s in zip(build, stats))
    level = starting_level + delta
    souls = REQUIRED_SOULS[level] - REQUIRED_SOULS[starting_level]
    return f"Starting as a {character}, level {level} will require {souls} souls."

D = {"warrior":(4, 86), "knight":(5, 86), "wanderer":(3, 86), "thief":(5, 86), "bandit":(4, 86),
     "hunter":(4, 86), "sorcerer":(3, 82), "pyromancer":(1, 84), "cleric":(2, 84), "deprived":(6, 88)}

count = lambda x: round(pow(x, 3) * 0.02 + pow(x, 2) * 3.06 + 105.6 * x - 895)

memo = [0, 0, 673, 1363, 2070, 2794, 3535, 4293, 5068, 5861, 6672, 7501]
def need(level):
    while len(memo) <= level: memo.append(memo[-1] + count(len(memo)))
    return memo[level]

def souls(character, build):
    level, stats = D[character]
    goal = level + sum(build) - stats
    return f"Starting as a {character}, level {goal} will require {need(goal) - need(level)} souls."

CLASSES = {"warrior": {"stats": [11, 8, 12, 13, 13, 11, 9, 9], "lvl": 4},
           "knight": {"stats": [14, 10, 10, 11, 11, 10, 9, 11], "lvl": 5},
           "wanderer": {"stats": [10, 11, 10, 10, 14, 12, 11, 8], "lvl": 3},
           "thief": {"stats": [9, 11, 9, 9, 15, 10, 12, 11], "lvl": 5},
           "bandit": {"stats": [12, 8, 14, 14, 9, 11, 8, 10], "lvl": 4},
           "hunter": {"stats": [11, 9, 11, 12, 14, 11, 9, 9], "lvl": 4},
           "sorcerer": {"stats": [8, 15, 8, 9, 11, 8, 15, 8], "lvl": 3},
           "pyromancer": {"stats": [10, 12, 11, 12, 9, 12, 10, 8], "lvl": 1},
           "cleric": {"stats": [11, 11, 9, 12, 8, 11, 8, 14], "lvl": 2},
           "deprived": {"stats": [11, 11, 11, 11, 11, 11, 11, 11], "lvl": 6}}

def souls(character, build):
    required_lvl = sum(build) - sum(CLASSES[character]["stats"]) + CLASSES[character]["lvl"]
    souls_needed = sum([calc_exp(lvl) for lvl in range(CLASSES[character]["lvl"] + 1, required_lvl + 1)])
    return f"Starting as a {character}, level {required_lvl} will require {souls_needed} souls."

def calc_exp(lvl):
    return 673 + 17 * (lvl - 2) if lvl <= 8 else 775 + 18 * (lvl - 8) if lvl <= 11 else round(pow(lvl, 3) * 0.02 + pow(lvl, 2) * 3.06 + 105.6 * lvl - 895)

BASE = {
    "warrior": (4, 86), "knight": (5, 86), "wanderer": (3, 86), "thief": (5, 86), "bandit": (4, 86),
    "hunter": (4, 86), "sorcerer": (3, 82), "pyromancer": (1, 84), "cleric": (2, 84), "deprived": (6, 88)
}

def souls(s, a):
    n, b = BASE[s]
    m = sum(a) - b
    r = sum([673, 690, 707, 724, 741, 758, 775, 793, 811, 829][n-1:n+m-1]) +\
        sum(round(i**3 * 0.02 + i**2 * 3.06 + 105.6 * i - 895) for i in range(12, n + m + 1))
    return f"Starting as a {s}, level {n + m} will require {r} souls."

def f(x):
    return round(.02 * x ** 3 + 3.06 * x ** 2 + 105.6 * x - 895)

def souls(character, build):
    
    final_level = sum(build) - 83 + sum([1 if n in character else 0 for n in 'hissss'])
    start_level = 6 - sum([1 if n in character else 0 for n in "awful cccn"])
    souls_needed = sum([
        17 * l + 16 * 41 if l < 8 else 18 * l + 11 * 59 if l < 12 else f(l + 1) for l in range(start_level, final_level)
    ])
    
    return "Starting as a " + character + ", level " + str(final_level) + " will require " + str(souls_needed) + " souls."

classes={
    'warrior':(4,[11, 8, 12, 13, 13, 11, 9, 9]),
    'knight':(5,[14, 10, 10, 11, 11, 10, 9, 11]),
    'wanderer':(3,[10, 11, 10, 10, 14, 12, 11, 8]),
    'thief':(5,[9, 11, 9, 9, 15, 10, 12, 11]),
    'bandit':(4,[12, 8, 14, 14, 9, 11, 8, 10]),
    'hunter':(4,[11, 9, 11, 12, 14, 11, 9, 9]),
    'sorcerer':(3,[8, 15, 8, 9, 11, 8, 15, 8]),
    'pyromancer':(1,[10, 12, 11, 12, 9, 12, 10, 8]),
    'cleric':(2,[11, 11, 9, 12, 8, 11, 8, 14]),
    'deprived':(6,[11, 11, 11, 11, 11, 11, 11, 11])
}
levelup_souls=[0,0,673,690,707,724,741,758,775,793,811,829]

def souls(character, build):
    level,stats=classes[character]
    up_level=sum(build)-sum(stats)+level
    s=0
    for l in range(level+1,up_level+1):
        if l<12:
            s+=levelup_souls[l]
        else:
            s+=round(pow(l,3)*0.02+pow(l,2)*3.06+105.6*l-895)
    return 'Starting as a {}, level {} will require {} souls.'.format(character,up_level,s)

d = {
    'warrior':[4,[11, 8, 12, 13, 13, 11, 9, 9]], 
    'knight':[5,[14, 10, 10, 11, 11, 10, 9, 11]],
    'wanderer':[3,[10, 11, 10, 10, 14, 12, 11, 8]],
    'thief':[5,[9, 11, 9, 9, 15, 10, 12, 11]],
    'bandit':[4,[12, 8, 14, 14, 9, 11, 8, 10]],
    'hunter':[4,[11, 9, 11, 12, 14, 11, 9, 9]],
    'sorcerer':[3,[8, 15, 8, 9, 11, 8, 15, 8]],
    'pyromancer':[1,[10, 12, 11, 12, 9, 12, 10, 8]],
    'cleric':[2,[11, 11, 9, 12, 8, 11, 8, 14]],
    'deprived':[6,[11, 11, 11, 11, 11, 11, 11, 11]]
    }

def souls(character, build):
    l = d[character][0]
    p = sum(d[character][1])
    ap = sum(build)
    al = l + ap - p
    s = 0
    for i in range(l+1,al+1):
        if i<=8:
            s = s + 673 + 17*(i-2)
        elif i<=11:
            s = s + 775 + 18*(i-8)
        else:
            s = s + round(pow(i, 3) * 0.02 + pow(i, 2) * 3.06 + 105.6 * (i) - 895)
    return "Starting as a {}, level {} will require {} souls.".format(character,al,s)
        
        
        


def last_level():
    x = 12
    formul_level = lambda x: round(pow(x, 3) * 0.02 + pow(x, 2) * 3.06 + 105.6 * x - 895)
    list_level = [0, 673, 690, 707, 724, 741, 758, 775, 793, 811, 829]
    for i in list_level:
        yield i
    while True:
        yield formul_level(x)
        x += 1
        
        
def souls(character, build):
    base_class = {
     'warrior'    : (4, [11, 8, 12, 13, 13, 11, 9, 9]),
     'knight'     : (5, [14, 10, 10, 11, 11, 10, 9, 11]),
     'wanderer'   : (3, [10, 11, 10, 10, 14, 12, 11, 8]),
     'thief'      : (5, [9, 11, 9, 9, 15, 10, 12, 11]),
     'bandit'     : (4, [12, 8, 14, 14, 9, 11, 8, 10]),
     'hunter'     : (4, [11, 9, 11, 12, 14, 11, 9, 9]),
     'sorcerer'   : (3, [8, 15, 8, 9, 11, 8, 15, 8]),
     'pyromancer' : (1, [10, 12, 11, 12, 9, 12, 10, 8]),
     'cleric'     : (2, [11, 11, 9, 12, 8, 11, 8, 14]),
     'deprived'   : (6, [11, 11, 11, 11, 11, 11, 11, 11])
    }
    souls_level = last_level()
    paramets = base_class[character]
    souls = filter(lambda i: i > 0, (b - s for s,b in zip(paramets[1], build)))
    level = sum(souls) + paramets[0] 
    souls = sum([next(souls_level) for i in range(level)][paramets[0]:]) 
    return "Starting as a {0}, level {1} will require {2} souls.".format(character, level, souls)

def souls(character, build):
    
    DICT={'pyromancer':(1,[10, 12, 11, 12, 9, 12, 10, 8]),
          'warrior':(4,[11, 8, 12, 13, 13, 11, 9, 9]),
          'knight':(5,[14, 10, 10, 11, 11, 10, 9, 11]),
          'wanderer':(3,[10, 11, 10, 10, 14, 12, 11, 8]),
          'thief':(5,[9, 11, 9, 9, 15, 10, 12, 11]),
          'bandit':(4,[12, 8, 14, 14, 9, 11, 8, 10]),
          'hunter':(4,[11, 9, 11, 12, 14, 11, 9, 9]),
          'sorcerer':(3,[8, 15, 8, 9, 11, 8, 15, 8]),
          'cleric':(2,[11, 11, 9, 12, 8, 11, 8, 14]),
          'deprived':(6,[11, 11, 11, 11, 11, 11, 11, 11])
          }
    
    
    list_upgrade_souls=[673, 690, 707, 724, 741, 758, 775, 793, 811,829]
    levels_after_11 = [round(pow(x+12, 3) * 0.02 + pow(x+12, 2) * 3.06 + 105.6 * (x+12) - 895) for x in range(5000)]
    list_upgrade_souls.extend(levels_after_11)
    cnt_souls=0
    
    actual_powers=DICT[character][1]
    actual_level=DICT[character][0]
    desired_level=sum([x1 - x2 for (x1, x2) in zip(build, actual_powers)]) + actual_level
    for i in range(actual_level-1,desired_level-1):
        cnt_souls+=list_upgrade_souls[i]

    return 'Starting as a {}, level {} will require {} souls.'.format(character,desired_level,cnt_souls)
    


classes = {
    "warrior":     {"start": 4,  "stats": [11, 8, 12, 13, 13, 11, 9, 9]},
    "knight":      {"start": 5,  "stats": [14, 10, 10, 11, 11, 10, 9, 11]},
    "wanderer":    {"start": 3,  "stats": [10, 11, 10, 10, 14, 12, 11, 8]},
    "thief":       {"start": 5,  "stats": [9, 11, 9, 9, 15, 10, 12, 11]},
    "bandit":      {"start": 4,  "stats": [12, 8, 14, 14, 9, 11, 8, 10]},
    "hunter":      {"start": 4,  "stats": [11, 9, 11, 12, 14, 11, 9, 9]},
    "sorcerer":    {"start": 3,  "stats": [8, 15, 8, 9, 11, 8, 15, 8]},
    "pyromancer":  {"start": 1,  "stats": [10, 12, 11, 12, 9, 12, 10, 8]},
    "cleric":      {"start": 2,  "stats": [11, 11, 9, 12, 8, 11, 8, 14]},
    "deprived":    {"start": 6,  "stats": [11, 11, 11, 11, 11, 11, 11, 11]},
}

requirements = [0, 673, 690, 707, 724, 741, 758, 775, 793, 811, 829]

def souls(character, build):
    diff = sum(b - s for b, s in zip(build, classes[character]["stats"]))
    level = classes[character]["start"] + diff
    required = sum(x for x in requirements[classes[character]["start"]:level])
    required += sum(round(0.02*x**3+3.06*x**2+105.6*x-895) for x in range(12, level+1))
    return "Starting as a {}, level {} will require {} souls.".format(character, level, required)