Tạo tên cột excel từ chỉ mục


21

Điều này xuất phát từ một vấn đề thực tế cuộc sống. Chúng tôi đã giải quyết nó, tất nhiên, nhưng nó cảm thấy như nó có thể được thực hiện tốt hơn, đó là giải pháp quá dài và vòng vo. Tuy nhiên không ai trong số các đồng nghiệp của tôi có thể nghĩ ra một cách viết ngắn gọn hơn. Do đó tôi trình bày nó như là môn đánh gôn.

Mục tiêu là để chuyển đổi một số nguyên không âm thành một chuỗi giống như cách Excel trình bày các tiêu đề cột của nó. Như vậy:

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

Nó phải hoạt động ít nhất lên tới 16.383, nhưng vượt quá mức chấp nhận được (mặc dù không có điểm thưởng nào). Tôi mong chờ nhất cho giải pháp C #, nhưng, theo truyền thống của môn đánh gôn, bất kỳ ngôn ngữ lập trình thực sự nào đều được chào đón.


Bạn có chắc chắn rằng 16383 nên là XFD? Bạn nhận được gì cho 676 và 702?
Peter Taylor

Chà, đó là những gì Excel thể hiện và tôi đã tìm thấy trên web rằng nó có 16384 cột. Tôi sẽ kiểm tra nó vào ngày mai với mã (được biết là hoạt động) của chúng tôi (là đêm khuya ngay bây giờ nơi tôi sống).
Vilx-

Ngoài ra, kiểm tra với chính Excel cho thấy 676 = ZA và 702 = AAA.
Vilx-

1
Lý do tôi hỏi là tôi đã viết một số mã cơ sở 26 đơn giản, có kết quả phù hợp với chính xác của bạn, nhưng đã phá vỡ vào 676 và 702.
Peter Taylor

1
Vâng Đó không phải là Base-26. Đó chính là vấn đề. ;)
Vilx-

Câu trả lời:



20

Công thức Excel :), 36 ký tự

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

Sử dụng:

nhập mô tả hình ảnh ở đây

Xin lỗi, không thể cưỡng lại ...


Arghh! Tôi đã thực sự nghĩ đến việc cấm điều này, nhưng quên đề cập đến nó trong bài viết! : D Tuy nhiên, các công thức Excel không phải là ngôn ngữ lập trình (và vâng, VBA của Excel cũng bị giới hạn). : P
Vilx-

@ Vilx- Cảm ơn Chúa, ai đó đã đưa ra một giải pháp ngắn hơn. Tôi không muốn đi vào lịch sử là người duy nhất giành chiến thắng trong một cuộc thi golf bằng công thức Excel :)
Tiến sĩ belisarius

Tôi vẫn có thể chấp nhận câu trả lời của bạn. >: D
Vilx-

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

4
Bạn có thể giảm 2 byte bằng cách thay thế "1"bằng1
Taylor Scott

9

Perl, 17 ký tự

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

Các ..nhà điều hành làm điều tương tự như huyền diệu auto-increment, nhưng không có nhu cầu sử dụng biến tạm thời và vòng lặp. Trừ khi strict subslà trong phạm vi, các barewords AXFDđược hiểu là chuỗi.

( Câu trả lời này được đề xuất bởi một người dùng ẩn danh dưới dạng chỉnh sửa cho câu trả lời hiện có . Tôi cảm thấy nó xứng đáng là một câu trả lời riêng biệt và đã đưa ra câu trả lời. Vì tôi sẽ không công bằng khi nhận được đại diện từ nó, tôi đã làm cho nó Cộng đồng Wiki. )


Vì đó là câu trả lời ngắn nhất cho đến nay, tôi đoán rằng nó xứng đáng được đánh dấu là "được chấp nhận" cho đến khi tìm thấy giải pháp ngắn hơn (có lẽ chỉ có trong JonSkeetScript): P Ironic.
Vilx-

1
Vì câu hỏi mơ hồ về cách thực hiện đầu vào và đầu ra, điều đó thực sự cho phép rút ngắn đáng kể điều này. Ví dụ: nếu đầu vào nằm trong $_và đầu ra là giá trị của biểu thức, thì sẽ (A..XFD)[$_]giải quyết thách thức chỉ với 12 ký tự .
Ilmari Karonen

Xin lỗi làm thế nào điều này nên được chạy? Với perl 5.18, nó không in gì khi được đưa ra làm đối số cho -E.
Ed Avis

