View difference between Paste ID: atakgace and umZNT4LN
SHOW: | | - or go back to the newest paste.
1
# --------------     tasks/escher_tasks/task_9__treasures.py   ----------------
2
3
4
def treasures(info, limit):
5-
    return []
5+
6
    limit = int(limit * 1000)
7
    keys = sorted(info,
8
                  key=lambda k: info[k]["price"] / info[k]["weight"],
9
                  reverse=True)
10
11
    res = {}
12-
from tasks.escher_tasks.task_9__treasures import treasures
12+
    for k in keys:
13
        can_take = limit // info[k]["weight"]
14
        will_take = min(can_take, info[k]["amount"])
15-
def test_treasures():
15+
        res[k] = will_take
16
        limit -= will_take * info[k]["weight"]
17-
    assert treasures(
17+
18
    return [f"{k}: {res[k]}" for k in info if res[k] > 0]
19
20
21
from itertools import product
22
23-
    assert treasures(
23+
24
def treasures_2(info, limit):
25
26
    limit = int(limit * 1000)
27
28
    counts = {}
29
    for k in info:
30
        can_put = limit // info[k]["weight"]
31
        will_put = min(can_put, info[k]["amount"])
32
        counts[k] = will_put
33
34
    res = [0 for _ in info]
35
    best_price = 0
36
37
    for combination in product(*[range(counts[k] + 1) for k in info]):
38
        total_price = sum([amount * info[k]["price"]
39
                           for k, amount in zip(info, combination)])
40
        total_weight = sum([amount * info[k]["weight"]
41
                            for k, amount in zip(info, combination)])
42
43
        if total_weight <= limit and total_price > best_price:
44
            res = combination
45
            best_price = total_price
46
47
    return [f"{k}: {count}" for k, count in zip(info, res) if count]
48
49
50
def treasures_3(info, limit):
51
52
    limit = int(limit * 1000)
53
    best_results = [[0 for _ in info]]
54
55
    for i in range(1, limit + 1):
56
        results = [best_results[-1].copy()]
57
58
        for _idx, k in enumerate(info):
59
            if i < info[k]["weight"]:
60
                continue
61
62
            res = best_results[i - info[k]["weight"]].copy()
63
            res[_idx] += 1
64
            if res[_idx] > info[k]["amount"]:
65
                continue
66
            results.append(res)
67
68
        get_price = lambda res: sum(i * info[k]["price"]
69
                                    for i, k in zip(res, info))
70
        best_results.append(max(results, key=get_price))
71
72
    return [f"{k}: {i}" for k, i in zip(info, best_results[-1]) if i]
73
74
75
# ----------------  tests/test_escher_tasks/test_task_9__treasures.py ------------------
76
77
78
import pytest
79
from tasks.escher_tasks.task_9__treasures import (
80
    treasures, treasures_2, treasures_3)
81
82
83
@pytest.mark.parametrize("func", [treasures, treasures_2, treasures_3])
84
def test_treasures(func):
85
86
    assert func(
87
        {'golden coin': {'price': 100, 'weight': 50, 'amount': 200},
88
         'silver coin': {'price': 10, 'weight': 20, 'amount': 1000},
89
         'ruby': {'price': 1000, 'weight': 200, 'amount': 2}}, 5
90
    ) == ['golden coin: 92', 'ruby: 2']
91
92
    assert func(
93
        {'golden coin': {'price': 100, 'weight': 50, 'amount': 100},
94
         'silver coin': {'price': 10, 'weight': 20, 'amount': 100},
95
         'ruby': {'price': 1000, 'weight': 200, 'amount': 1}}, 7.5
96
    ) == ['golden coin: 100', 'silver coin: 100', 'ruby: 1']
97