Skip to content

Commit 83fb24f

Browse files
authored
Add files via upload
1 parent eb7b59c commit 83fb24f

22 files changed

+2522
-0
lines changed

02/__pycache__/ib111.cpython-311.pyc

57 KB
Binary file not shown.

02/cards.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from ib111 import week_02 # noqa
2+
3+
# Predicte ‹is_visa›, is True, when parameter number is valid VISA card number
4+
# It starts with 4, and has 13, 16, or 19 numerals and is valid number from <credit> file
5+
6+
def is_visa(number):
7+
length = get_length(number)
8+
if number // 10 ** (length - 1) != 4:
9+
return False
10+
if length != 13 and length != 16 and length != 19:
11+
return False
12+
if not is_valid_card(number):
13+
return False
14+
15+
return True
16+
17+
def is_valid_card(number):
18+
control = number % 10
19+
number //= 10
20+
index = 2
21+
sumVal = 0
22+
while number > 0:
23+
if index % 2 == 0:
24+
value = number % 10
25+
if (value * 2) > 9:
26+
value = (value * 2) - 9
27+
sumVal += value
28+
else:
29+
sumVal += value * 2
30+
else:
31+
sumVal += number % 10
32+
index += 1
33+
number //= 10
34+
if (sumVal + control) % 10 == 0:
35+
return True
36+
return False
37+
38+
def get_length(number):
39+
count = 0
40+
while number > 0:
41+
number //= 10
42+
count += 1
43+
return count
44+
45+
# Predicate <is_mastercard> is True, when number is valid Mastercard number
46+
# Thats: starts with 50–55, or 22100–27209, has 16 numerals and is valid credit card number
47+
48+
def is_mastercard(number):
49+
length = get_length(number)
50+
if length != 16:
51+
return False
52+
value = number // 10 ** (length - 2)
53+
if value >= 50 and value <= 55:
54+
return True
55+
value = number // 10 ** (length - 5)
56+
if value >= 22100 and value <= 27209:
57+
return True
58+
return False
59+
60+
def main(): # run simple tests
61+
assert is_visa(4111111111111111)
62+
assert is_visa(4012888888881881)
63+
assert is_visa(4988438843884305)
64+
assert is_visa(4646464646464644)
65+
assert is_visa(4199350000000002)
66+
assert is_visa(4222222222222)
67+
assert is_visa(4111111111111111110)
68+
69+
assert not is_visa(411111111111116)
70+
assert not is_visa(5500000000000004)
71+
assert not is_visa(4929300836739328)
72+
73+
assert is_mastercard(5500000000000004)
74+
assert is_mastercard(5555555555554444)
75+
assert is_mastercard(5105105105105100)
76+
assert is_mastercard(5424000000000015)
77+
assert is_mastercard(2223520443560010)
78+
assert is_mastercard(5101180000000007)
79+
assert is_mastercard(2222400070000005)
80+
81+
assert not is_mastercard(4012888888881881)
82+
assert not is_mastercard(22004000700000003)
83+
assert not is_mastercard(5624000000000013)
84+
assert not is_mastercard(2721000030000016)
85+
assert not is_mastercard(5101180000000000003)
86+
87+
88+
if __name__ == "__main__":
89+
main()

02/comb.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from ib111 import week_02 # noqa
2+
from math import factorial
3+
4+
5+
# Consider combination numbers, defined like:
6+
# ⟦ (n¦k) = n! / (k! ⋅ (n - k)!) ⟧
7+
8+
# where ⟦k ≤ n⟧. Factorial is defined: ⟦ n! = ∏ᵢ₌₁ⁿi ⟧
9+
10+
# That means:
11+
# ⟦ n! / k! = ∏ᵢ₌₁ⁿ i / ∏ᵢ₌₁ᵏ i = ∏ᵢ₌ₖ₊₁ⁿ i ⟧
12+
13+
def comb_for(n, k):
14+
# Find smaller from ⟦k⟧ and ⟦n - k⟧
15+
# where ⟦(n¦k) = (n¦n-k)⟧.
16+
if k < n - k:
17+
k = n - k
18+
19+
# Multiply all numbers between ⟦k⟧ and ⟦n⟧ excluding k and including n
20+
numerator = 1
21+
for i in range(k + 1, n + 1):
22+
numerator *= i
23+
24+
return numerator // factorial(n - k)
25+
26+
# Eqvivalent definition but using ‹while› cycle:
27+
def comb_while(n, k):
28+
if k < n - k:
29+
k = n - k
30+
31+
numerator = 1
32+
i = k + 1
33+
34+
while i <= n:
35+
numerator *= i
36+
i += 1
37+
38+
return numerator // factorial(n - k)
39+
40+
def main(): # run tests in cycle
41+
for n in range(1, 50):
42+
for k in range(1, n):
43+
naive = factorial(n) // (factorial(k) * factorial(n - k))
44+
assert comb_for(n, k) == naive
45+
assert comb_while(n, k) == naive
46+
47+
48+
if __name__ == '__main__':
49+
main()