@EdAvis: Đang chờ bạn nhập số. Hoặc bạn có thể đặt số trong một tập tin và làm perl -E 'say[A..XFD]->[<>]' < number.txt. Hoặc, trong các shell hỗ trợ nó, chỉ cần cung cấp đầu vào trên dòng lệnh với perl -E 'say[A..XFD]->[<>]' <<< 123.
Ilmari Karonen

1
Tôi nghĩ điều này có thể được tối ưu hóa thànhsay+(A..XFD)[<>]
Konrad Borowski

6

C, 53 ký tự

Nó giống như chơi golf với một cái búa ...

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

Phiên bản bình thường:

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

Và cách sử dụng là như thế:

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

Ít chơi gôn hơn:

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

Giải trình

Người sequencekết hợp của Haskell lấy một danh sách các hành động và thực hiện chúng, trả về kết quả của từng hành động trong một danh sách. Ví dụ:

sequence [getChar, getChar, getChar]

tương đương với:

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

Trong Haskell, các hành động được coi như các giá trị và được dán lại với nhau bằng cách sử dụng >>=(liên kết) và returnnguyên thủy. Bất kỳ loại nào cũng có thể là một "hành động" nếu nó thực hiện các toán tử này bằng cách có một cá thể Monad .

Ngẫu nhiên, loại danh sách có một thể hiện đơn nguyên. Ví dụ:

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

Điều này bằng [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. Lưu ý cách hiểu danh sách tương tự nhau:

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

Vì danh sách là một loại "hành động", chúng tôi có thể sử dụng sequencevới danh sách. Trên đây có thể được thể hiện như sau:

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

Do đó, sequencecho chúng tôi kết hợp miễn phí!

Do đó, để xây dựng danh sách:

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

Tôi chỉ cần xây dựng danh sách để vượt qua sequence

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

Sau đó sử dụng concatMapđể cả hai áp dụng sequencecho các danh sách và nối các danh sách kết quả. Thật trùng hợp, concatMap=<<chức năng cho các danh sách, do đó, danh sách đơn vị cũng cho phép tôi cạo một vài ký tự ở đây.


5

Perl, 26 ký tự

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

3

Ruby, 35 ký tự

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

Sử dụng:

puts e[16383]   # XFD

Lưu ý: Ngoài ra còn có phiên bản ngắn hơn (30 ký tự) bằng cách sử dụng đệ quy.

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

Nhưng sử dụng chức năng này, bạn có thể phải tăng kích thước ngăn xếp cho số lượng lớn tùy thuộc vào trình thông dịch ruby ​​của bạn.


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

Con trăn 45 51

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

bạn có thể xóa 2 dấu ngoặc đơn bằng cách kéo +chr(65+i%26)vào bên trong và kiểm tra i>=0, tiết kiệm cho bạn 1 ký tự :)
quasimodo

Bạn cũng có thể tắt 4 ký tự bằng cách sử dụng f=lambda i:thay vìdef f(i):return
Strigoides

thực tế điều đó không hoạt động tốt cho các số 37 trở lên. Tôi đã phải cập nhật mã này một chút:f = lambda i: i >= 0 and f(math.floor(i / 26 - 1)) + chr(int(round(65 + i % 26))) or ''
user007

2

Scala, 62 ký tự

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

Sử dụng:

println(f(16383))

trả về:

XFD

Bạn có thể thử điều này trên Simply scala . Sao chép và dán chức năng và sử dụng f(some integer)để xem kết quả.


Bạn không cần ""+vào elsetrường hợp.
Peter Taylor

2

VBA Excel, 31 byte

Hàm cửa sổ tức thời VBE ẩn danh lấy đầu vào từ ô [A1]và xuất ra cửa sổ ngay lập tức VBE

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

2

JavaScript (Node.js) , 50 byte

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

Hãy thử trực tuyến!

Thấy nhiều người bắt đầu trả lời nên tôi cũng trả lời.

Chú thích :

Về cơ bản, đây là một sự rút gọn câu trả lời của @ kevinCruijssen trong Java rút ngắn nhờ đây là JS.


2

PHP, 30 byte

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

