Створити ім’я стовпця excel з індексу


21

Це походить від реальної життєвої проблеми. Ми вирішили це, звичайно, але все одно відчуваємо, що це можна було б зробити краще, що це занадто тривале і кругле рішення. Однак ніхто з моїх колег не може придумати більш складний спосіб його написання. Тому я представляю його як код-гольф.

Мета - перетворити негативне ціле число в рядок так само, як Excel представляє заголовки стовпців. Таким чином:

0 -> A
1 -> B
...
25 -> Z
26 -> AA
27 -> AB
...
51 -> AZ
52 -> BA
...
16,383 -> XFD

Він повинен працювати щонайменше до 16 383, але також є прийнятним (хоча бонусних балів немає). Я з нетерпінням чекаю найрізноманітнішого рішення C #, але, згідно традицій кодового гольфу, будь-яка реальна мова програмування вітається.


Ви впевнені, що 16383 має бути XFD? Що ви отримуєте за 676 та 702?
Пітер Тейлор

Ну, це показує Excel, і я виявив, що в Інтернеті він має 16384 стовпців. Я перевіряю його завтра за допомогою нашого (відомого для роботи) коду (пізно вночі зараз, де я живу).
Vilx-

Крім того, тестування за допомогою Excel виявляє, що 676 = ZA і 702 = AAA.
Vilx-

1
Причина, яку я запитую, полягає в тому, що я написав простий код базової 26, отримав результати, які точно відповідають вашим, але зламалися на 676 і 702.
Пітер Тейлор

1
Так. Це не База-26. У цьому проблема. ;)
Вількс-

Відповіді:



20

Формула Excel :), 36 символів

=SUBSTITUTE(ADDRESS(1,A1,4),"1","")

Використання:

enter image description here

Вибачте, не втримався ...


Архх! Я насправді думав заборонити це, але забув згадати це у пості! : D Проте формули Excel не є мовою програмування (і так, Excel VBA теж поза межами). : P
Vilx-

@ Vilx- Слава Богу, хтось придумав коротше рішення. Я не хочу входити в історію, будучи єдиним, хто виграв змагання з гольфу за формулами Excel :)
Доктор belisarius

Я все одно можу прийняти вашу відповідь. >: D
Vilx-

3
<laughter type="evil">Muhahahahaha!</laughter>
Vilx-

4
Ви можете скинути 2 байти, замінивши "1"на1
Тейлор Скотт

9

Perl, 17 символів

say[A..XFD]->[<>]

..Оператор робить те ж саме, що і чарівне автопріращеніе, але без необхідності тимчасових змінного і петлі. Якщо strict subsце не в обсязі, то баревор Aі XFDне трактуються як рядки.

( Ця відповідь запропонував анонімний користувач як правкою існуючу відповідь . Я відчував , що заслуговує того, щоб бути окремим відповіддю, і зробив це один. Так як це не було б справедливо для мене , щоб отримати репутацію від нього, я » Ви зробили це спільнотою Wiki. )


Оскільки це найкоротша відповідь на даний момент, я думаю, що вона заслуговує на те, щоб бути позначеною як "прийнята", поки не знайдеться коротше рішення (можливо, доступне лише в JonSkeetScript): P Ironic.
Vilx-

1
Оскільки питання невизначене, як робиться вхід і вихід, це фактично дозволяє значно скоротити це. Наприклад, якщо вхід є, $_а вихід є значенням виразу, то (A..XFD)[$_]вирішує завдання лише 12 символів .
Ільмарі Каронен

Вибачте, як це слід запускати? З Perl 5.18 він нічого не друкує, коли він задається як аргумент до -E.
Ед Авіс

@EdAvis: Вас чекає введення номера. Або ви можете поставити число у файл і зробити perl -E 'say[A..XFD]->[<>]' < number.txt. Або в оболонках, які його підтримують, просто введіть вхід у командному рядку з perl -E 'say[A..XFD]->[<>]' <<< 123.
Ільмарі Каронен

