สร้างชื่อคอลัมน์ 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
Peter Taylor

นั่นคือสิ่งที่ Excel แสดงและฉันพบบนเว็บว่ามีคอลัมน์ 16384 ฉันจะทดสอบในวันพรุ่งนี้ด้วยรหัส (ที่รู้จักกันในการทำงาน) ของเรา (ตอนดึกตอนนี้ที่ฉันอยู่)
Vilx-

นอกจากนี้การทดสอบกับ Excel นั้นพบว่า 676 = ZA และ 702 = AAA
Vilx-

1
เหตุผลที่ผมถามคือว่าผมเขียนบางอย่างตรงไปตรงมาฐาน-26 รหัสได้ผลลัพธ์ที่เหมาะสมของคุณได้อย่างแม่นยำ แต่ยากจนใน 676 และ 702
ปีเตอร์เทย์เลอร์

1
ได้. ไม่ใช่ Base-26 นั่นคือปัญหา. ;)
Vilx-

คำตอบ:



20

Excel Formula :), 36 ตัวอักษร

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

การใช้งาน:

ป้อนคำอธิบายรูปภาพที่นี่

ขออภัยไม่สามารถต้านทาน ...


Arghh! จริง ๆ แล้วฉันคิดว่าจะห้ามไม่ให้ทำเช่นนี้ แต่ลืมที่จะพูดถึงมันในโพสต์! : D ยังคงสูตร Excel ไม่ใช่ภาษาการเขียนโปรแกรม (และใช่ Excel VBA ก็ถูก จำกัด เช่นกัน) : P
Vilx-

@ Vilx- ขอบคุณพระเจ้าที่มีคนคิดวิธีแก้ปัญหาที่สั้นกว่า ฉันไม่ต้องการที่จะใส่ประวัติศาสตร์เป็นเพียงคนเดียวที่ได้รับรางวัลการประกวดกอล์ฟโดยใช้สูตร Excel :)
ดร. เบลิซาเรี

ฉันยังอาจยอมรับคำตอบของคุณ >: D
Vilx-

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

4
คุณสามารถวาง 2 ไบต์โดยแทนที่"1"ด้วย1
Taylor Scott

9

Perl, 17 ตัวอักษร

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

..ผู้ประกอบการจะเป็นสิ่งเดียวกับที่มีมนต์ขลังเพิ่มโดยอัตโนมัติ แต่ไม่มีความจำเป็นสำหรับตัวแปรชั่วคราวและห่วง นอกจากstrict subsอยู่ในขอบเขต barewords AและXFDถูกตีความว่าเป็นสตริง

( คำตอบนี้ถูกแนะนำโดยผู้ใช้ที่ไม่ระบุชื่อเพื่อแก้ไขคำตอบที่มีอยู่ฉันรู้สึกว่ามันสมควรที่จะเป็นคำตอบที่แยกจากกันและทำให้เป็นคำตอบเดียวเนื่องจากมันไม่ยุติธรรมสำหรับฉันที่จะได้รับตัวแทนจากฉัน ทำให้มันเป็นชุมชน Wiki )


เนื่องจากเป็นคำตอบที่สั้นที่สุดดังนั้นฉันจึงสมควรที่จะทำเครื่องหมายว่า "ยอมรับ" จนกว่าจะพบโซลูชันที่สั้นกว่า (อาจมีเฉพาะใน JonSkeetScript): P Ironic
Vilx-

1
เนื่องจากคำถามที่คลุมเครือเกี่ยวกับวิธีการป้อนข้อมูลและเอาท์พุทจะช่วยให้สั้นลงมาก ตัวอย่างเช่นถ้าอินพุตอยู่$_และเอาต์พุตเป็นค่าของนิพจน์จากนั้น(A..XFD)[$_]แก้ไขความท้าทายด้วย12 ตัวอักษรเท่านั้น
Ilmari Karonen

ขออภัยวิธีนี้จะทำงานได้อย่างไร ด้วย perl 5.18 มันจะพิมพ์อะไรเมื่อได้รับเป็นอาร์กิวเมนต์ไปที่ -E
Ed Avis

@EdAvis: รอให้คุณพิมพ์ตัวเลข perl -E 'say[A..XFD]->[<>]' < number.txtหรือคุณอาจจะใส่หมายเลขในแฟ้มและทำ perl -E 'say[A..XFD]->[<>]' <<< 123หรือในเปลือกหอยที่สนับสนุนมันเพียงแค่ให้ข้อมูลเกี่ยวกับบรรทัดคำสั่งด้วย
Ilmari Karonen

1
ฉันคิดว่าสิ่งนี้สามารถปรับให้เหมาะกับsay+(A..XFD)[<>]
Konrad Borowski

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

Haskell, 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, การกระทำจะได้รับการปฏิบัติเช่นค่านิยมและได้รับการติดกาวเข้าด้วยกันโดยใช้>>=(ผูก) และreturnวิทยาการ ประเภทใดก็ได้อาจเป็น "การกระทำ" หากใช้ตัวดำเนินการเหล่านี้โดยมีอินสแตนซ์Monad

