Wygeneruj nazwę kolumny programu Excel z indeksu


21

Ten pochodzi z prawdziwego problemu z życia. Oczywiście rozwiązaliśmy to, ale nadal wydaje się, że można to zrobić lepiej, że jest to zbyt długie i okrągłe rozwiązanie. Jednak żaden z moich kolegów nie może wymyślić bardziej zwięzłego sposobu napisania tego. Dlatego przedstawiam to jako golf golfowy.

Celem jest przekonwertowanie nieujemnej liczby całkowitej na ciąg znaków w taki sam sposób, w jaki program Excel prezentuje nagłówki kolumn. A zatem:

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

Musi działać co najmniej do 16 383, ale poza tym jest również do przyjęcia (choć nie ma punktów bonusowych). Nie mogę się doczekać rozwiązania C #, ale zgodnie z tradycjami gry w golfa jest mile widziany każdy prawdziwy język programowania.


Czy na pewno 16383 powinno być XFD? Co dostajesz za 676 i 702?
— Peter Taylor

Cóż, to pokazuje Excel i znalazłem w Internecie, że ma 16384 kolumny. Przetestuję to jutro z naszym (znanym z pracy) kodem (jest teraz późno w nocy, gdzie mieszkam).
— Vilx-

Ponadto testy z samym Excelem wykazują, że 676 = ZA i 702 = AAA.
— Vilx-

1
Pytam dlatego, że napisałem prosty kod 26, uzyskałem wyniki, które dokładnie pasują do twojego, ale zepsuły się na 676 i 702.
— Peter Taylor

1
Tak. To nie jest Base-26. To jest problem. ;)
— Vilx-

Odpowiedzi:



20

Formuła Excel :), 36 znaków

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

Stosowanie:

enter image description here

Przepraszam, nie mogłem się oprzeć ...


Aaaa! Myślałem o zakazaniu tego, ale zapomniałem o tym wspomnieć w poście! : D Mimo to formuły programu Excel nie są językiem programowania (i tak, program Excel VBA jest również niedostępny). : P
— Vilx

@ Vilx- Dzięki Bogu ktoś wymyślił krótsze rozwiązanie. Nie chcę wchodzić w historię jako jedyna osoba, która wygrała zawody golfowe przy użyciu formuł Excela :)
— Dr. Belisarius

Nadal mogę przyjąć twoją odpowiedź. >: D
— Vilx

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

4
Można upuścić 2 bajty zastępując "1"z1
— Taylor Scotta

9

Perl, 17 znaków

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

..Operator robi to samo, co magicznego automatycznego przyrostu, ale bez konieczności czasowego zmiennej i pętli. O ile nie strict subsjest w zakresie, na gołe słowa Ai XFDsą interpretowane jako ciągi.

( Ta odpowiedź była zasugerowana przez anonimowego użytkownika jako edycja istniejącej odpowiedzi . Czułem, że zasługuje na osobną odpowiedź, i uczyniłem ją jedną. Ponieważ nie byłoby fair, aby uzyskać z niej przedstawiciela, ja ” stworzyliśmy Wiki Wiki. )


Ponieważ jest to jak dotąd najkrótsza odpowiedź, myślę, że należy ją oznaczyć jako „zaakceptowaną”, dopóki nie zostanie znalezione krótsze rozwiązanie (prawdopodobnie dostępne tylko w JonSkeetScript): P Ironic.
— Vilx-

1
Ponieważ pytanie, w jaki sposób dokonywane są dane wejściowe i wyjściowe, jest niejasne, pozwala to znacznie je skrócić. Na przykład, jeśli wejście jest w, $_a wyjście jest wartością wyrażenia, to (A..XFD)[$_]rozwiązuje wyzwanie tylko z 12 znakami .
— Ilmari Karonen

Przepraszam, jak to powinno być uruchomione? W perlu 5.18 nic nie wypisuje, gdy podano jako argument -E.
— Ed Avis,