02/credit.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from ib111 import week_02 # noqa
2+
3+
# Predicate checks valid credit card number using Luhn algorithm:
4+
# 1. Double every second value from right side; if value >9 deduct 9
5+
# 2. Sum all numbers from 1. and on odd indexes excluding first from right
6+
# 3. NUmber is valid if sum of all numbers is divisible by 10.
7+
8+
# For 28316 control number is 6 and sum:
9+
# ⟦2 + (2⋅8 - 9) + 3 + 2⋅1 = 2 + 7 + 3 + 2 = 14⟧.
10+
# After adding control number, sum is 20 which is divisible with 10
11+
# and number is thus valid.
12+
13+
def is_valid_card(number):
14+
control = number % 10
15+
number //= 10
16+
index = 2
17+
sumVal = 0
18+
while number > 0:
19+
if index % 2 == 0:
20+
value = number % 10
21+
if (value * 2) > 9:
22+
value = (value * 2) - 9
23+
sumVal += value
24+
else:
25+
sumVal += value * 2
26+
else:
27+
sumVal += number % 10
28+
index += 1
29+
number //= 10
30+
if (sumVal + control) % 10 == 0:
31+
return True
32+
return False
33+
34+
def main():
35+
assert is_valid_card(28316)
36+
assert is_valid_card(4556737586899855)
37+
assert is_valid_card(4929599116478604)
38+
assert is_valid_card(4929300836739668)
39+
assert not is_valid_card(4929300835539668)
40+
assert not is_valid_card(4929300836739328)
41+
assert not is_valid_card(5101180000000000007)
42+
43+
assert is_valid_card(5294967072531977)
44+
assert is_valid_card(5354598557505686)
45+
assert is_valid_card(2720993849498580)
46+
47+
48+
if __name__ == "__main__":
49+
main()

02/delete.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from ib111 import week_02 # noqa
2+
3+
# Function ‹delete_to_maximal› for ‹number› returns biggest
4+
# value by deleting one decimal digit in number.
5+
6+
def delete_to_maximal(number):
7+
original_number = number
8+
current_power_of_ten = 1
9+
max_number = float('-inf') # Initialize to smallest number
10+
11+
while current_power_of_ten <= original_number:
12+
left_part = number // (current_power_of_ten * 10)
13+
right_part = number % current_power_of_ten
14+
new_number = left_part * current_power_of_ten + right_part
15+
max_number = max(max_number, new_number)
16+
current_power_of_ten *= 10
17+
18+
return max_number
19+
20+
def get_length(num):
21+
count = 0
22+
while num > 0:
23+
num //= 10
24+
count += 1
25+
return count
26+
27+
# Function ‹delete_k_to_maximal› returns biggest number created by deleting <k> digits:
28+
29+
def delete_k_to_maximal(number, k):
30+
result = number
31+
for i in range(k):
32+
result = delete_to_maximal(result)
33+
34+
return result
35+
36+
def main():
37+
assert delete_to_maximal(54) == 5
38+
assert delete_to_maximal(45) == 5
39+
assert delete_to_maximal(100) == 10
40+
assert delete_to_maximal(123) == 23
41+
assert delete_to_maximal(4312) == 432
42+
assert delete_to_maximal(1231) == 231
43+
assert delete_to_maximal(2331) == 331
44+
45+
assert delete_k_to_maximal(2331, 2) == 33
46+
assert delete_k_to_maximal(22331, 2) == 331
47+
assert delete_k_to_maximal(12345, 4) == 5
48+
assert delete_k_to_maximal(1234554321, 8) == 55
49+
assert delete_k_to_maximal(123123123123, 4) == 33123123
50+
assert delete_k_to_maximal(123321123321, 4) == 33223321
51+
assert delete_k_to_maximal(11181118111, 9) == 88
52+
53+
54+
if __name__ == "__main__":
55+
main()

