Generieren Sie den Namen der Excel-Spalte aus dem Index

21

Dieser kommt von einem realen Problem. Wir haben es natürlich gelöst, aber wir haben immer das Gefühl, es hätte besser gemacht werden können, dass es zu langwierig und umständlich ist. Allerdings kann sich keiner meiner Kollegen eine prägnantere Schreibweise vorstellen. Daher präsentiere ich es als Code-Golf.

Das Ziel ist es, eine nichtnegative Ganzzahl in eine Zeichenfolge zu konvertieren, so wie Excel die Spaltenüberschriften darstellt. Somit:

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

Es muss mindestens bis zu 16.383 funktionieren, aber darüber hinaus ist es auch akzeptabel (aber keine Bonuspunkte). Ich freue mich am meisten auf die C # -Lösung, aber gemäß den Traditionen von Code-Golf ist jede echte Programmiersprache willkommen.

Vilx-
quelle
Sind Sie sicher, dass 16383 XFD sein sollte? Was bekommen Sie für 676 und 702?
Peter Taylor
Genau das zeigt Excel, und ich habe im Web festgestellt, dass es 16384 Spalten hat. Ich werde es morgen mit unserem (für die Arbeit bekannten) Code testen (es ist spät in der Nacht, in der ich wohne).
Vilx 24.
Testen mit Excel selbst zeigt außerdem, dass 676 = ZA und 702 = AAA.
Vilx
1
Der Grund, den ich frage, ist, dass ich einen einfachen Base-26-Code geschrieben habe, Ergebnisse erzielt habe, die genau zu Ihnen passen, aber bei 676 und 702 gebrochen haben.
Peter Taylor,
1
Jep. Es ist nicht Base-26. Das ist das Problem. ;)
Vilx-

Antworten:

3

Perl 6 ,16 14 Bytes

{("A"..*)[$_]}

Funktioniert auch über XFD hinaus. Dank der unendlichen Listen in Perl 6 dauert die Ausführung nicht ewig (anderthalb).

Probieren Sie es online!

Konrad Borowski
quelle
20

Excel Formula :), 36 Zeichen

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

Verwendung:

Bildbeschreibung hier eingeben

Entschuldigung, konnte nicht widerstehen ...

Dr. belisarius
quelle
Arghh! Ich hatte tatsächlich daran gedacht, dies zu verbieten, aber vergessen, es in der Post zu erwähnen! : D Trotzdem sind Excel-Formeln keine Programmiersprache (und ja, Excel VBA ist auch tabu). : P
Vilx
@ Vilx- Gott sei Dank hat sich jemand eine kürzere Lösung ausgedacht. Ich möchte nicht in die Geschichte eingehen, als einzige Person, die einen Golfwettbewerb mit Excel-Formeln gewonnen hat :)
Dr. belisarius
Ich könnte immer noch Ihre Antwort akzeptieren. >: D
Vilx
3
<laughter type="evil">Muhahahahaha!</laughter>
Vilx
4
Sie können durch Ersetzen von 2 Bytes fallen "1"mit1
Taylor Scott
9

Perl, 17 Zeichen

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

Der ..Operator macht dasselbe wie das magische automatische Inkrementieren, benötigt jedoch keine temporäre Variable und Schleife. Es sei denn , strict subsin Rahmen ist, die Barewords Aund XFDwerden als Strings interpretiert.

( Diese Antwort wurde vorgeschlagen , von einem anonymen Benutzer als Bearbeitung auf einer bestehenden Antwort . Ich fühlte es verdient eine gesonderte Antwort zu sein, und haben es zu einem gemacht. Da es nicht fair wäre für mich rep zu gewinnen aus, ich‘ habe es zum Community Wiki gemacht. )

Ilmari Karonen
quelle
Da es sich bisher um die kürzeste Antwort handelt, sollte sie meines Erachtens als "akzeptiert" markiert werden, bis eine kürzere Lösung gefunden wird (wahrscheinlich nur in JonSkeetScript verfügbar): P Ironic.
Vilx
1
Da die Frage, wie Input und Output erfolgen, vage ist, kann dies tatsächlich erheblich verkürzt werden. Wenn beispielsweise die Eingabe in $_und die Ausgabe der Wert des Ausdrucks ist, wird (A..XFD)[$_]die Herausforderung mit nur 12 Zeichen gelöst .
Ilmari Karonen
Entschuldigung, wie soll das laufen? In Perl 5.18 gibt es nichts aus, wenn es als Argument an -E übergeben wird.
Ed Avis
@EdAvis: Es wartet darauf, dass Sie eine Nummer eingeben. Oder Sie könnten die Nummer in eine Datei einfügen und tun perl -E 'say[A..XFD]->[<>]' < number.txt. Oder geben Sie in Shells, die dies unterstützen, einfach die Eingabe in der Befehlszeile mit ein perl -E 'say[A..XFD]->[<>]' <<< 123.
Ilmari Karonen
1
Ich denke, das kann optimiert werdensay+(A..XFD)[<>]
Konrad Borowski
6