บังเอิญประเภทรายการมีอินสแตนซ์ 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เป็น=<<ฟังก์ชั่นสำหรับรายการดังนั้นรายการ monad ให้ฉันโกนตัวละครไม่กี่ตัวที่นี่เช่นกัน



3

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

Python 45 51

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

คุณสามารถลบ 2 วงเล็บโดยการดึง+chr(65+i%26)ภายในและการทดสอบเพื่อให้i>=0คุณประหยัด 1 ตัวอักษร :)
Quasimodo

คุณสามารถโกนหนวดได้ 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กรณี
Peter Taylor

2

Excel VBA ขนาด 31 ไบต์

ฟังก์ชันหน้าต่าง VBE แบบไม่ระบุชื่อทันทีที่รับอินพุตจากเซลล์[A1]และเอาต์พุตไปยังหน้าต่างทันที VBE

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

2

JavaScript (Node.js) , 50 ไบต์

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

ลองออนไลน์!

เมื่อเห็นว่ามีผู้คนมากมายเริ่มตอบคำถามนี้ฉันก็ตอบด้วย

บันทึก :

นี่เป็นพื้นฐานของคำตอบของ @kevinCruijssen ใน Java ที่สั้นลงเนื่องจาก JS นี้


2

PHP, 30 ไบต์

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

ทำงานเป็นท่อด้วย `-nr' หรือลองออนไลน์


ฉันค่อนข้างแน่ใจว่านี่ไม่ได้ทำสิ่งที่ต้องการ หลังจากที่Zมันจะไปมากกว่า[ AA
Vilx-

@ Vilx- ฉันถือเป็นข้อพิสูจน์ว่าคุณไม่รู้ PHP มาก ฉันเพิ่ม TiO ดูด้วยตัวคุณเอง
ติตัส

ศักดิ์สิทธิ์ ... คุณพูดถูก! ฉันรู้ PHP ค่อนข้างดี แต่มันเต็มไปด้วยสิ่งแปลก ๆ ที่เป็นไปไม่ได้ที่จะรู้ทั้งหมด ความแปลกประหลาดนี้ทำให้ฉันออก ที่นี่มี upvote และคำขอโทษของฉัน!
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)
Taylor Scott

1
@TaylorScott คุณพูดถูก ทำงานกับมัน ...
LS_ᴅᴇᴠ

1
@TaylorScott แก้ไขแล้ว +6 ไบต์ ... ขอบคุณ
LS_ᴅᴇᴠ

1

Javascript, 147 ไบต์

ฉันมีปัญหาที่คล้ายกัน นี่คือสนามกอล์ฟของการแก้ปัญหา คอลัมน์ Excel เป็นฐาน-26 bijective

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 ปีที่แล้วไม่ใช่ความคิดที่ดีจริงๆ
มูฮัมหมัดซัลมาน

โอเค nvm นี้ผิดในหลาย ๆ ระดับฉันไม่เคยเห็นสิ่งนี้
Muhammad Salman

ฉันต้องการถามคำถามนี้ แต่มันซ้ำซ้อน ฉันไม่แน่ใจว่าสิ่งที่คุณจะได้รับที่ @MuhammadSalman
MattH

ฉันจะติดต่อกลับภายในไม่กี่นาทีอย่างไรก็ตามยินดีต้อนรับสู่ PPCG คำตอบที่ดี โปรดทราบว่าเมื่อเขียนคำตอบคุณจะต้องจัดให้มีโปรแกรมหรือฟังก์ชั่นเต็มรูปแบบ
Muhammad Salman

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 ไม่มีปัญหา ที่จริงผมมีของฉันจากคำตอบที่สกาล่า ;)
Kevin Cruijssen

1

Forth (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

Haskell, 48

ฉันคิดว่าฉันจะสามารถเอาชนะรายการ Haskell อื่น ๆ ได้ แต่ ...

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

ฉันแน่ใจว่าเป็นไปได้ที่จะโกนตัวละครออกมาสองสามตัว แต่ฉันไม่ได้เข้ารหัสใน Haskell มาเกือบปีแล้วดังนั้นฉันจึงค่อนข้างเป็นสนิม

ไม่ใช่สิ่งที่คุณจะเรียกว่าหรูหรา


ไม่เลว! :) แต่ Ha - หลังจากผ่านไป 3 ปีก็ยังไม่มีทางออก C # : D
Vilx-

ฮ่าฮ่าแน่นอน แต่การแก้ปัญหา C # เป็นเรื่องเล็กน้อยที่จะเขียนโดยใช้วิธีการเดียวกันนี้ string f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}57 ตัวอักษรดังนั้นฉันเกือบจะรู้สึกไม่ดีโดยโพสต์มันเป็นคำตอบ
Fors

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

ลองออนไลน์!



โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.