02/descending.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from ib111 import week_02 # noqa
2+
3+
# Function that checks if digits in number are descending in value.
4+
# For example "321" or "775" is True but "123" is False
5+
6+
# ‹get_digit› gets digit value on k-index:
7+
def get_digit(number, k):
8+
return (number // 10 ** k) % 10
9+
10+
# Each division by 10 "removes" one digit, thus in counter remains number of digits:
11+
def count_digits(number):
12+
count = 0
13+
while number > 0:
14+
count += 1
15+
number = number // 10
16+
return count
17+
18+
# Main function that calls helper functions:
19+
def is_descending(number):
20+
for k in range(count_digits(number) - 1):
21+
if get_digit(number, k + 1) < get_digit(number, k):
22+
return False
23+
24+
return True
25+
26+
def main(): # Run simple tests
27+
assert is_descending(7)
28+
assert is_descending(321)
29+
assert is_descending(33222111)
30+
assert is_descending(9999)
31+
assert is_descending(7741)
32+
assert not is_descending(123)
33+
assert not is_descending(332233)
34+
assert not is_descending(774101)
35+
36+
if __name__ == "__main__":
37+
main()

02/digit_sum.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from ib111 import week_02 # noqa
2+
3+
# ‹power_digit_sum›, returns special digit sum of ‹number›
4+
# Each number exponentiate to the value of the index
5+
# Numbering from left where index of first digit has value 1
6+
# ‹power_digit_sum› calculation will be done in seven-base.
7+
8+
# Example: number ⟦1234⟧ is seven base is: ⟦(3412)₇⟧ – ⟦3⋅7³ + 4⋅7² + 1⋅7¹ + 2⋅7⁰ = 1029
9+
# + 196 + 7 + 2 = 1234⟧. ‹power_digit_sum(1234)› gets us ⟦3¹ + 4² + 1³ + 2⁴ = 36⟧.
10+
11+
def power_digit_sum(number):
12+
value = to_seven_base(number)
13+
sum_val = 0
14+
length = get_length(value)
15+
for i in range(1, length + 1):
16+
digit = get_digit(value, i)
17+
sum_val += digit ** (length - i + 1)
18+
return sum_val
19+
20+
# Convert decimal number to seven-base number
21+
def to_seven_base(number):
22+
if number == 0:
23+
return 0
24+
value = 0
25+
power = 1
26+
while number > 0:
27+
value += number % 7 * power
28+
number //= 7
29+
power *= 10
30+
31+
return value
32+
33+
def get_length(number):
34+
count = 0
35+
while number > 0:
36+
number //= 10 # Count digits in decimal numbre
37+
count += 1
38+
return count
39+
40+
def get_digit(number, index):
41+
digit = 0
42+
for _ in range(1, index + 1):
43+
digit = number % 10 # Get digit in decimal number
44+
number //= 10
45+
return digit
46+
47+
def main() -> None: # run tests
48+
assert power_digit_sum(7) == 1
49+
assert power_digit_sum(1234) == 36
50+
assert power_digit_sum(333) == 95
51+
assert power_digit_sum(52891) == 46693
52+
53+
54+
if __name__ == "__main__":
55+
main()

02/digits.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from ib111 import week_02 # noqa
2+
3+
# ‹count_digit_in_sequence›, returns how many times ‹digit›
4+
# occurs in numbers in interval from <low> to <hight> including.
5+
6+
def count_digit_in_sequence(digit, low, high):
7+
counter = 0
8+
for i in range(low, high + 1):
9+
for x in range(1, count_digits(i) + 1):
10+
if get_digit(i, x) == digit:
11+
counter += 1
12+
13+
return counter
14+
15+
def count_digits(number):
16+
counter = 0
17+
if number == 0:
18+
return 1
19+
while number > 0:
20+
number //= 10
21+
counter += 1
22+
return counter
23+
24+
def get_digit(number, index):
25+
digit = 0
26+
while index > 0:
27+
digit = number % 10
28+
number //= 10
29+
index -= 1
30+
return digit
31+
32+
def main(): # run tests
33+
assert count_digit_in_sequence(1, 0, 13) == 6
34+
assert count_digit_in_sequence(0, 10, 20) == 2
35+
assert count_digit_in_sequence(0, 0, 10) == 2
36+
assert count_digit_in_sequence(4, 15, 23) == 0
37+
assert count_digit_in_sequence(5, 20, 120) == 20
38+
assert count_digit_in_sequence(0, 10, 100) == 11
39+
assert count_digit_in_sequence(2, 111, 1000) == 279
40+
41+
42+
if __name__ == "__main__":
43+
main()

0 commit comments

Comments
 (0)