0

I am sorry if the title is a misnomer and/or doesn't properly describe what this is all about, you are welcome to edit the title to make it clear once you understand what this is about.

The thing is very simple, but I find it hard to describe, this thing is sorta like a number system, except it is about lists of integers.

So we start with a list of integers with only zero, foreach iteration we add one to it, until a certain limit is reached, then we insert 1 at the start of the list, and set the second element to 0, then iterate over the second element until the limit is reached again, then we add 1 to the first element and set the second element 0, and when the first element reaches the limit, insert another element with value of 1 to the start of the list, and zero the two elements after it, et cetera.

And just like this, when a place reaches limit, zero the place and the places after it, increase the place before it by one, and when all available places reach limit, add 1 to the left, for example:

0
1
2
1, 0
1, 1
1, 2
2, 0
2, 1
2, 2
1, 0, 0

The limit doesn't have to be three.

This is what I currently have that does something similar to this:

array = []
for c in range(26):
    for b in range(26):
        for a in range(26):
            array.append((c, b, a))

I don't want leading zeroes but I can remove them, but I can't figure out how to do this with a variable number of elements.

What I want is a function that takes two arguments, limit (or base) and number of tuples to be returned, and returns the first n such tuples in order.

This must be very simple, but I just can't figure it out, and Google returns completely irrelevant results, so I am asking for help here.

How can this be done? Any help will truly be appreciated!


Hmm, I was thinking about something like this, but very unfortunately I can't make it work, please help me figure out why it doesn't work and how to make it work:

array = []
numbers = [0]

for i in range(1000):
    numbers[-1] += 1
    while 26 in numbers:
        index = numbers.index(26)
        numbers[index:] = [0] * (len(numbers) - index)
        if index != 0:
            numbers[index - 1] += 1
        else:
            numbers.insert(0, 1)
    array.append(numbers)

I don't quite understand it, my testing shows everything inside the loop work perfectly fine outside the loop, the results are correct, but it just simply magically will not work in a loop, I don't know the reason for this, it is very strange.


I discovered the fact that if I change the last line to print(numbers) then everything prints correctly, but if I use append only the last element will be added, how so?

  • 1
    Does this help? https://stackoverflow.com/questions/34559663/convert-decimal-to-ternarybase3-in-python – Lucas Ng May 31 '21 at 20:07

3 Answers3

0
from math import log
def number_to_base(n,base):
    number=[]
    for digit in range(int(log(n+0.500001,base)),-1,-1):
        number.append(n//base**digit%base)
    return number
def first_numbers_in_base(n,base):
    numbers=[]
    for i in range(n):
        numbers.append(tuple(number_to_base(i,base)))
    return numbers

#tests:
print(first_numbers_in_base(10,3))
print(number_to_base(1048,10))
print(number_to_base(int("10201122110212",3),3))
print(first_numbers_in_base(25,10))
user2952903
  • 365
  • 2
  • 10
0

I finally did it!

The logic is very simple, but the hard part is to figure out why it won't work in a loop, turns out I need to use .copy(), because for whatever reason, doing an in-place modification to a list directly modifies the data reside in its memory space, such behavior modifies the same memory space, and .append() method always appends the latest data in a memory space.

So here is the code:

def steps(base, num):
    array = []
    numbers = [0]
    for i in range(num):
        copy = numbers.copy()
        copy[-1] += 1
        while base in copy:
            index = copy.index(base)
            copy[index:] = [0] * (len(copy) - index)
            if index != 0:
                copy[index - 1] += 1
            else:
                copy.insert(0, 1)
        array.append(copy)
        numbers = copy
    return array

Use it like this:

steps(26, 1000)

For the first 1000 lists in base 26.

  • You could make it faster by removing line "numbers = copy" and replacing variable "copy" everywhere with variable "numbers". – user2952903 Jun 01 '21 at 12:31
  • @user2952903 I know what I am doing, and I deliberately chose to use a copy of the `numbers` variable because using numbers alone gives unexpected results and breaks the code, and that is exactly what this question is about... –  Jun 01 '21 at 12:34
  • I think it does not give unexpected results If line after "for i in range(num):" is "numbers = numbers.copy()". – user2952903 Jun 01 '21 at 12:38
  • I posted a better function, that does almost same thing, but faster, as a new answer. – user2952903 Jun 01 '21 at 19:57
0

Here is a a function, that will satisfy original requirements (returns list of tuples, first tuple represents 0) and is faster than other functions that have been posted to this thread:

def first_numbers_in_base(n,base):
    if n<2:
        if n:
            return [(0,)]
        return []
    numbers=[(0,),(1,)]
    base-=1
    l=-1
    num=[1]
    for i in range(n-2):
        if num[-1]==base:
            num[-1]=0
            for i in range(l,-1,-1):
                if num[i]==base:
                    num[i]=0
                else:
                    num[i]+=1
                    break
            else:
                num=[1]+num
                l+=1
        else:
            num[-1]+=1
        numbers.append(tuple(num))#replace tuple(num) with num.copy() if you want resutl to contain lists instead of tuples.
    return numbers
user2952903
  • 365
  • 2
  • 10