Преобразование десятичного числа в число, подобное заголовку excel
0 = A
1 = B
...
25 = Z
26 = AA
27 = AB
...
701 = ZZ
702 = AAA
Я не могу придумать никакого решения, которое не включало бы loop-bruteforce : - (
Я ожидаю функцию / программу, которая принимает десятичное число и возвращает строку в результате.
10 ответов
Хаскел, 78 57 50 43 chars
o=map(['A'..'Z']:)$[]:o
e=(!!)$o>>=sequence
другие записи не учитывают драйвер, который добавляет еще 40 символов:
main=interact$unlines.map(e.read).lines
новый подход, используя ленивый, бесконечный список, и сила монады! И кроме того, используя sequence
меня :)
, использование бесконечных списков делает меня :o
если вы внимательно посмотрите представление excel как база 26 номер, но не точно так же, как базы 26.
в Excel преобразования Z + 1 = AA
а в базе-26 Z + 1 = BA
алгоритм почти такой же, как преобразование decimal в base-26 с одним изменением.
В base-26 мы делаем рекурсивный вызов, передавая ему quotient
, но здесь мы передаем его quotient-1
:
function decimalToExcel(num)
// base condition of recursion.
if num < 26
print 'A' + num
else
quotient = num / 26;
reminder = num % 26;
// recursive calls.
decimalToExcel(quotient - 1);
decimalToExcel(reminder);
end-if
end-function
питон, 44 символов
Ой да ладно, мы можем сделать лучше, чем длины 100+ :
X=lambda n:~n and X(n/26-1)+chr(65+n%26)or''
тестирование:
>>> for i in 0, 1, 25, 26, 27, 700, 701, 702:
... print i,'=',X(i)
...
0 = A
1 = B
25 = Z
26 = AA
27 = AB
700 = ZY
701 = ZZ
702 = AAA
поскольку я не уверен, какую базу вы конвертируете и какую базу вы хотите (ваш заголовок предлагает один, а ваш вопрос наоборот), я рассмотрю оба.
алгоритм преобразования ZZ
to 701
сначала признаем, что у нас есть число, закодированное в базе 26, где "цифры" -A..Z
. Установите счетчик a
до нуля и начните читать число в крайнем правом углу (наименее значимая цифра). Продвигаясь справа налево, прочитайте каждое число и преобразуйте его "цифру" в десятичное число. Умножьте это на 26a
и добавьте это к результату. Инкремент a
и обработать следующую цифру.
алгоритм преобразования 701
to ZZ
мы просто факторизуем число в степени 26, как и при преобразовании в двоичный код. Просто возьмите num%26
, преобразовать его в A..Z
"цифры" и добавьте к преобразованному числу (предполагая, что это строка), а затем целое число-разделите свое число. Повторяйте, пока num
равна нулю. После этого отмените преобразованную числовую строку, чтобы сначала иметь самый значительный бит.
Edit: как вы указываете, как только двузначные числа достигнуты, у нас фактически есть база 27 для всех не наименее значимых битов. Просто примените те же алгоритмы здесь, увеличивая любые "константы" на единицу. должны работа, но я сам не пробовал.
изменить: на ZZ->701
case, не увеличивайте базу показатель. Однако имейте в виду, что A
больше не 0 (но 1) и так далее.
объяснение, почему это не преобразование базы 26
давайте начнем с рассмотрения реальной позиционной системы базы 26. (Скорее, посмотрите как база 4, так как это меньше чисел). Верно следующее (при условии A = 0):
A = AA = A * 4^1 + A * 4^0 = 0 * 4^1 + 0 * 4^0 = 0
B = AB = A * 4^1 + B * 4^0 = 0 * 4^1 + 1 * 4^0 = 1
C = AC = A * 4^1 + C * 4^0 = 0 * 4^1 + 2 * 4^0 = 2
D = AD = A * 4^1 + D * 4^0 = 0 * 4^1 + 3 * 4^0 = 3
BA = B * 4^0 + A * 4^0 = 1 * 4^1 + 0 * 4^0 = 4
и так далее... заметьте, что AA
равно 0, а не 4, как это было бы в нотации Excel. Следовательно, обозначение Excel не база 26.
в Excel VBA ... очевидный выбор :)
Sub a()
For Each O In Range("A1:AA1")
k = O.Address()
Debug.Print Mid(k, 2, Len(k) - 3); "="; O.Column - 1
Next
End Sub
или для получения номера столбца в первой строке рабочего листа (что имеет больше смысла, так как мы находимся в Excel ...)
Sub a()
For Each O In Range("A1:AA1")
O.Value = O.Column - 1
Next
End Sub
или еще лучше:
56 символов
Sub a()
Set O = Range("A1:AA1")
O.Formula = "=Column()"
End Sub
Пролог 109 123 байт
преобразование из десятичного числа в строку Excel:
c(D,E):- d(D,X),atom_codes(E,X).
d(D,[E]):-D<26,E is D+65,!.
d(D,[O|M]):-N is D//27,d(N,M),O is 65+D rem 26.
Этот код не работает для c (27, N), который дает N='BB'
это работает отлично:
c(D,E):-c(D,26,[],X),atom_codes(E,X).
c(D,B,T,M):-(D<B->M-S=[O|T]-B;(S=26,N is D//S,c(N,27,[O|T],M))),O is 91-S+D rem B,!.
тесты:
?- c(0, N).
N = 'A'.
?- c(27, N).
N = 'AB'.
?- c(701, N).
N = 'ZZ'.
?- c(702, N).
N = 'AAA'
преобразует из строки Excel в десятичное число (87 байт):
x(E,D):-x(E,0,D).
x([C],X,N):-N is X+C-65,!.
x([C|T],X,N):-Y is (X+C-64)*26,x(T,Y,N).
F#:166
let rec c x = if x < 26 then [(char) ((int 'A') + x)] else List.append (c (x/26-1)) (c (x%26))
let s x = new string (c x |> List.toArray)
let rec c x = if x < 26 then [(char) ((int 'A') + x)] else List.append (c (x/26-1)) (c (x%26))
let s x = new string (c x |> List.toArray)
PHP: не менее 59 и 33 символов.
<?for($a=NUM+1;$a>=1;$a=$a/26)$c=chr(--$a%26+65).$c;echo$c;
или самая короткая версия:
<?for($a=A;$i++<NUM;++$a);echo$a;
используя следующую формулу, можно выяснить последний символ в строке:
transform(int num)
return (char)num + 47; // Transform int to ascii alphabetic char. 47 might not be right.
char lastChar(int num)
{
return transform(num % 26);
}
используя это, мы можем сделать рекурсивную функцию (я не думаю, что его грубой силой).
string getExcelHeader(int decimal)
{
if (decimal > 26)
return getExcelHeader(decimal / 26) + transform(decimal % 26);
else
return transform(decimal);
}
или.. что-то вроде того. Я очень устал, может быть, мне стоит перестать отвечать на вопросы и лечь спать: P