String manipulation
Source
Description
String manipulation functions for an “inventory management system.”
My solution
1
import pytest
Simple checksum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def contains_n_any(mystr, n):
'''
Return True if `mystr` contains any character repeated exactly
`n` times, otherwise false.
'''
if not mystr or n <= 0:
return False
for char in mystr:
if mystr.count(char) == n:
return True
return False
def checksum(strs, reps):
'''
For each integer `n` in an iterable `reps`, count the number of
items in the iterable `ids` that contain any character repeated
exactly `n` times. Return the product of these counts, or 0 if
`ids` or `reps` is empty.
'''
if not strs or not reps:
return 0
ret = 1
for r in reps:
count = 0
for s in strs:
if contains_n_any(s, r):
count += 1
ret *= count
return ret
def test_invalid_input():
assert not contains_n_any('', 1)
assert not contains_n_any('foo', -1)
assert not contains_n_any('bar', 0)
assert not checksum([], [])
assert not checksum([], 1)
assert not checksum(['foo'], [])
def test_one_char():
assert contains_n_any('a', 1)
assert not contains_n_any('a', 2)
assert checksum(['a'], [1]) == 1
assert checksum(['a'], [0, 1]) == 0
assert checksum(['a'], [1, 1]) == 1
def test_two_chars():
assert contains_n_any('ab', 1)
assert checksum(['ab'], [1, 2]) == 0
assert contains_n_any('aa', 2)
assert checksum(['aa'], [1, 2]) == 0
assert not contains_n_any('aa', 1)
assert not contains_n_any('ab', 2)
Difference of exactly one character
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def off_by_one(str1, str2):
'''
Return True if `str1` and `str2` are the same length and they differ
by exactly one character, otherwise False.
'''
if len(str1) != len(str2):
return False
count = 0
for idx, char in enumerate(str1):
if str2[idx] != char:
count += 1
if count > 1:
return False
return True if count == 1 else False
def test_off_by_one():
assert not off_by_one('abcde', 'abcdef')
assert not off_by_one('abcde', 'fghij')
assert not off_by_one('abcde', 'abcfg')
assert off_by_one('fghij', 'fguij')
Common characters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def common_chars(str1, str2):
'''
Return a string containing all characters that appear in the same
index position in `str1` and `str2`.
'''
ret = ''
for idx, char in enumerate(str1):
if str2[idx] == char:
ret += char
return ret
def test_common_chars():
assert common_chars('foo', 'bar') == ''
assert common_chars('fghij', 'fguij') == 'fgij'
“Match” strings that differ by one exactly character
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def match(strs):
'''
Return a string containing the characters shared by the first two
elements of `strs` that differ by exactly one character, or an
empty string otherwise.
'''
strslen = len(strs)
for i in range(strslen):
str1 = strs[i]
for j in range(i + 1, strslen):
str2 = strs[j]
if off_by_one(str1, str2):
return common_chars(str1, str2)
return ''
def test_match():
assert match(['abcde', 'fghij']) == ''
assert match(['fghij', 'fguij']) == 'fgij'
assert match(['abcde', 'fghij', 'lmnop', 'qrstu', 'fguij']) == 'fgij'
Tests provided with challenge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
def test_provided():
# abcdef contains no letters that appear exactly two or three times.
assert not contains_n_any('abcdef', 2)
assert not contains_n_any('abcdef', 3)
# bababc contains two a and three b, so it counts for both.
assert contains_n_any('bababc', 2)
assert contains_n_any('bababc', 3)
# abbcde contains two b, but no letter appears exactly three times.
assert contains_n_any('abbcde', 2)
assert not contains_n_any('abbcde', 3)
# abcccd contains three c, but no letter appears exactly two times.
assert contains_n_any('abcccd', 3)
assert not contains_n_any('abcccd', 2)
# aabcdd contains two a and two d, but it only counts once.
assert contains_n_any('aabcdd', 2)
# abcdee contains two e.
assert contains_n_any('abcdee', 2)
# ababab contains three a and three b, but it only counts once.
assert contains_n_any('ababab', 3)
ids = ['abcdef', 'bababc', 'abbcde', 'abcccd',
'aabcdd', 'abcdee', 'ababab']
assert checksum(ids, [2, 3]) == 12
ids = ['abcde', 'fghij', 'klmno', 'pqrst',
'fguij', 'axcye', 'wvxyz']
assert match(ids) == 'fgij'
Run all tests
1
pytest.main([__file__])
Solution using data provided with challenge
1
2
3
4
with open('./input.txt') as f:
ids = f.readlines()
print('Solution to part 1:', checksum(ids, [2, 3]))
print('Solution to part 2:', match(ids))