1, 2, 3, ... , 26, 27, 28, ... for a, b, c, ..., z, aa, ab, ... , z, aa, ab, ... to a, b, c, ..., z, aa, ab, ... https://atcoder.jp/contests/abc171/tasks/abc171_c
complete form python
def solve(N):
q = N
ret = ""
while True:
q, r = divmod(q - 1, 26)
ret = ascii_lowercase[r] + ret
if q == 0:
print(ret)
return
I didn't write this code from the beginning.
At first I thought, "This problem is easy to test, so let's make it test-driven," so I put up a snippet that calls doctest. python
from string import ascii_lowercase
def solve(N):
"""
"""
def main():
N = int(input())
solve(N)
def _test():
import doctest
doctest.testmod()
if __name__ == "__main__":
import sys
argv = sys.argv
if len(sys.argv) == 1:
# no option
main()
elif sys.argv[1] == "-t":
_test()
else:
input = open(sys.argv[1]).buffer.readline
First, write a test case python
def solve(N):
"""
>>> solve(1)
a
"""
Naturally, the test will fail. python
$ python3 c2.py -t
**********************************************************************
File "c2.py", line 6, in __main__.solve
Failed example:
solve(1)
Expected:
a
Got nothing
**********************************************************************
1 items had failures:
1 of 1 in __main__.solve
***Test Failed*** 1 failures.
Write code that passes tests python
def solve(N):
"""
>>> solve(1)
a
"""
print(ascii_lowercase[N - 1])
Run the test to confirm it is OK (doctest does not display anything when it is OK).
Add a test case python
def solve(N):
"""
>>> solve(1)
a
>>> solve(27)
aa
"""
print(ascii_lowercase[N - 1])
Naturally, the test will fail.
See what kind of failures you have.
I'm getting IndexError: string index out of range after reading the 27th of only 26 strings.
python
$ python3 c2.py -t
**********************************************************************
File "c2.py", line 8, in __main__.solve
Failed example:
solve(27)
Exception raised:
Traceback (most recent call last):
File ".../doctest.py", line 1329, in __run
compileflags, 1), test.globs)
File "<doctest __main__.solve[1]>", line 1, in <module>
solve(27)
File "c2.py", line 11, in solve
print(ascii_lowercase[N - 1])
IndexError: string index out of range
**********************************************************************
1 items had failures:
1 of 2 in __main__.solve
***Test Failed*** 1 failures.
Then let's just calculate the quotient divided by 26 and the remainder. python
def solve(N):
"""
>>> solve(1)
a
>>> solve(27)
aa
"""
q, r = divmod(N - 1, 26)
print(ascii_lowercase[r])
The error message changed, and it was not a runtime error, but rather that the value output was wrong. Let's fix this. python
$ python3 c2.py -t
**********************************************************************
File "c2.py", line 8, in __main__.solve
Failed example:
solve(27)
Expected:
aa
Got:
a
**********************************************************************
1 items had failures:
1 of 2 in __main__.solve
***Test Failed*** 1 failures.
I haven't used the quotient I calculated earlier, so I'll use it anyway. python
def solve(N):
"""
>>> solve(1)
a
>>> solve(27)
aa
"""
q, r = divmod(N - 1, 26)
ret = ascii_lowercase[r]
if q == 0:
print(ret)
else:
print(ascii_lowercase[q] + ret)
Failure that it should be aa but it is ba (foreshadowing 1) python
$ python3 c2.py -t
**********************************************************************
File "c2.py", line 8, in __main__.solve
Failed example:
solve(27)
Expected:
aa
Got:
ba
**********************************************************************
1 items had failures:
1 of 2 in __main__.solve
***Test Failed*** 1 failures.
The number was reduced by 1 to make it more consistent. python
def solve(N):
"""
>>> solve(1)
a
>>> solve(27)
aa
"""
q, r = divmod(N - 1, 26)
ret = ascii_lowercase[r]
if q == 0:
print(ret)
else:
print(ascii_lowercase[q - 1] + ret)
Test OK Add a new test case. python
def solve(N):
"""
>>> solve(1)
a
>>> solve(27)
aa
>>> solve(703)
aaa
"""
q, r = divmod(N - 1, 26)
ret = ascii_lowercase[r]
if q == 0:
print(ret)
else:
print(ascii_lowercase[q - 1] + ret)
Naturally, it will fail.
This error message IndexError: string index out of range is the one I saw earlier, let's fix it the same way.
python
$ python3 c2.py -t
**********************************************************************
File "c2.py", line 10, in __main__.solve
Failed example:
solve(703)
Exception raised:
Traceback (most recent call last):
File ".../doctest.py", line 1329, in __run
compileflags, 1), test.globs)
File "<doctest __main__.solve[2]>", line 1, in <module>
solve(703)
File "c2.py", line 18, in solve
print(ascii_lowercase[q - 1] + ret)
IndexError: string index out of range
**********************************************************************
1 items had failures:
1 of 3 in __main__.solve
***Test Failed*** 1 failures.
I copied and pasted the code I wrote earlier and modified it the same way. python
def solve(N):
"""
>>> solve(1)
a
>>> solve(27)
aa
>>> solve(703)
aaa
"""
q, r = divmod(N - 1, 26)
ret = ascii_lowercase[r]
if q == 0:
print(ret)
else:
q, r = divmod(q - 1, 26)
ret = ascii_lowercase[r] + ret
if q == 0:
print(ret)
else:
q, r = divmod(q - 1, 26)
ret = ascii_lowercase[r] + ret
print(ret)
Test OK The same thing continues after the fourth digit, so let's rewrite it using a loop. python
def solve(N):
"""
>>> solve(1)
a
>>> solve(27)
aa
>>> solve(703)
aaa
"""
q = N
while True:
q, r = divmod(q - 1, 26)
ret = ascii_lowercase[r]
if q == 0:
print(ret)
break
Fail when rewritten and tested. python
$ python3 c2.py -t
**********************************************************************
File "c2.py", line 8, in __main__.solve
Failed example:
solve(27)
Expected:
aa
Got:
a
**********************************************************************
File "c2.py", line 10, in __main__.solve
Failed example:
solve(703)
Expected:
aaa
Got:
a
**********************************************************************
1 items had failures:
2 of 3 in __main__.solve
***Test Failed*** 2 failures.
Forgot to extend the string. Correction. python
def solve(N):
"""
>>> solve(1)
a
>>> solve(27)
aa
>>> solve(703)
aaa
"""
q = N
ret = ""
while True:
q, r = divmod(q - 1, 26)
ret = ascii_lowercase[r] + ret
if q == 0:
print(ret)
break
Test OK Now submitted.
digression
This page is auto-translated from /nishio/テストドリブンで変形26進法の実装 using DeepL. If you looks something interesting but the auto-translated English is not good enough to understand it, feel free to let me know at @nishio_en. I'm very happy to spread my thought to non-Japanese readers.