Je souhait créer un algo (a but éducatif) qui permet de trouver le nom d'une colonne en fonction de son numéro / indice.
Ex:
colonne n°0 = "A", n°25 = "Z", n°30 = "AE" etc...
je suis arriver à ça:
def column(n):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
column_name = list()
# solution of n < 26**x
letters_nbs = int(log(n, 26)) if n> 0 else 0
for letter in range(letters_nbs, -1, -1):
letter_index = (n// 26 ** letter) % 26
column_name.append(alphabet[letter_index])
return "".join(column_name)
ce qui équivaux à:
def column(n):
for i in range(n + 1):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
result = list()
result.append(alphabet[i%26])
last = i // 26
result.append(alphabet[last % 26])
while last >=26:
last //=26
result.append(alphabet[last % 26])
result.reverse()
return "".join(result)
Pas vraiment compris ton algorithme. Il me semble que ton calcul de longueur du nom de la colonne est faux, je crois comprendre que pour toi c'est 1+int(log(n, 26)), la première valeur fausse étant pour n=676 qui donne 3 chez toi alors que c'est plutôt 2 puisque le nom correspondant est ZA.
Le problème à résoudre est un problème de conversion de l'entier n en base b=26 mais avec un algorithme de conversion adapté. Il s'agit d'écrire n sous la forme
[en latex, ça donne : c_0+(c_1+1)b+(c_2+1)b^2+\dots+(c_{N-1}+1)b^{N-1}] où N est la longueur du nom de la colonne, où b est le nombre de caractères possibles (b=26 pour toi mais pour faire des essais, il est pratique de prendre b=10, les caractères étant les chiffres décimaux) et où les coefficients ci sont des chiffres en base b. Pourquoi ? Réponse : chaque fois que la longueur du nom de colonne augmente de 1 caractère, on recommence à compter depuis 0 (c'est à dire AAA...A).
D'où le code suivant :
from string import ascii_uppercase as upper, digits
def col(n, b, alpha=upper):
L=[alpha[n%b]]
n//=b
while n:
r=n%b
if r:
L.append(alpha[r-1])
n//=b
else:
L.append(alpha[b-1])
n=(n-b)//b
return ''.join(L)[::-1]
alpha=upper
b=len(alpha)
n=676
print(col(n,b))
qui affiche
ZA
Tu peux aussi générer manuellement tous les noms de colonnes jusqu'à celle qui représente n :
from string import ascii_uppercase as upper, digits
def gen(n, alpha=upper):
def next_col(s, alpha=upper):
last=alpha[-1]
N=len(s)
if s==last*N:
return alpha[0]*(N+1)
k=N-1
for _ in range(N):
if s[k]!=last:
j=alpha.index(s[k])
return s[:k]+alpha[j+1]+alpha[0]*(N-k-1)
k-=1
s=alpha[0]
print(s, end=', ')
for k in range(n):
s=next_col(s, alpha)
print(s, end=', ')
return s
alpha=upper
b=len(alpha)
n=676
gen(n)
r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
ln = len(r)
def foo(n):
n,m = divmod(n,ln)
z = r[m]
while n:
n,m = divmod(n-1,ln)
z = r[m]+z
return z
- Edité par josmiley il y a 10 minutes
Oui, bien vu : en faisant prenant n-1 au lieu de n à chaque étape, tu obtiens comme reste (ci+1)-1=ci de ma formule plus haut qui est l'indice cherché.
r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
ln = len(r)
def foo(n):
n,m = divmod(n,ln)
z = r[m]
while n:
n,m = divmod(n-1,ln)
z = r[m]+z
return z
rd = dict(zip(r,range(ln)))
def unfoo(s):
l,*r = s
z = rd[l]
while r:
l,*r = r
z = (z+1)*ln+rd[l]
return z
print(foo(701)) # ZZ
print(unfoo('ZZ')) # 701
import string
alpha = string.ascii_uppercase
n = int(input('\nn : '))
if(n//26 - 1 < 0):
col = alpha[n%26]
else:
col = alpha[n//26 - 1] + alpha[n%26]
print('\n{} --> {}'.format(n,col))
- Edité par Phil_1857 il y a 7 minutes
Ton code est certainement incomplet car ça n'a aucune raison de marcher sans aucune répétition (récursive ou itérative). Ta ligne 10 va générer un débordement d'indice.
En tenant compte de la remarque de josmiley qui dit que c'est 10 et non 00 qui suit 9 en base 10: (je suppose le nombre correct en base 26 [lettres])
from string import ascii_uppercase as upper def col(n, alpha): b = len(alpha) s = "" while n: s = alpha[n%b] + s n //= b return s or alpha[0] def num(s, alpha): b = len(alpha) n = 0 for c in s: n = n*b + alpha.index(c) return n # n = int(input("> ")) print(col(n, upper)) print(num(col(n, upper), upper))
- Edité par PierrotLeFou 28 janvier 2023 à 18:21:03
Le Tout est souvent plus grand que la somme de ses parties.
from string import ascii_uppercase as upper
from itertools import product, count
def gen(n):
cpt=0
for k in count(1):
for s in product(upper, repeat=k):
if cpt==n:
return ''.join(s)
cpt+=1
n=2023
print(gen(n))
BYV
Le code est très certainement améliorable. Evidemment, ça ne peut pas traiter des valeurs de n arbitrairement grandes.
import string
def foo(n):
letters = string.ascii_uppercase
result = ""
while n:
n, remainder = divmod(n - 1, len(letters) - 1)
result = letters[remainder] + result
return result
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
import string
def foo(n):
letters = string.ascii_uppercase
result = ""
while n:
n, remainder = divmod(n - 1, len(letters) - 1)
result = letters[remainder] + result
return result
import string
def foo(n):
letters = string.ascii_uppercase
result = ""
while n:
n, remainder = divmod(n - 1, len(letters) - 1)
result = letters[remainder] + result
return result
Pas bon, 0 doit retourner A et 25 Z.
je corrige,
import string
def foo_1(n):
letters = string.ascii_uppercase
result = ""
n += 1
while n:
n, remainder = divmod(n-1, 26)
result = letters[remainder] + result
return result
puis une autre proposition
def foo_2(n):
base = ord('A')
result = ""
while n >= 0:
result = chr(base + n % 26) + result
n = n // 26 - 1
return result
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
josmiley a écrit: > @PierrotLeFou > Dans ton code, si je tape 26 ça retourne BA au lieu de AA Il faudrait demander à ebdm13 ce que devrait donner 676 (26*26), 675 ou 650 (26*25) J'obtiens BAA, ZZ, ZA dans l'ordre.
edit: Je crois commencer à comprendre la logique de tout cela ... J'ai refait mon code en m'inspirant de celui de PascalOrtiz, mais sans le module itertools. Je suppose que mon code est plus lent. J'obtiens le mêm résultat pour 2023:
from string import ascii_uppercase as upper from math import log def col(n, alpha): b = len(alpha) M = list(alpha) C = M for _ in range(int(log(n, b))+2): M = [i+j for i in M for j in alpha] C += M return C[n] n = int(input("> ")) print(col(n, upper))
re-edit: Ce processus est plutôt lent. J'ai essayé de l'optimiser en le simulant. On n'est pas vraiment en base 26. On a tout de même 26 nombres de 1 lettre, 676 nombres de 2 lettres à la suite, etc. Le code qui suit semble fonctionner pour toutes les valeurs de mon code précédent:
from string import ascii_uppercase as upper def col(n, alpha): b = len(alpha) p = 1 while n >= b**p: # Pourrait être optimisé. n -= b**p p += 1 C = [] while n: C.append(n%b) n //= b C.extend([0]*(p-len(C))) return "".join(alpha[i] for i in C[-1::-1]) n = int(input("> ")) print(col(n, upper))
- Edité par PierrotLeFou 29 janvier 2023 à 3:30:24
Le Tout est souvent plus grand que la somme de ses parties.
import string
def foo_1(n):
letters = string.ascii_uppercase
result = ""
n += 1
while n:
n, remainder = divmod(n-1, 26)
result = letters[remainder] + result
return result
La première correction reste incorrecte (renvoie CEW pour n=2023 au lieu de BYV). Et le code reste très proche de ce que josmiley a proposé.
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Mes excuses, j'avais pris ton code non corrigé sans le n+1. Et, effectivement le fait de rajouter 1 à n au départ est une bonne idée.
Sinon, quelles sont vos propositions pour calculer le nombre de lettres du nom de la colonne de rang n, sans calculer le nom de la colonne ?
Une proposition,
def foo_2_length(n):
length = 0
while n >= 0:
length += 1
n = n // 26 - 1
return length
j'ai pas trop testé, mais c'est fonctionnel sur les quelques tests déjà effectués précédemment.
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
> Et il existe une solution sans boucle. Ceci semble fonctionner:
from math import log def w(n): return int(log((n+1)*25+1, 26)) print(w(int(input("> "))))
Oui, c'est cette formule que j'avais en tête. Néanmoins, cette formule a un gros inconvénient, elle donne dans certains cas un résultat faux à cause d'une erreur d'arrondi, style un log qui vaut 2.999999996. Je ne l'ai pas vu se produire pour b=26 néanmoins ce n'est pas le cas pour b=10.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Python c'est bon, mangez-en.
Découverte Python Doc Tkinter Les chaînes de caractères
Python c'est bon, mangez-en.
Découverte Python Doc Tkinter Les chaînes de caractères
Python c'est bon, mangez-en.
Découverte Python Doc Tkinter Les chaînes de caractères
Découverte Python Doc Tkinter Les chaînes de caractères
Découverte Python Doc Tkinter Les chaînes de caractères
Découverte Python Doc Tkinter Les chaînes de caractères
Le Tout est souvent plus grand que la somme de ses parties.
Python c'est bon, mangez-en.
Découverte Python Doc Tkinter Les chaînes de caractères
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Python c'est bon, mangez-en.
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Le Tout est souvent plus grand que la somme de ses parties.
Découverte Python Doc Tkinter Les chaînes de caractères
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Python c'est bon, mangez-en.
Découverte Python Doc Tkinter Les chaînes de caractères
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Découverte Python Doc Tkinter Les chaînes de caractères
Le Tout est souvent plus grand que la somme de ses parties.
Python c'est bon, mangez-en.
Découverte Python Doc Tkinter Les chaînes de caractères