10000 chore: no dash in filenames · benmtz/codewars-python@31cbde8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 31cbde8

Browse files
committed
chore: no dash in filenames
1 parent ef1446e commit 31cbde8

12 files changed

+218
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# 51fda2d95d6efda45e00004e
2+
#
3+
# Write a class called User that is used to calculate the amount that a user
4+
# will progress through a ranking system similar to the one Codewars uses.
5+
#
6+
# Business Rules:
7+
#
8+
# A user starts at rank -8 and can progress all the way to 8.
9+
# There is no 0 (zero) rank. The next rank after -1 is 1.
10+
# Users will complete activities. These activities also have ranks.
11+
# Each time the user completes a ranked activity the users rank progress is
12+
# updated based off of the activity's rank
13+
# The progress earned from the completed activity is relative to what the
14+
# user's current rank is compared to the rank of the activity
15+
# A user's rank progress starts off at zero, each time the progress reaches
16+
# 100 the user's rank is upgraded to the next level
17+
# Any remaining progress earned while in the previous rank will be applied
18+
# towards the next rank's progress (we don't throw any progress away).
19+
# The exception is if there is no other rank left to progress towards
20+
# (Once you reach rank 8 there is no more progression). A user cannot progress
21+
# beyond rank 8.
22+
# The only acceptable range of rank values is
23+
# -8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8. Any other value should raise an error.
24+
# The progress is scored like so:
25+
#
26+
# Completing an activity that is ranked the same as that of the user's will be
27+
# worth 3 points
28+
# Completing an activity that is ranked one ranking lower than the user's will
29+
# be worth 1 point
30+
# Any activities completed that are ranking 2 levels or more lower than the
31+
# user's ranking will be ignored
32+
# Completing an activity ranked higher than the current user's rank will
33+
# accelerate the rank progression. The greater the difference between rankings
34+
# the more the progression will be increased. The formula is 10 * d * d where
35+
# d equals the difference in ranking between the activity and the user.
36+
#
37+
# Logic Examples:
38+
# If a user ranked -8 completes an activity ranked -7
39+
# they will receive 10 progress
40+
# If a user ranked -8 completes an activity ranked -6
41+
# they will receive 40 progress
42+
# If a user ranked -8 completes an activity ranked -5
43+
# they will receive 90 progress
44+
# If a user ranked -8 completes an activity ranked -4
45+
# they will receive 160 progress, resulting in the user being upgraded to
46+
# rank -7 and having earned 60 progress towards their next rank
47+
# If a user ranked -1 completes an activity ranked 1
48+
# they will receive 10 progress (remember, zero rank is ignored)
49+
#
50+
# Code Usage Examples:
51+
# user = User()
52+
# user.rank # => -8
53+
# user.progress # => 0
54+
# user.inc_progress(-7)
55+
# user.progress # => 10
56+
# user.inc_progress(-5) # will add 90 progress
57+
# user.progress # => 0 # progress is now zero
58+
# user.rank # => -7 # rank was upgraded to -7
59+
#
60+
# Note: Codewars no longer uses this algorithm for its own ranking system.
61+
# It uses a pure Math based solution that gives consistent results no matter
62+
# what order a set of ranked activities are completed at.
63+
64+
from unittest import TestCase
65+
66+
ranks = list(range(-8, 0)) + list(range(1, 9))
67+
68+
class User:
69+
70+
# Using a getter take abstraction of the no 0 rank rule
71+
def get_rank(self):
72+
return ranks[self.rank_index]
73+
rank = property(get_rank)
74+
75+
def __init__(self):
76+
self.rank_index = 0
77+
self.progress = 0
78+
79+
def get_progress_points(self, new_rank_index):
80+
rank_diff = new_rank_index - self.rank_index
81+
print("rank_diff: {}, new_index: {}, current_index: {}".format(rank_diff, new_rank_index, self.rank_index))
82+
if rank_diff <= -2:
83+
return 0
84+
elif rank_diff == -1:
85+
return 1
86+
elif rank_diff == 0:
87+
return 3
88+
else:
89+
return 10 * rank_diff * rank_diff
90+
91+
def level_up(self):
92+
self.progress -= 100
93+
self.rank_index += 1
94+
if self.rank == 8:
95+
self.progress = 0
96+
97+
def inc_progress(self, rank):
98+
print("u: {}, ex: {}".format(self.rank, rank))
99+
new_rank_index = ranks.index(rank)
100+
print("new_rank is {} ({})".format(new_rank_index, ranks[new_rank_index]))
101+
self.progress += self.get_progress_points(new_rank_index)
102+
print("before level flushing: {}".format(self.progress))
103+
while self.progress >= 100:
104+
self.level_up()
105+
print("levelup - new progress: {} - new rank: {}".format(self.progress, self.rank))
106+
107+
108+
class Test4CodewarsStyleRankingSystem(TestCase):
109+
def test_1(self):
110+
user = User()
111+
self.assertEqual(user.rank, -8)
112+
self.assertEqual(user.progress, 0)
113+
user.inc_progress(-7)
114+
self.assertEqual(user.progress, 10)
115+
user.inc_progress(-5)
116+
self.assertEqual(user.progress, 0)
117+
self.assertEqual(user.rank, -7)

