utils.py
View source code here on GitHub!
Includes
- python.src.lib.utils.get_data_file(name: str, mode: 'r' = 'r') str
- python.src.lib.utils.get_data_file(name: str, mode: 'rb') bytes
Returns the contents of a file in the top-level _data directory.
- python.src.lib.utils.is_palindrome(n: ~typing.Any, rep_func: ~typing.Callable[[~typing.Any], str] = <built-in function repr>) bool
Checks if the string representation of an object is a palindrome
- python.src.lib.utils.steps_to_palindrome(n: int, depth: int = 0) int
Returns a 0 if the number does not reach a palindrome in 50 or fewer steps, otherwise returns the step count
1from functools import lru_cache
2from pathlib import Path
3from typing import Any, Callable, Union, overload
4
5from .iters import digits
6from .math import from_digits
7
8try:
9 from typing import Literal
10except ImportError:
11 from typing_extensions import Literal # type: ignore
12
13
14@overload
15def get_data_file(name: str, mode: Literal['r'] = 'r') -> str: ...
16@overload
17def get_data_file(name: str, mode: Literal['rb']) -> bytes: ...
18
19
20@lru_cache(maxsize=None)
21def get_data_file(name: str, mode: str = 'r') -> Any:
22 """Returns the contents of a file in the top-level _data directory."""
23 with Path(__file__).parent.parent.parent.parent.joinpath('_data', name).open(mode) as f:
24 return f.read()
25
26
27def get_answer(n: int) -> Union[int, str]:
28 for line in get_data_file('answers.tsv').splitlines()[1:]:
29 id_, type, size, value = line.split('\t')
30 if int(id_) != n:
31 continue
32 if type == 'str':
33 return value
34 return int(value)
35 raise ValueError()
36
37
38def is_palindrome(n: Any, rep_func: Callable[[Any], str] = repr) -> bool:
39 """Checks if the string representation of an object is a palindrome"""
40 r = rep_func(n)
41 return r == r[::-1]
42
43
44def steps_to_palindrome(n: int, depth: int = 0) -> int:
45 """Returns a 0 if the number does not reach a palindrome in 50 or fewer steps, otherwise returns the step count"""
46 new = n + from_digits(digits(n))
47 if is_palindrome(new):
48 return depth + 1
49 elif depth == 50:
50 return 0
51 return steps_to_palindrome(new, depth=depth + 1)