C, 53 Zeichen

Es ist, als würde man mit einem Hammer Golf spielen ...

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

Normale Version:

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

Und die Verwendung ist wie folgt:

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

Haskell, 48

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

Weniger golfen:

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

Erläuterung

Der sequenceKombinator von Haskell führt eine Liste von Aktionen durch und gibt das Ergebnis jeder Aktion in einer Liste zurück. Beispielsweise:

sequence [getChar, getChar, getChar]

ist äquivalent zu:

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

In Haskell werden Aktionen wie Werte behandelt und unter Verwendung von >>=(Binden) und returnPrimitiven zusammengeklebt. Jeder Typ kann eine "Aktion" sein, wenn er diese Operatoren durch eine Monade implementiert Instanz .

Übrigens hat der Listentyp eine Monadeninstanz. Beispielsweise:

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

Das ist gleich [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. Beachten Sie, dass das Listenverständnis auffällig ähnlich ist:

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

Da Listen eine Art "Aktion" sind, können wir sie sequencemit Listen verwenden. Das Obige kann ausgedrückt werden als:

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

Somit, sequence gibt uns Kombinationen kostenlos!

So erstellen Sie die Liste:

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

Ich muss nur Listen erstellen, an die ich übergebe sequence

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

Verwenden Sie dann, concatMapum beide sequenceauf die Listen anzuwenden und die resultierenden Listen zu verketten. Zufälligerweise concatMapist dies die =<<Funktion für Listen. Mit der Listenmonade kann ich auch hier einige Zeichen rasieren.

Joey Adams
quelle
5

Perl, 26 Zeichen

$x='A';map$x++,1..<>;say$x
Toto
quelle
3

Ruby, 35 Zeichen

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

Verwendung:

puts e[16383]   # XFD

Hinweis: Es gibt auch eine kürzere Version (30 Zeichen) mit Rekursion.

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

Bei Verwendung dieser Funktion müssen Sie möglicherweise die Stapelgröße für große Zahlen erhöhen, abhängig von Ihrem Ruby-Interpreter.

Howard
quelle
3

Groovy, 47 Jahre alt

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) }
Armand
quelle
3

Python 45 51

f=lambda i:i>=0and f(i/26-1)+chr(65+i%26)or''
Daniel
quelle
Sie können 2 Klammern entfernen, indem Sie nach +chr(65+i%26)innen ziehen und testen i>=0, um 1 Zeichen zu speichern :)
quasimodo
Sie können auch 4 Zeichen aus , indem Sie rasieren , f=lambda i:anstattdef f(i):return
strigoides
Tatsächlich funktioniert das nicht gut für die Nummern 37 und höher. Ich musste diesen Code ein wenig aktualisieren:f = lambda i: i >= 0 and f(math.floor(i / 26 - 1)) + chr(int(round(65 + i % 26))) or ''
user007
2

Scala, 62 Zeichen

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

Verwendung:

println(f(16383))

kehrt zurück:

XFD

Sie können dies mit Simply Scala ausprobieren . Kopieren Sie die Funktion, fügen Sie sie ein und verwenden Sie f(some integer), um das Ergebnis anzuzeigen.

Gareth
quelle
Sie brauchen das ""+auf dem elseFall nicht.
Peter Taylor
2

Excel VBA, 31 Bytes

Anonyme VBE-Direktfensterfunktion, die Eingaben von der Zelle [A1]und Ausgaben in das VBE-Direktfenster übernimmt

?Replace([Address(1,A1,4)],1,"")
Taylor Scott
quelle
2

JavaScript (Node.js) , 50 Byte

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

Probieren Sie es online!

Als ich sah, dass viele Leute anfingen, darauf zu antworten, antwortete ich auch.

Hinweis :

Dies ist im Grunde eine Abzocke der Antwort von @ kevinCruijssen in Java, die dank JS verkürzt wurde.

Muhammad Salman
quelle
2

PHP, 30 Bytes

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

Führe es als Pipe mit -nr aus oder versuche es online .

