Hasilkan nama kolom excel dari indeks


21

Yang ini berasal dari masalah kehidupan nyata. Kami menyelesaikannya, tentu saja, tetapi tetap terasa seperti itu bisa dilakukan lebih baik, bahwa itu solusi yang terlalu panjang dan bundaran. Namun tidak ada kolega saya yang bisa memikirkan cara penulisan yang lebih ringkas. Karenanya saya menyajikannya sebagai kode-golf.

Tujuannya adalah untuk mengkonversi bilangan bulat negatif ke string dengan cara yang sama seperti Excel menyajikan tajuk kolomnya. Demikian:

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

Itu harus bekerja setidaknya hingga 16.383, tetapi di luar juga dapat diterima (tidak ada poin bonus sekalipun). Saya sangat menantikan solusi C #, tetapi, sesuai tradisi kode-golf, semua bahasa pemrograman yang nyata diterima.


Apakah Anda yakin 16383 adalah XFD? Apa yang Anda dapatkan untuk 676 dan 702?
Peter Taylor

Nah, itulah yang ditunjukkan Excel, dan saya temukan di web bahwa ia memiliki 16384 kolom. Saya akan mengujinya besok dengan kode (diketahui bekerja) kami (sekarang sudah larut malam di tempat saya tinggal).
Vilx-

Juga, pengujian dengan Excel sendiri mengungkapkan bahwa 676 = ZA dan 702 = AAA.
Vilx-

1
Alasan saya bertanya adalah bahwa saya menulis beberapa kode base-26 langsung, mendapat hasil yang pas dengan Anda, tetapi mematahkan 676 dan 702.
Peter Taylor

1
Ya. Itu bukan Base-26. Itulah masalahnya. ;)
Vilx-

Jawaban:



20

Formula Excel :), 36 karakter

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

Pemakaian:

masukkan deskripsi gambar di sini

Maaf, tidak bisa menahan ...


Arghh! Saya sebenarnya berpikir untuk melarang ini, tetapi lupa menyebutkannya di pos! : D Namun, rumus Excel bukan bahasa pemrograman (dan ya, Excel VBA juga terlarang). : P
Vilx-

@ Vilx- Terima kasih Tuhan seseorang datang dengan solusi yang lebih pendek. Saya tidak ingin memasukkan sejarah menjadi satu-satunya orang yang memenangkan kontes golf menggunakan rumus Excel :)
Dr. belisarius

Saya mungkin masih menerima jawaban Anda. >: D
Vilx-

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

4
Anda dapat menjatuhkan 2 byte dengan menggantinya "1"dengan1
Taylor Scott

9

Perl, 17 karakter

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

The ..Operator melakukan hal yang sama dengan ajaib auto-increment, tapi tanpa perlu untuk variabel sementara dan loop. Kecuali strict subsdalam ruang lingkup, kata pengantar Adan XFDdiartikan sebagai string.

