Passed
Push — master ( d0203a...db8646 )
by Ken M.
01:09
created

colder_warmer.checkio()   C

Complexity

Conditions 11

Size

Total Lines 34
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 31
nop 1
dl 0
loc 34
rs 5.4
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like colder_warmer.checkio() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
from collections import defaultdict
2
from math import hypot
3
from random import choice
4
5
6
possible_positions = [(i, j) for i in range(10) for j in range(10)]
7
8
9
def distance(point_1, point_2):
10
    return hypot(point_2[0] - point_1[0], point_2[1] - point_1[1])
11
12
13
def checkio(steps):
14
    global possible_positions
15
    previous_distance = defaultdict(int)
16
17
    if len(steps) == 1:
18
        possible_positions = [(i, j) for i in range(10) for j in range(10)]
19
        possible_positions.remove(tuple(steps[0][:2]))
20
        for i in possible_positions:
21
            previous_distance[i] = distance(tuple(steps[0][:2]), i)
22
        max_distance = max(previous_distance.values())
23
        candidates = [
24
            cell for cell, value in previous_distance.items() if value == max_distance
25
        ]
26
        next_step = choice(candidates)
27
        possible_positions.remove(next_step)
28
        return next_step
29
30
    last_step = tuple(steps[-1][:2])
31
    last_feedback = steps[-1][-1]
32
    disqualified = []
33
    for i in possible_positions:
34
        last_distance = distance(tuple(steps[-2][:2]), i)
35
        current_distance = distance(last_step, i)
36
        if last_feedback == -1 and last_distance >= current_distance:
37
            disqualified.append(i)
38
        elif last_feedback == 0 and last_distance != current_distance:
39
            disqualified.append(i)
40
        elif last_feedback == 1 and last_distance <= current_distance:
41
            disqualified.append(i)
42
    for i in disqualified:
43
        possible_positions.remove(i)
44
    next_step = choice(possible_positions)
45
    possible_positions.remove(next_step)
46
    return next_step
47
48
49
if __name__ == '__main__':
50
    # This part is using only for self-checking and not necessary for
51
    # auto-testing
52
    MAX_STEP = 12
53
54 View Code Duplication
    def check_solution(func, goal, start):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
55
        prev_steps = [start]
56
        for step in range(MAX_STEP):
57
            row, col = func([s[:] for s in prev_steps])
58
            if [row, col] == goal:
59
                return True
60
            if 10 <= row or 0 > row or 10 <= col or 0 > col:
61
                print("You gave wrong coordinates.")
62
                return False
63
            prev_distance = hypot(
64
                prev_steps[-1][0] - goal[0], prev_steps[-1][1] - goal[1]
65
            )
66
            distance = hypot(row - goal[0], col - goal[1])
67
            alteration = (
68
                0
69
                if prev_distance == distance
70
                else (1 if prev_distance > distance else -1)
71
            )
72
            prev_steps.append([row, col, alteration])
73
        print("Too many steps")
74
        return False
75
76
    assert check_solution(checkio, [7, 7], [5, 5, 0]), "1st example"
77
    assert check_solution(checkio, [5, 6], [0, 0, 0]), "2nd example"
78