katas/4_magnet_particules_in_boxes.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from unittest import TestCase
2+
from functools import lru_cache
3+
4+
5+
@lru_cache(maxsize=None)
6+
def cached_pow(nb, pow):
7+
return nb ** pow
8+
9+
@lru_cache(maxsize=None)
10+
def box_force(k, n):
11+
return 1 / (k * cached_pow(n + 1, 2 * k))
12+
13+
14+
def doubles(maxk, maxn):
15+
return sum([box_force(k, n) for k in range(1, maxk + 1) for n in range(1, maxn + 1)])
16+
17+
18+
class TestDoubles(TestCase):
19+
20+
def assertFuzzyEquals(self, actual, expected, msg=""):
21+
merr = 1e-9
22+
msg = "Tested at 1e-9; Expected value must be {:0.16f} but got {:0.16f}".format(expected, actual)
23+
return self.assertAlmostEqual(actual, expected, delta=merr, msg=msg)
24+
25+
def test_box_force(self):
26+
self.assertEqual(box_force(1, 1), 0.25)
27+
28+
def test_basic(self):
29+
self.assertFuzzyEquals(doubles(20, 10000), 0.6930471955575918)
30+
31+
def test_basic_2(self):
32+
self.assertFuzzyEquals(doubles(1, 10), 0.5580321939764581)
33+
self.assertFuzzyEquals(doubles(10, 1000), 0.6921486500921933)
34+
self.assertFuzzyEquals(doubles(10, 10000), 0.6930471674194457)
35+
36+
37+
def test_long(self):
38+
doubles(40, 150000)

katas/4_range_extraction.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# 51ba717bb08c1cd60f00002f
2+
#
3+
# A format for expressing an ordered list of integers is to use a comma separated list of either
4+
#
5+
# * individual integers
6+
# * or a range of integers denoted by the starting integer separated from the end integer in the range by a dash, '-'.
7+
# The range includes all integers in the interval including both endpoints. It is not considered a range unless it
8+
# spans at least 3 numbers. For example "12,13,15-17" Complete the solution so that it takes a list of integers in
9+
# increasing order and returns a correctly formatted string in the range format.
10+
#
11+
# Example:
12+
#
13+
# solution([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20])
14+
# # returns "-6,-3-1,3-5,7-11,14,15,17-20"
15+
from itertools import groupby
16+
import unittest
17+
from unittest import TestCase
18+
19+
20+
def stringify_pair(r):
21+
if r[0] == r[1]:
22+
return str(r[0])
23+
elif r[1] - r[0] >= 2:
24+
return f"{r[0]}-{r[1]}"
25+
else:
26+
return ",".join([str(u) for u in range(r[0], r[1] + 1)])
27+
28+
29+
def stringify_ranges(ranges):
30+
return ",".join([stringify_pair(x) for x in ranges])
31+
32+
33+
def ranges(integers):
34+
def group_by_function(pair):
35+
return pair[1] - pair[0]
36+
37+
# It's brilliant, but sadly not mine, found it here :
38+
# https://stackoverflow.com/questions/4628333/converting-a-list-of-integers-into-range-in-python
39+
# However it may be error prone in real world code
40+
for a, b in groupby(enumerate(integers), group_by_function):
41+
# This makes a subgroup calling the grouper once again
42+
b = list(b)
43+
yield b[0][1], b[-1][1]
44+
45+
46+
def solution(args):
47+
return stringify_ranges(ranges(args))
48+
49+
50+
class SolutionTest(TestCase):
51+
52+
def test_basic_cases(self):
53+
self.assertEqual(solution([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]),
54+
'-6,-3-1,3-5,7-11,14,15,17-20')
55+
self.assertEqual(solution([-3, -2, -1, 2, 10, 15, 16, 18, 19, 20]), '-3--1,2,10,15,16,18-20')
56+
57+
58+
if __name__ == "__main__":
59+
unittest.main()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)
0