@EdAvis: Czeka na Ciebie wpisanie numeru. Lub możesz umieścić numer w pliku i zrobić perl -E 'say[A..XFD]->[<>]' < number.txt. Lub, w powłokach, które go obsługują, po prostu podaj dane w wierszu poleceń za pomocą perl -E 'say[A..XFD]->[<>]' <<< 123.
— Ilmari Karonen

1
Myślę, że można to zoptymalizowaćsay+(A..XFD)[<>]
— Konrad Borowski

6

C, 53 znaki

To jak grać w golfa młotkiem ...

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

Wersja normalna:

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

A użycie jest takie:

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

5

Haskell, 48

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

Mniej golfa:

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

Wyjaśnienie

sequenceKombinator Haskella pobiera listę akcji i wykonuje je, zwracając wynik każdej akcji z listy. Na przykład:

sequence [getChar, getChar, getChar]

jest równa:

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

W Haskell akcje są traktowane jak wartości i są sklejane za pomocą >>=(bind) i returnprymitywów. Każdy typ może być „działaniem”, jeśli implementuje te operatory poprzez instancję Monady .

Nawiasem mówiąc, typ listy ma instancję monady. Na przykład:

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

To się równa [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. Zwróć uwagę, jak rozumienie listy jest uderzająco podobne:

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

Ponieważ listy są rodzajem „akcji”, możemy ich używać sequencez listami. Powyższe można wyrazić jako:

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

W ten sposób sequencedaje nam połączona za darmo!

Tak więc, aby zbudować listę:

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

Muszę tylko zbudować listy, aby przejść sequence

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

Następnie użyj, concatMapaby zastosować oba sequencedo list i połączyć uzyskane listy. Przypadkowo concatMapjest to =<<funkcja list, więc monada listy pozwala mi również ogolić tutaj kilka znaków.



3

Ruby, 35 znaków

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

Stosowanie:

puts e[16383]   # XFD

Uwaga: Istnieje również krótsza wersja (30 znaków) z rekurencją.

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

Ale korzystając z tej funkcji, być może będziesz musiał zwiększyć rozmiar stosu dla dużych liczb w zależności od interpretera ruby.


3

Groovy, 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

Python 45 51

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

możesz usunąć 2 nawiasy, wsuwając się do +chr(65+i%26)środka i testując i>=0, oszczędzając 1 znak :)
— quasimodo

Możesz także ogolić 4 znaki, używając f=lambda i:zamiastdef f(i):return
— Strigoides,

właściwie to nie działa dobrze dla liczb 37 i wyższych. Musiałem trochę zaktualizować ten kod:f = lambda i: i >= 0 and f(math.floor(i / 26 - 1)) + chr(int(round(65 + i % 26))) or ''
— user007

2

Scala, 62 znaki

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

Stosowanie:

println(f(16383))

zwroty:

XFD

Możesz tego spróbować na Simply scala . Skopiuj i wklej funkcję i użyj, f(some integer)aby zobaczyć wynik.


Nie potrzebujesz ""+tej elseskrzynki.
— Peter Taylor

2

Excel VBA, 31 bajtów

Anonimowa funkcja bezpośredniego okna VBE, która przenosi dane wejściowe z komórki [A1]i dane wyjściowe do bezpośredniego okna VBE

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

2

JavaScript (Node.js) , 50 bajtów

f=_=>_<0?'':f(_/26-1)+String.fromCharCode(_%26+65)

Wypróbuj online!

Widząc, że wiele osób zaczęło na nie odpowiadać, ja również odpowiedziałem.

Uwaga :

Jest to w zasadzie zdzierstwo odpowiedzi @ kevinCruijssen w Javie skróconej dzięki temu, że jest JS.


2

PHP, 30 bajtów

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