( Jawaban ini disarankan oleh pengguna anonim sebagai pengeditan untuk jawaban yang ada . Saya merasa layak untuk menjadi jawaban yang terpisah, dan menjadikannya sebagai jawaban. Karena tidak adil bagi saya untuk mendapatkan perwakilan dari itu, saya ' telah membuatnya menjadi Wiki Komunitas. )


Karena ini adalah jawaban terpendek sejauh ini, saya kira pantas untuk ditandai sebagai "diterima" sampai solusi yang lebih pendek ditemukan (mungkin hanya tersedia di JonSkeetScript): P Ironic.
Vilx-

1
Karena pertanyaannya tidak jelas tentang bagaimana input dan output dilakukan, itu sebenarnya memungkinkan memperpendek hal ini. Misalnya, jika input masuk $_dan output adalah nilai ekspresi, maka (A..XFD)[$_]selesaikan tantangan hanya dengan 12 karakter .
Ilmari Karonen

Maaf bagaimana ini harus dijalankan? Dengan perl 5.18 tidak mencetak apa-apa saat diberikan sebagai argumen untuk -E.
Ed Avis

@EdAvis: Menunggu Anda mengetik nomor. Atau Anda bisa memasukkan nomor dalam file dan lakukan perl -E 'say[A..XFD]->[<>]' < number.txt. Atau, pada shell yang mendukungnya, cukup berikan input pada baris perintah dengan perl -E 'say[A..XFD]->[<>]' <<< 123.
Ilmari Karonen

1
Saya pikir ini dapat dioptimalkan untuksay+(A..XFD)[<>]
Konrad Borowski

6

C, 53 karakter

Ini seperti bermain golf dengan palu ...

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

Versi normal:

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

Dan penggunaannya seperti itu:

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']:)[]))

Kurang bermain golf:

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

Penjelasan

sequenceCombinator Haskell mengambil daftar tindakan dan melakukannya, mengembalikan hasil setiap tindakan dalam daftar. Sebagai contoh:

sequence [getChar, getChar, getChar]

setara dengan:

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

Di Haskell, tindakan diperlakukan seperti nilai, dan direkatkan menggunakan >>=(bind) dan returnprimitif. Jenis apa pun dapat menjadi "tindakan" jika menerapkan operator ini dengan memiliki instance Monad .

Kebetulan, tipe daftar memiliki instance monad. Sebagai contoh:

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

Ini sama dengan [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. Perhatikan bagaimana pemahaman daftar sangat mirip:

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

Karena daftar adalah jenis "tindakan", kita dapat menggunakan sequencedaftar. Di atas dapat dinyatakan sebagai:

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

Jadi, sequenceberi kami kombinasi gratis!

Jadi, untuk membangun daftar:

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

Saya hanya perlu membuat daftar untuk lolos sequence

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

Kemudian gunakan concatMapuntuk keduanya berlaku sequenceuntuk daftar, dan menggabungkan daftar yang dihasilkan. Secara kebetulan, concatMapini adalah =<<fungsi untuk daftar, jadi daftar monad memungkinkan saya mencukur beberapa karakter di sini juga.


5

Perl, 26 karakter

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

3

Ruby, 35 karakter

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

Pemakaian:

puts e[16383]   # XFD

Catatan: Ada juga versi yang lebih pendek (30 karakter) menggunakan rekursi.

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

Tetapi menggunakan fungsi ini Anda mungkin harus menambah ukuran tumpukan untuk jumlah besar tergantung pada penerjemah ruby ​​Anda.


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''

Anda dapat menghapus 2 tanda kurung dengan menarik +chr(65+i%26)masuk dan menguji i>=0, menghemat 1 karakter :)
quasimodo

Anda juga dapat mencukur 4 karakter dengan menggunakan f=lambda i:daripadadef f(i):return
Strigoides

sebenarnya itu tidak berfungsi dengan baik untuk nomor 37 dan di atas. Saya harus memperbarui kode ini sedikit:f = lambda i: i >= 0 and f(math.floor(i / 26 - 1)) + chr(int(round(65 + i % 26))) or ''
user007

2

Scala, 62 karakter

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

Pemakaian:

println(f(16383))

pengembalian:

XFD

Anda dapat mencoba ini di Cukup scala . Salin dan tempel fungsi dan gunakan f(some integer)untuk melihat hasilnya.


Anda tidak perlu ""+pada elsekasingnya.
Peter Taylor

2

Excel VBA, 31 Bytes

Fungsi jendela langsung VBE anonim yang mengambil input dari sel [A1]dan output ke jendela langsung VBE

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

2

JavaScript (Node.js) , 50 byte

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

Cobalah online!

Melihat bahwa banyak orang mulai menjawab ini, saya juga menjawab.

Catatan :

Ini pada dasarnya adalah rip off dari jawaban @ kevinCruijssen di Jawa yang dipersingkat berkat JS ini.


2

PHP, 30 byte

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

Jalankan sebagai pipa dengan `-nr 'atau coba online .


Saya cukup yakin ini tidak melakukan apa yang diperlukan. Setelah Zitu akan pergi [daripada AA.
Vilx-

@ Vilx- Saya menganggap itu sebagai bukti bahwa Anda tidak tahu banyak tentang PHP. Saya menambahkan TiO; Lihat diri mu sendiri.
Titus

Kudus ... kamu benar! Saya memang mengenal PHP dengan cukup baik, tetapi itu penuh dengan hal-hal aneh, sehingga tidak mungkin untuk mengetahui semuanya. Keanehan khusus ini mengusir saya. Di sini, dapatkan upvote dan permintaan maaf saya!
Vilx-

1

VBA / VB6 / VBScript (non-Excel), 73 byte

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

Panggilan s(16383)akan kembali XFC.


Selamat datang di PPCG! Bisakah Anda menambahkan penjelasan untuk pengguna yang tidak terbiasa dengan VB?
AdmBorkBork

1
@AdmBorkBork Tidak banyak yang ditambahkan ke jawaban sebelumnya, cukup ikat bahasa!
LS_ᴅᴇᴠ

Ini tampaknya gagal pada semua kasus di mana i>675 - s(676)=A@@(diharapkan YZ), s(677)=A@A(diharapkan ZA)
Taylor Scott

1
@TaylorScott Anda benar. Mengerjakannya ...
LS_ᴅᴇᴠ

1
@TaylorScott Dikoreksi, +6 byte ... Terima kasih.
LS_ᴅᴇᴠ

1

Javascript, 147 byte

Saya punya masalah serupa. Ini adalah golf solusinya. Kolom Excel adalah 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))}

Diperluas, kecuali menggunakan 1-indeks:

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
Anda dapat menambahkan tautan TIO. Selain itu jawaban pertama yang bagus. Juga selamat datang di PPCG.
Muhammad Salman

Juga menjawab pertanyaan yang diajukan 7 tahun lalu sebenarnya bukan ide yang bagus.
Muhammad Salman

Ok, nvm ini salah pada banyak tingkatan bagaimana saya tidak pernah melihat ini
Muhammad Salman

Saya ingin mengajukan pertanyaan ini tetapi itu adalah duplikat. Saya tidak yakin apa yang Anda maksud @MuhammadSalman
Matth

Saya akan menghubungi Anda sebentar lagi, Selamat datang di PPCG. jawaban bagus. Harap perhatikan bahwa saat menulis jawaban Anda harus menyediakan program atau fungsi lengkap
Muhammad Salman

1

Java, 57 byte (rekursif)

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

Cobalah online.

Penjelasan:

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 byte (berulang)

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

Cobalah online.

Penjelasan:

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

Hai. Maaf tapi saya mencuri kode Anda: Ini . :)
Muhammad Salman

@MuhammadSalman Hehe, tidak masalah. Saya benar-benar mendapatkan milik saya dari jawaban Scala . ;)
Kevin Cruijssen

1

Keempat (gforth) , 59 byte

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

Cobalah online!

Penjelasan

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 byte

Jawaban rekursif seperti banyak jawaban sebelumnya.

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

Cobalah online!


1

Powershell, 68 byte

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

Versi rekursif alternatif, 68 byte:

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

Skrip uji:

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

Keluaran:

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

Catatan: Powershell tidak menyediakan divoperator.


0

Haskell, 48

Saya benar-benar berpikir bahwa saya akan dapat mengalahkan entri Haskell lainnya, tetapi sayangnya ...

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

Saya yakin mungkin untuk mencukur beberapa karakter dari ini, tapi saya belum kode di Haskell selama hampir satu tahun, jadi saya cukup berkarat.

Bukan apa yang Anda sebut elegan.


Tidak buruk! :) Tapi Ha - setelah lebih dari 3 tahun, masih tidak ada solusi C #. : D
Vilx-

Haha, memang. Tetapi solusi C # adalah sepele untuk menulis menggunakan metode yang sama. string f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}57 karakter, jadi saya hampir merasa tidak enak dengan mempostingnya sebagai jawaban.
Fors

0

Jq 1,5 , 71 byte

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

Mengharapkan masukan dalam N. misalnya

def N:16383;

Diperluas:

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

Cobalah online!



Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.