1
Я думаю, що це можна оптимізувати доsay+(A..XFD)[<>]
Конрад Боровський

6

C, 53 символи

Це як грати в гольф молотком ...

char b[4],*p=b+3;f(i){i<0||(*--p=i%26+65,f(i/26-1));}

Звичайна версія:

char b[4];
char *p = b+3;
void f(int i) {
    if (i >= 0) {
        --p;
        *p = i%26 + 65;
        f(i/26-1);
    }
}

А використання таке:

int main(int argc, char *argv[])
{
    f(atoi(argv[1]));
    printf("%s\n", p);
    return 0;
}

5

Хаскелл, 48

f=(!!)(sequence=<<(tail$iterate(['A'..'Z']:)[]))

Менше гольфу:

f n = (concatMap sequence $ tail $ iterate (['A'..'Z'] :) []) !! n

Пояснення

sequenceКомбінатор Haskell здійснює перелік дій і виконує їх, повертаючи результат кожної дії у список. Наприклад:

sequence [getChar, getChar, getChar]

еквівалентно:

do
    a <- getChar
    b <- getChar
    c <- getChar
    return [a,b,c]

У Haskell дії трактуються як значення та склеюються за допомогою >>=(bind) та returnпримітивів. Будь-який тип може бути "дією", якщо він реалізує цих операторів, маючи Monad екземпляр .

До речі, тип списку має монадний екземпляр. Наприклад:

do
    a <- [1,2,3]
    b <- [4,5,6]
    return (a,b)