Uruchom jako potok z `-nr 'lub wypróbuj online .


Jestem prawie pewien, że to nie robi tego, co jest wymagane. Po Ztym [raczej by poszło AA.
— Vilx-

@ Vilx- Przyjmuję to za dowód, że nie znasz dużo PHP. Dodałem TiO; Sam zobacz.
— Tytus

Święty ... masz rację! Znam PHP dość dobrze, ale jest tak pełen dziwnych rzeczy, że nie można tego wszystkiego poznać. Ta szczególna dziwność mnie odrzuciła. Proszę, oddaj głos i przepraszam!
— Vilx-

1

VBA / VB6 / VBScript (inny niż Excel), 73 bajty

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

Dzwonienie s(16383)powróci XFC.


Witamy w PPCG! Czy możesz dodać wyjaśnienie dla użytkowników, którzy nie znają VB?
— AdmBorkBork

1
@AdmBorkBork Niewiele do dodania do poprzednich odpowiedzi, wystarczy powiązanie językowe!
— LS_ᴅᴇᴠ

To wydaje się nie działać we wszystkich przypadkach, w których i>675 - s(676)=A@@(oczekiwany YZ), s(677)=A@A(oczekiwany ZA)
— Taylor Scott

1
@TaylorScott Masz rację. Pracuję nad tym ...
— LS_ᴅᴇᴠ

1
@TaylorScott Poprawione, +6 bajtów ... Dzięki.
— LS_ᴅᴇᴠ

1

JavaScript, 147 bajtów

Miałem podobny problem. To jest golf rozwiązania. Kolumny Excel są bijective base-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))}

Rozszerzone, z wyjątkiem użycia 1-wskaźników:

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
Możesz dodać link TIO. Poza tym świetna pierwsza odpowiedź. Witamy również w PPCG.
— Muhammad Salman

Odpowiedź na pytanie zadane 7 lat temu nie jest naprawdę świetnym pomysłem.
— Muhammad Salman

Ok, nvm, to jest złe na tak wielu poziomach, jak ja tego nigdy nie widziałem
— Muhammad Salman

Chciałem zadać to pytanie, ale było to duplikat. Nie jestem pewien, co otrzymujesz w @MuhammadSalman
— MattH

Wrócę do ciebie za minutę. W każdym razie witamy w PPCG. niezła odpowiedź. Plz pamiętaj, że pisząc odpowiedź, musisz podać pełny program lub funkcję
— Muhammad Salman

1

Java, 57 bajtów (rekurencyjne)

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

Wypróbuj online.

Wyjaśnienie:

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 bajty (iteracyjne)

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

Wypróbuj online.

Wyjaśnienie:

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

Cześć. Przepraszam, ale ukradłem twój kod: tutaj . :)
— Muhammad Salman

@MuhammadSalman Hehe, nie ma problemu. Właściwie mam swoją odpowiedź Scali . ;)
— Kevin Cruijssen

1

Dalej (gforth) , 59 bajtów

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

Wypróbuj online!

Wyjaśnienie

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

R , 65 bajtów

Odpowiedź rekurencyjna, tak jak wiele poprzednich odpowiedzi.

function(n,u=LETTERS[n%%26+1])"if"(n<=25,u,paste0(g(n%/%26-1),u))

Wypróbuj online!


1

PowerShell, 68 bajtów

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

Alternatywna wersja rekurencyjna, 68 bajtów:

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

Skrypt testowy:

$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"
}

Wynik:

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

Uwaga: PowerShell nie udostępnia divoperatora.


0

Haskell, 48

Naprawdę myślałem, że uda mi się pokonać inne wejście do Haskell, ale niestety ...

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

Jestem pewien, że można zgolić kilka postaci, ale nie kodowałem w Haskell od prawie roku, więc jestem dość zardzewiały.

To nie jest dokładnie to, co nazwałbyś eleganckim.


Nie jest zły! :) Ale Ha - po ponad 3 latach wciąż nie ma rozwiązania C #. : D
— Vilx

Haha, rzeczywiście. Ale rozwiązanie w języku C # jest łatwe do napisania przy użyciu tej samej metody. string f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}57 znaków, więc prawie czułbym się źle, publikując go jako odpowiedź.
— Fors

0

Jq 1,5 , 71 bajtów

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

Oczekuje wkładu N . na przykład

def N:16383;

Rozszerzony:

[                       # 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

Wypróbuj online!



Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.