Titus
quelle
Ich bin mir ziemlich sicher, dass dies nicht das tut, was erforderlich ist. Danach Zwürde es [eher gehen als AA.
Vilx
@ Vilx- Ich nehme das als Beweis dafür, dass du nicht viel PHP kennst. Ich habe ein TiO hinzugefügt; überzeugen Sie sich selbst.
Titus
Heilig ... du hast recht! Ich kenne PHP ziemlich gut, aber es ist so voll von seltsamen Dingen, dass es unmöglich ist, alles zu wissen. Diese besondere Kuriosität warf mich ab. Hier, habt eine Gegenstimme und ich entschuldige mich!
Vilx
1

VBA / VB6 / VBScript (nicht Excel), 73 Byte

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

Der Anruf s(16383)wird zurückgegeben XFC.

LS_ᴅᴇᴠ
quelle
Willkommen bei PPCG! Können Sie eine Erklärung für Benutzer hinzufügen, die mit VB nicht vertraut sind?
AdmBorkBork
1
@AdmBorkBork Es gibt nicht viel zu früheren Antworten hinzuzufügen, nur Sprachbindung!
LS_ᴅᴇᴠ
Dies scheint in allen Fällen zu scheitern, in denen i>675 - s(676)=A@@(erwartet YZ), s(677)=A@A(erwartet ZA)
Taylor Scott
1
@ TaylorScott Du hast recht. Arbeiten daran ...
LS_ᴅᴇᴠ
1
@ TaylorScott Korrigiert, +6 Bytes ... Danke.
LS_ᴅᴇᴠ
1

Javascript, 147 Bytes

Ich hatte ein ähnliches Problem. Das ist der Golf der Lösung. Excel-Spalten sind bijektive Basis 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))}

Erweitert, außer bei Verwendung von 1-Indizes:

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));
}
MattH
quelle
1
Sie könnten einen TIO-Link hinzufügen. Davon abgesehen eine großartige erste Antwort. Willkommen auch bei PPCG.
Muhammad Salman
Auch die Beantwortung einer vor 7 Jahren gestellten Frage ist keine wirklich gute Idee.
Muhammad Salman
Ok, nvm das ist auf so vielen Ebenen falsch, wie habe ich das jemals nicht gesehen
Muhammad Salman
Ich wollte diese Frage stellen, aber es war ein Duplikat. Ich bin mir nicht sicher, was du bei @ MuhammadSalman
MattH
Ich werde mich in Kürze bei Ihnen melden. Wie auch immer, willkommen bei PPCG. gute Antwort. Bitte beachten Sie, dass Sie beim Schreiben einer Antwort ein vollständiges Programm oder eine Funktion angeben müssen
Muhammad Salman,
1

Java, 57 Bytes (rekursiv)

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

Probieren Sie es online aus.

Erläuterung:

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 Bytes (iterativ)

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

Probieren Sie es online aus.

Erläuterung:

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
Kevin Cruijssen
quelle
Hallo. Entschuldigung, aber ich habe Ihren Code gestohlen: Hier . :)
Muhammad Salman
@ Muhammad Salman Hehe, kein Problem. Ich habe meine tatsächlich von der Scala-Antwort erhalten . ;)
Kevin Cruijssen
1

Viertens (gviertens) , 59 Bytes

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

Probieren Sie es online!

Erläuterung

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
reffu
quelle
1

R , 65 Bytes

Rekursive Antwort wie viele frühere Antworten.

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

Probieren Sie es online!

JayCe
quelle
1

Powershell, 68 Bytes

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

Alternative rekursive Version, 68 Bytes:

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

Testskript:

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

Ausgabe:

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

Hinweis: Powershell bietet keinen divOperator.

mazzy
quelle
0

Haskell, 48

Ich dachte wirklich, dass ich den anderen Haskell-Eintrag schlagen könnte, aber leider ...

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

Ich bin mir sicher, dass es möglich ist, ein paar Charaktere davon abzuhalten, aber ich habe fast ein Jahr lang nicht in Haskell codiert, also bin ich ziemlich rostig.

Es ist nicht genau das, was Sie als elegant bezeichnen würden.

Fors
quelle
Nicht schlecht! :) Aber Ha - nach mehr als 3 Jahren noch keine C # -Lösung. : D
Vilx
Haha, in der Tat. Es ist jedoch trivial, eine C # -Lösung mit derselben Methode zu schreiben. string f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}57 Zeichen, also würde ich mich fast schlecht fühlen, wenn ich es als Antwort posten würde.
Fors
0

Jq 1,5 , 71 Bytes

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

Erwartet Eingaben in N. z.B

def N:16383;

Erweitert:

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

Probieren Sie es online!

jq170727
quelle