Isso pode parecer trivial, mas não encontrei uma boa solução para o problema. Eu até encontrei isso: gere todos os números binários de n bits da maneira mais rápida possível . mas não encontrei uma duplicata exata.
O problema é muito simples: dado um limite N que seja um inteiro positivo, gere a representação binária de cada número natural até N em ordem (excluindo N, o primeiro número natural é 0, então N - 1 é o número máximo a ser representado), na tuple
forma, com cada tupla preenchida com zeros à esquerda para que todas as representações tenham o mesmo comprimento.
Por exemplo, se N
for 4, a saída deverá ser [(0, 0), (0, 1), (1, 0), (1, 1)]
.
Neste ponto, o problema é de fato trivial, mas há um porém: não são permitidos " bin(n)
e f'{n:b}'
" e "afins". O algoritmo deve operar inteiramente no domínio binário, porque, pelo que entendi, tudo (texto, fotos, música, vídeos...) em computadores são numerais binários, então converter representações de um lado para o outro está adicionando cálculos desnecessários. Esses cálculos (conversão de base) são completamente redundantes e devem ser eliminados para produzir o programa mais eficiente (trata-se de manter os problemas específicos para o menor número possível de domínios, para que possamos operar apenas nesses domínios).
Eu escrevi um programa simples que faz exatamente o que descrevo:
from typing import Generator, Tuple
def count_in_binary(n: int) -> Generator[Tuple[int, ...], None, None]:
if not isinstance(n, int) or n < 1:
raise ValueError("The argument n must be a positive integer")
l = (n - 1).bit_length() if n > 1 else 1
numeral = [0] * l
maxi = l - 1
for _ in range(n):
yield tuple(numeral)
i = maxi
while True:
if not (d := numeral[i]):
numeral[i] = 1
break
else:
numeral[i] = 0
i -= 1
Mas não tenho certeza se essa é a maneira mais eficiente de fazer isso em Python. Não usei muitas operações de bits e os computadores já representam números como binários, então deve haver maneiras mais rápidas de fazer isso.
A questão é: qual é o caminho mais rápido?
Para efeito de comparação, aqui está uma maneira que usa f'{n:b}' e, portanto, é mais concisa, mas na verdade é muito mais lenta e estúpida:
def count_in_binary1(n: int) -> Generator[Tuple[int, ...], None, None]:
if not isinstance(n, int) or n < 1:
raise ValueError("The argument n must be a positive integer")
l = len(f'{n-1:b}')
for i in range(n):
yield tuple(map(int, f'{i:0{l}b}'))
In [50]: %timeit list(count_in_binary(256))
59.9 μs ± 209 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
In [51]: %timeit list(count_in_binary1(256))
452 μs ± 3.68 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
Editar
Não fiz muitos testes com a função original, apenas pensei que funcionaria, agora está corrigido.
E não, o escopo do escopo é limitado ao Python puro, então o NumPy não é permitido.
Editar 2
Agora acho que não há exceções.
Votei positivamente e aceitei a segunda resposta, pois ela responde à pergunta original, embora a pergunta original não inclua todas as informações relevantes, então o problema que eu estava tentando resolver postando uma pergunta continua sem solução.
Publiquei uma nova pergunta sem todas as informações relevantes. Por favor, responda: Qual é a maneira mais rápida de encontrar todas as permutações de 0, 1 de largura n sem itertools em Python puro?
Cheguei a essa solução usando inteiramente funções integradas:
e estes são os resultados da bancada projetada por no comment ):
Do Colab (tudo parece estável)
Do meu PC
Observe que
n=1
minha implementação retorna simplesmente a[]
porque não está claro como 0 deve ser representado em uma forma de tupla.Com itertools:
Resultados de benchmark e código:
Tente isso online!