Це дорівнює [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. Зверніть увагу, наскільки розуміння списку надзвичайно схоже:

[(a,b) | a <- [1,2,3], b <- [4,5,6]]

Оскільки списки є типом "дії", ми можемо використовувати sequenceзі списками. Сказане можна виразити як:

sequence [[1,2,3],[4,5,6]]

Таким чином, sequence дає нам комбінації безкоштовно!

Таким чином, для складання списку:

["A","B"..."Z","AA","AB"]

Мені просто потрібно скласти списки, на які переходити sequence

[['A'..'Z'],['A'..'Z','A'..'Z'],...]

Потім використовуйте concatMapобидва застосувати sequenceдо списків і об'єднайте отримані списки. Випадково, concatMapце =<<функція для списків, тому монада списку дозволяє мені також поголити декілька символів.



3

Рубін, 35 символів

e=->n{a=?A;n.times{a.next!};a}

Використання:

puts e[16383]   # XFD

Примітка: Існує також скорочена версія (30 символів) з використанням рекурсії.

    e=->n{n<1??A:e[n-1].next}

Але використовуючи цю функцію, можливо, доведеться збільшити розмір стека для великої кількості, залежно від вашого перекладача на рубіні.


3

Гровий, 47

m={it<0?'':m(((int)it/26)-1)+('A'..'Z')[it%26]}

[0:'A',1:'B',25:'Z',
        26:'AA',
        27:'AB',
        51:'AZ',
        52:'BA',
        16383:'XFD'].collect {k,v-> assert v == m(k);m(k) }

3

Пітон 45 51

f=lambda i:i>=0and f(i/26-1)+chr(65+i%26)or''

ви можете вилучити дві круглі дужки, потягнувши +chr(65+i%26)всередину та протестуючи на i>=01
знак

Ви також можете поголити 4 символи, скориставшись, f=lambda i:а неdef f(i):return
Strigoides

насправді це не добре працює для чисел 37 і вище. Мені довелося трохи оновити цей код:f = lambda i: i >= 0 and f(math.floor(i / 26 - 1)) + chr(int(round(65 + i % 26))) or ''
user007

2

Скала, 62 символи

def f(i:Int):String=if(i<0)""else f((i/26)-1)+(i%26+65).toChar

Використання:

println(f(16383))

повертає:

XFD

Ви можете спробувати це на простому шкалі . Скопіюйте та вставте функцію та використовуйте f(some integer)для перегляду результату.


Вам не потрібно в ""+цій elseсправі.
Пітер Тейлор

2

Excel VBA, 31 байт

Анонімна функція негайного вікна VBE, яка приймає вхід з комірки [A1]та виводить у безпосереднє вікно VBE

?Replace([Address(1,A1,4)],1,"")


2

PHP, 30 байт

for($c=A;$argn--;)$c++;echo$c;

Запустіть як трубу з `-nr 'або спробуйте в Інтернеті .


Я впевнений, що це не робить того, що потрібно. Після Zце піде [швидше, ніж AA.
Vilx-

@ Vilx - я вважаю це доказом того, що ти не знаєш багато PHP. Я додав TiO; бачите самі.
Тіт

Святий ... ти маєш рацію! Я знаю PHP досить добре, але він настільки дивний, що неможливо все це знати. Ця особлива дивацтво мене відкинула. Ось, висловіть привітання та мої вибачення!
Vilx-

1

VBA / VB6 / VBScript (не в Excel), 73 байти

Function s(i):While i:i=i-1:s=Chr(i Mod 26+65)&s:i=i\26:Wend:End Function

Дзвінок s(16383)повернеться XFC.


Ласкаво просимо до PPCG! Чи можете ви додати пояснення користувачам, незнайомим з VB?
AdmBorkBork

1
@AdmBorkBork Не так багато, щоб додати до попередніх відповідей, просто зв’яжіть мову!
LS_ᴅᴇᴠ

Схоже, це не в усіх випадках, коли i>675 - s(676)=A@@(очікувано YZ), s(677)=A@A(очікується ZA)
Тейлор Скотт

1
@TaylorScott Ти маєш рацію. Працюючи над цим ...
LS_ᴅᴇᴠ

1
@TaylorScott Виправлено, +6 байт ... Дякую.
LS_ᴅᴇᴠ

1

Javascript, 147 байт

У мене була схожа проблема. Це гольф рішення. Колонки Excel є біективною базою-26 .

n=>{f=Math.floor;m=Math.max;x=m(0,f((n-24)/676));y=m(0,f(n/26-x*26));return String.fromCharCode(...[x,y,n+1-x*676-y*26].filter(d=>d).map(d=>d+64))}

Розширено, за винятком використання 1-індексів:

function getColName(colNum){ // example: 16384 => "XFD"
    let mostSig = Math.max(0, Math.floor((colNum - 26 - 1)/26**2));
    let midSig = Math.max(0, Math.floor((colNum - mostSig*26**2 - 1)/26));
    let leastSig = colNum - mostSig*26**2 - midSig*26;

    return String.fromCharCode(...[mostSig,midSig,leastSig].filter(d=>d).map(d=>d+64));
}

1
Ви можете додати посилання TIO. Крім того, чудова перша відповідь. Також ласкаво просимо до PPCG.
Мухаммед Салман

Також відповісти на запитання, поставлене 7 років тому, насправді не чудова ідея.
Мухаммад Салман

Гаразд, нвм це неправильно на стільки рівнів, як я ніколи цього не бачив
Мухаммед Салман

Я хотів задати це питання, але це був дублікат. Я не впевнений, що ти отримуєш у @MuhammadSalman
MattH

Я повернусь до вас за хвилину, будь ласка, ласкаво просимо до PPCG. приємна відповідь. Зауважте, що при написанні відповіді ви повинні надати повну програму або функцію
Мухаммед Салман

1

Java, 57 байт (рекурсивна)

String f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}

Спробуйте в Інтернеті.

Пояснення:

String f(int n){        // Recursive method with integer parameter and String return-type
  return n<0?           //  If `n` is negative:
    ""                  //   Return an empty String
   :                    //  Else:
    f(n/26-1)           //   Recursive call with `n` integer-divided by 26, minus 1
    +(char)(n%26+65);}  //   And append `n%26+65` as character

Java 10, 62 байти (ітеративний)

n->{var r="";for(;n>=0;n=n/26-1)r=(char)(n%26+65)+r;return r;}

Спробуйте в Інтернеті.

Пояснення:

n->{                      // Method with integer parameter and String return-type
  var r="";               //  Result-String, starting empty
  for(;n>=0;              //  Loop as long as `n` is not negative
      n=n/26-1)           //    After every iteration: divide `n` by 26, and subtract 1
    r=(char)(n%26+65)+r;  //   Prepend `n%26+65` as character to the result-String
  return r;}              //  Return the result-String

Привіт. Вибачте, але я вкрав ваш код: Ось . :)
Мухаммад Салман

@MuhammadSalman Hehe, немає проблем. Я фактично отримав своє з відповіді Скали . ;)
Кевін Круїссен

1

Четвертий (gforth) , 59 байт

: f dup 0< if drop else 26 /mod 1- recurse 65 + emit then ;

Спробуйте в Інтернеті!

Пояснення

dup 0<            \ duplicate the top of the stack and check if negative
if drop           \ if negative, drop the top of the stack
else              \ otherwise
   26 /mod        \ divide by 26 and get the quotient and remainder
   1- recurse     \ subtract one from quotient and recurse on result
   65 + emit      \ add 65 to remainder and output ascii char
then              \ exit if statement


1

Powershell, 68 байт

param($n)for(;$n-ge0;$n=($n-$r)/26-1){$s=[char](($r=$n%26)+65)+$s}$s

Альтернативна рекурсивна версія, 68 байт:

filter g{if($_-ge0){(($_-($r=$_%26))/26-1|f)+[char]($r+65)}else{''}}

Тестовий сценарій:

$f = {

param($n)for(;$n-ge0;$n=($n-$r)/26-1){$s=[char](($r=$n%26)+65)+$s}$s

}

filter g{if($_-ge0){(($_-($r=$_%26))/26-1|f)+[char]($r+65)}else{''}}


@(
    ,(0 , "A")
    ,(1 , "B")
    ,(25 , "Z")
    ,(26 , "AA")
    ,(27 , "AB")
    ,(51 , "AZ")
    ,(52 , "BA")
    ,(676 , "ZA")
    ,(702 , "AAA")
    ,(16383 , "XFD")
) | % {
    $n, $expected = $_
    $result = &$f $n
    # $result = $n|g      # Alternative
    "$($result-eq$expected): $result"
}

Вихід:

True: A
True: B
True: Z
True: AA
True: AB
True: AZ
True: BA
True: ZA
True: AAA
True: XFD

Примітка: Powershell не надає divоператора.


0

Хаскелл, 48

Я дійсно думав, що мені вдасться обіграти іншу Хаскельську запис, але на жаль ...

f(-1)=""
f n=f(div n 26-1)++[toEnum$mod n 26+65]

Я впевнений, що можна поголити пару персонажів з цього, але я не кодував у Haskell майже рік, тому я досить іржавий.

Це не зовсім те, що ви б назвали елегантним.


Непогано! :) Але Ха - після більш ніж 3 років досі немає рішення C #. : D
Vilx-

Ха-ха, справді. Але рішення C # тривіальне для написання цим самим методом. string f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}57 символів, тому я майже почуваюся погано, публікуючи це як відповідь.
Форс

0

Jq 1,5 , 71 байт

[range(1;4)as$l|[65+range(26)]|implode/""|combinations($l)]|map(add)[N]

Очікує введення в N. напр

def N:16383;

Розширено:

[                       # create array with
   range(1;4) as $l     #  for each length 1,2,3
 | [65+range(26)]       #   list of ordinal values A-Z
 | implode/""           #   converted to list of strings ["A", "B", ...]
 | combinations($l)     #   generate combinations of length $l
]
| map(add)[N]           # return specified element as a string

Спробуйте в Інтернеті!



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.