| Conditions | 17 |
| Total Lines | 58 |
| Code Lines | 36 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like magic_domino.check_data() 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 | import operator as op |
||
| 105 | def check_data(size, number, user_result): |
||
| 106 | |||
| 107 | # check types |
||
| 108 | def check_container_type(o): |
||
| 109 | return any(map(lambda t: isinstance(o, t), (list, tuple))) |
||
| 110 | |||
| 111 | def check_cell_type(i): |
||
| 112 | return isinstance(i, int) |
||
| 113 | |||
| 114 | if not ( |
||
| 115 | check_container_type(user_result) |
||
| 116 | and all(map(check_container_type, user_result)) |
||
| 117 | and all(map(lambda row: all(map(check_cell_type, row)), user_result)) |
||
| 118 | ): |
||
| 119 | raise Exception( |
||
| 120 | "You should return a list/tuple of lists/tuples with integers." |
||
| 121 | ) |
||
| 122 | |||
| 123 | # check sizes |
||
| 124 | def check_size(o): |
||
| 125 | return len(o) == size |
||
| 126 | |||
| 127 | if not (check_size(user_result) and all(map(check_size, user_result))): |
||
| 128 | raise Exception("Wrong size of answer.") |
||
| 129 | |||
| 130 | # check is it a possible numbers (from 0 to 6 inclusive) |
||
| 131 | if not all( |
||
| 132 | map(lambda x: 0 <= x <= 6, itertools.chain.from_iterable(user_result)) |
||
| 133 | ): |
||
| 134 | raise Exception("Wrong matrix integers (can't be domino tiles)") |
||
| 135 | |||
| 136 | # check is it a magic square |
||
| 137 | def seq_sum_check(seq): |
||
| 138 | return sum(seq) == number |
||
| 139 | |||
| 140 | diagonals_indexes = zip( |
||
| 141 | *map(lambda i: ((i, i), (i, size - i - 1)), range(size)) |
||
| 142 | ) |
||
| 143 | |||
| 144 | def values_from_indexes(inds): |
||
| 145 | return itertools.starmap(lambda x, y: user_result[y][x], inds) |
||
| 146 | |||
| 147 | if not ( |
||
| 148 | all(map(seq_sum_check, user_result)) |
||
| 149 | and all(map(seq_sum_check, zip(*user_result))) # rows |
||
| 150 | and all( # columns |
||
| 151 | map(seq_sum_check, map(values_from_indexes, diagonals_indexes)) |
||
| 152 | ) |
||
| 153 | ): # diagonals |
||
| 154 | raise Exception("It's not a magic square.") |
||
| 155 | |||
| 156 | # check is it domino square |
||
| 157 | tiles = set() |
||
| 158 | for x, y in itertools.product(range(size), range(0, size, 2)): |
||
| 159 | tile = tuple(sorted((user_result[y][x], user_result[y + 1][x]))) |
||
| 160 | if tile in tiles: |
||
| 161 | raise Exception("It's not a domino magic square.") |
||
| 162 | tiles.add(tile) |
||
| 163 | |||
| 165 |