2009-05-29 10 views
5

Estoy tratando de crear una función que me dé la posición del alfabeto cuando se pasa un índice. Será lo mismo que Excel muestra sus columnas. A ... Z, AA, AB .... Me escribió la función siguiente para obtener los resultados upto Z. Parece queIncrementando los alfabetos

static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 
    if (index <= alphabetsCount) 
    { 
     int code = (index - 1) + (int)'A'; 
     return char.ConvertFromUtf32(code); 
    } 
    return string.Empty; 
} 

Esto funciona bien hasta que 'Z'. Devuelve 'A' si paso 1 y devuelve 'B' si paso 2 y así sucesivamente. Pero, no puedo averiguar cómo obtendré AA cuando pase 27 a esta función. Supongo que necesito un método recursivo para encontrarlo.

¡Cualquier entrada a este problema será genial!

Editar

Esto es sugerido por Tordek. Pero su código fallará en números como 52, 78, etc. Se agregó una solución para eso y aquí está el código de trabajo final.

static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 

    if (index > alphabetsCount) 
    { 
     int mod = index % alphabetsCount; 
     int columnIndex = index/alphabetsCount; 

     // if mod is 0 (clearly divisible) we reached end of one combination. Something like AZ 
     if (mod == 0) 
     { 
      // reducing column index as index/alphabetsCount will give the next value and we will miss one column. 
      columnIndex -= 1; 
      // passing 0 to the function will return character '@' which is invalid 
      // mod should be the alphabets count. So it takes the last char in the alphabet. 
      mod = alphabetsCount; 
     } 
     return GetColumnName(columnIndex) + GetColumnName(mod); 
    } 
    else 
    { 
     int code = (index - 1) + (int)'A'; 
     return char.ConvertFromUtf32(code); 
    } 
} 

Respuesta

4

Cualquier función recursiva se puede convertir en una iterativa equivalente. Me resulta siempre fácil pensar de forma recursiva primero:

static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 

    if (index > alphabetsCount) { 
     return GetColumnName(index/alphabetsCount) + GetColumnName(index % alphabetsCount); 
    } else { 
     int code = (index - 1) + (int)'A'; 
     return char.ConvertFromUtf32(code); 
    } 
} 

Cuál puede ser simple convertida en:

static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 
    string result = string.Empty; 

    while (index > 0) { 
     result = char.ConvertFromUtf32(64 + (index % alphabetsCount)) + result; 
     index /= alphabetsCount; 
    } 

    return result; 
} 

Aun así, escuchar a Joel.

+0

Genial.Mi matemática está oxidada. Entonces no pude entender el funcionamiento del módulo. Gracias por el código –

0

La recursividad es una posibilidad - si index > 26, a lidiar con index % 26 en la presente convocatoria y concatena a una llamada recursiva en index/26. Sin embargo, la iteración suele ser más rápida y no es difícil organizar casos simples como este. En pseudocódigo:

string result = <convert `index % 26`> 
while index > 26: 
    index = index/26 
    result = <convert `index % 26`> + result 
return result 

o similar.

+0

No hay nada malo con su pseudocódigo, pero es importante saber que probablemente debería utilizar la clase StringBuilder si va a estar añadiendo a una cadena en un bucle, para ahorrar en las asignaciones de objetos: http://msdn.microsoft.com/en-us/library/system.text.stringbuilder(loband).aspx –

+0

Esto es incorrecto porque no es un sistema base 26. Si A fuera 0, A sería igual a AA (0 == 00). Si A fuera 1, pasar de Z a AA sería como pasar del 9 al 11. –

+0

Paul, StringBuilder es excesivo. Un int de 32 bits es 2^32 y 26^7 lo desborda, por lo que el máximo es de 7 letras. 7 iteraciones son difíciles de gravar. Una longitud de 64 bits solo tendría 14 letras. :) –

0
 
static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 
    string result = ''; 

    if (index >= alphabetsCount) 
    { 
     result += GetColumnName(index-alphabetsCount) 
    } 
    return (string) (64 + index); 
} 

Mi C# es HORRIBLE AND RUSTY. Interpreta esto como un seudocódigo: seguramente no compilará, pero puede ayudarte a comenzar.

-1

No quiero responder la pregunta en C# pero le mostraré lo fácil que es esto en Haskell.

alphas :: [String] 
alphas = [x ++ [c] | x <- ([]:alphas), c <- ['A'..'Z']] 

Prelude> take 100 alphas 
["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T", 
"U","V","W","X","Y","Z","AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK", 
"AL","AM","AN","AO","AP","AQ","AR","AS","AT","AU","AV","AW","AX","AY","AZ","BA", 
"BB","BC","BD","BE","BF","BG","BH","BI","BJ","BK","BL","BM","BN","BO","BP","BQ", 
"BR","BS","BT","BU","BV","BW","BX","BY","BZ","CA","CB","CC","CD","CE","CF","CG", 
"CH","CI","CJ","CK","CL","CM","CN","CO","CP","CQ","CR","CS","CT","CU","CV"] 
Cuestiones relacionadas