Reputation: 13
What I want to do is count with a certain number of letters. the inputs will be n and x, where n is the number of letters to be used and x is the number I'm trying to count to. Say n is 3 and x is 12. It would go like this: 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', 'aba', 'abb', 'baa', 'bab'. 'bab' is 12 when using 2 numbers to count. I know there is a mathematical way to do this, but I can't figure it out. Another test case is n = 16 and x = 248832. It would return 'clkop'. I'm sorry if someone has asked something like this before, I couldn't find anything. Also, let me know if this belongs on a different website. For clarity, the number of letters can range from 1 to 26. if it is 1, then 8 would be expressed as 'aaaaaaaa'. If the number of letters is 2, 8 would be expressed as 'aab'. If it is 3, then 17 would be expressed as 'abc' etc. I thought that it would be as simple as converting to base n, but it isn't. Hopefully, that helps. When I was writing this question, I saw a similar one that was in javascript, but it only did all 26 letters. I don't know how to convert javascript code into python code, and I want to be able to do any number of letters from 1-26. I know there is also a way to brute force this, but I don't know how
Let me know if the question needs more clarification
Edit: I figured out how to convert the string of letters into a number given the number of letters. For 16 letters, clkop = 3 * (16^4) + 12 * (16^3) + 11 * (16^2) + 15 * 16 + 16 = 248832 (or for an x length where v = the value of the current letter when iterating through the string, and n = number of letters, v * (n^x-1) + v * (n^x-2)... + v. Hopefully there is something you can do with that.
Upvotes: 0
Views: 796
Reputation: 440
With n different letters, we can form
different words of length at most k. Solving for y yields that the yth word has length
If we start our count with 0 and the empty word '', counting to x requires x+1 different words.
from math import log as ln
from math import ceil
from itertools import chain, product
def xth_word(x, n):
'''returns the xth word over the alphabet consisting of
the first n lowercase letters
The empty word '' is the 0th word
'''
letters = [chr(97 + i) for i in range(n)]
word_length = ceil(ln((x + 1) * (n - 1) + 1) / ln(n))
it = chain.from_iterable((product(letters, repeat=i)\
for i in range(word_length)))
word = next(w for i,w in enumerate(it) if i == x)
return ''.join(word)
print([xth_word(i, 2) for i in range(13)])
print(xth_word(248832, 16))
Output:
['', 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', 'aba', 'abb', 'baa', 'bab']
clkop
Upvotes: 0
Reputation: 7971
from string import ascii_lowercase
def alphabetic_counter(n, x):
letterNums = [0]
for i in range(x):
yield ''.join(reversed([ascii_lowercase[l] for l in letterNums]))
letterNums[0] += 1
currIdx = 0
while letterNums[currIdx] == n:
if currIdx == len(letterNums) - 1:
letterNums[currIdx] = 0
letterNums.append(0)
else:
letterNums[currIdx] = 0
currIdx += 1
letterNums[currIdx] += 1
print(list(alphabetic_counter(2,12)))
Output:
['a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', 'aba', 'abb', 'baa', 'bab']
Not the prettiest solution, I have to admit, but either I have bad day for this sort of tasks or it is much harder than it looks on the first glance.
Upvotes: 0
Reputation: 26901
You're basically asking how to convert a number into a different base, with the letters being the possible digits:
import string
namespace = string.ascii_lowercase
def convert(base, num):
result = []
while num:
num -= 1
num, mod = divmod(num, base)
result.append(namespace[mod])
return "".join(reversed(result))
Upvotes: 1