Chạy như đường ống với `-nr 'hoặc thử trực tuyến .


Tôi khá chắc chắn rằng điều này không làm những gì được yêu cầu. Sau Znó sẽ đi [chứ không phải AA.
Vilx-

@ Vilx- Tôi lấy đó làm bằng chứng cho thấy Bạn không biết nhiều về PHP. Tôi đã thêm một TiO; xem cho chính mình.
Tít

Thánh ... bạn nói đúng! Tôi biết PHP khá rõ, nhưng nó chứa đầy những thứ kỳ lạ, đến mức không thể biết hết được. Điều kỳ lạ đặc biệt này đã ném tôi đi. Ở đây, có một upvote và lời xin lỗi của tôi!
Vilx-

1

VBA / VB6 / VBScript (không phải Excel), 73 byte

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

Gọi s(16383)sẽ trả lại XFC.


Chào mừng đến với PPCG! Bạn có thể thêm một lời giải thích cho người dùng không quen thuộc với VB?
admBorkBork

1
@AdmBorkBork Không có nhiều để thêm vào câu trả lời trước, chỉ cần liên kết ngôn ngữ!
LS_ᴅᴇᴠ

Điều này dường như thất bại trong tất cả các trường hợp i>675 - s(676)=A@@(dự kiến YZ), s(677)=A@A(dự kiến ZA)
Taylor Scott

1
@TaylorScott Bạn nói đúng. Làm việc trên nó ...
LS_ᴅᴇᴠ

1
@TaylorScott Đã sửa, +6 byte ... Cảm ơn.
LS_ᴅᴇᴠ

1

Javascript, 147 byte

Tôi đã có một vấn đề tương tự. Đây là golf của giải pháp. Các cột Excel là cơ sở sinh học-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))}

Mở rộng, ngoại trừ sử dụng 1 chỉ số:

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
Bạn có thể thêm một liên kết TIO. Khác hơn đó là một câu trả lời đầu tiên tuyệt vời. Cũng chào mừng đến với PPCG.
Muhammad Salman

Ngoài ra trả lời một câu hỏi 7 năm trước đây không thực sự là một ý tưởng tuyệt vời.
Muhammad Salman

Ok, nvm điều này là sai ở rất nhiều cấp độ, làm thế nào mà tôi chưa từng thấy điều này
Muhammad Salman

Tôi muốn hỏi câu hỏi này nhưng nó là một bản sao. Tôi không chắc chắn những gì bạn nhận được tại @MuhammadSalman
MattH

Tôi sẽ quay lại với bạn sau một phút nữa, Dù sao cũng chào mừng bạn đến với PPCG. câu trả lời tốt đẹp. Xin lưu ý rằng khi viết câu trả lời, bạn phải cung cấp một chương trình đầy đủ hoặc một chức năng
Muhammad Salman

1

Java, 57 byte (đệ quy)

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

Hãy thử trực tuyến.

Giải trình:

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 (lặp)

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

Hãy thử trực tuyến.

Giải trình:

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

Chào. Xin lỗi nhưng tôi đã đánh cắp mã của bạn: Ở đây . :)
Muhammad Salman

@MuhammadSalman Hehe, không vấn đề gì. Tôi thực sự có của tôi từ câu trả lời Scala . ;)
Kevin Cruijssen

1

Forth (gforth) , 59 byte

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

Hãy thử trực tuyến!

Giải trình

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 byte

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

Phiên bản đệ quy thay thế, 68 byte:

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

Kịch bản thử nghiệm:

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

Đầu ra:

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

Lưu ý: Powershell không cung cấp divtoán tử.


0

Haskell, 48

Tôi thực sự nghĩ rằng tôi sẽ có thể đánh bại mục Haskell khác, nhưng than ôi ...

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

Tôi chắc chắn có thể loại bỏ một vài nhân vật khỏi điều này, nhưng tôi đã không được mã hóa trong Haskell trong gần một năm, vì vậy tôi khá là gỉ.

Đó không phải là chính xác những gì bạn sẽ gọi là thanh lịch.


Không tệ! :) Nhưng Hà - sau hơn 3 năm, vẫn không có giải pháp C #. : D
Vilx-

Haha, thực sự Nhưng một giải pháp C # là tầm thường để viết bằng phương pháp tương tự. string f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}57 ký tự, vì vậy tôi gần như sẽ cảm thấy tồi tệ bằng cách đăng nó dưới dạng câu trả lời.
Dành cho

0

Jq 1.5 , 71 byte

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

Mong đợi đầu vào N. ví dụ

def N:16383;

Mở rộng:

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

Hãy thử trực tuyến!



Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.