インデックスから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で何が得られますか?
ピーターテイラー

まあ、それはExcelが示すものであり、Web上で16384列があることがわかりました。明日、(動作することがわかっている)コードを使ってテストします(現在の夜遅くまでです)。
ヴィルクス

また、Excel自体でテストすると、676 = ZAおよび702 = AAAであることがわかります。
Vilx-

1
私が尋ねる理由は、私は、いくつかの簡単なベース-26コードを書いた正確にあなたに合うような結果を得たが、676と702で破ったということです
ピーター・テイラー

1
うん。Base-26ではありません。それが問題です。;)
Vilx-

回答:



20

Excelの数式:)、36文字

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

使用法:

ここに画像の説明を入力してください

申し訳ありませんが、抵抗できませんでした...


ああ!私は実際にこれを禁止することを考えていましたが、投稿でそれを言及するのを忘れました!:Dそれでも、Excelの数式はプログラミング言語ではありません(もちろん、Excel VBAも立ち入り禁止です)。:P
Vilx-

@ Vilx-ありがたいことに、誰かが短い解決策を思いついた。私は:) Excelの数式を使用したゴルフコンテストで優勝した唯一の人であることの歴史を入力する必要はありません
博士ベリサリウス

私はまだあなたの答えを受け入れるかもしれません。>:D
Vilx-

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

4
あなたは置き換えることによって、2つのバイトをドロップすることができ"1"1
テイラースコット

9

Perl、17文字

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

..オペレータは、魔法の自動インクリメントとしてではなく、一時的な変数やループを必要とせずに同じことを行います。strict subsスコープ内にない限り、ベアワードAXFDは文字列として解釈されます。

この回答は、既存の回答の編集として匿名ユーザーによって提案されたものです。別の回答に値すると感じ、それを作成しました。それから回答を得るのは公平ではないので、私はコミュニティWikiにしました。


これはこれまでの最短の回答なので、より短い解決策が見つかるまで(おそらくJonSkeetScriptでのみ利用可能):P Ironicと「受け入れられた」としてマークするに値すると思います。
Vilx-

1
質問は入力と出力がどのように行われるかについて曖昧なので、実際にはこれをかなり短縮することができます。たとえば、入力が入力され$_、出力が式の値である場合、(A..XFD)[$_]わずか12文字で課題を解決します。
イルマリカロネン

申し訳ありませんが、これはどのように実行すべきですか?perl 5.18では、-Eの引数として指定しても何も出力されません。
エドエイビス

@EdAvis:数字を入力するのを待っています。または、ファイルに番号を入れて実行することもできますperl -E 'say[A..XFD]->[<>]' < number.txt。または、それをサポートするシェルでは、単にコマンドラインで入力を与えperl -E 'say[A..XFD]->[<>]' <<< 123ます。
イルマリカロネン

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

ハスケル、48

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

少ないゴルフ:

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

説明

Haskellのsequenceコンビネータはアクションのリストを取得して実行し、リスト内の各アクションの結果を返します。例えば:

sequence [getChar, getChar, getChar]

以下と同等です:

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

Haskellでは、アクションは値のように扱われ、>>=(バインド)およびreturnプリミティブを使用して接着されます。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=<<関数なので、リストモナドではここでいくつかの文字を剃ることもできます。



3

ルビー、35文字

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

使用法:

puts e[16383]   # XFD

注:再帰を使用する短いバージョン(30文字)もあります。

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

ただし、この関数を使用すると、Rubyインタープリターによっては、大きな数値のスタックサイズを増やす必要がある場合があります。


3

グルーヴィー、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

パイソン45 51

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

+chr(65+i%26)内側に引っ張ってテストすることで2つの括弧を削除でき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

Scala、62文字

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

使用法:

println(f(16383))

戻り値:

XFD

Simply scalaでこれを試すことができます。関数をコピーして貼り付け、使用f(some integer)して結果を確認します。


あなたは必要としない""+elseケース。
ピーターテイラー

2

Excel VBA、31バイト

セルから入力を受け取り[A1]、VBEイミディエイトウィンドウに出力する匿名VBEイミディエイトウィンドウ関数

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


2

PHP、30バイト

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

`-nr 'でパイプとして実行するか、オンラインで試してください


これは必要なことをしないと確信しています。後Zでは[なく、行くだろうAA
Vilx-

@ Vilx-それは、あなたがPHPをあまり知らないという証拠として受け止めます。TiOを追加しました。自分で見て。
タイタス

神聖な…あなたは正しい!私はPHPをかなりよく知っていますが、それは奇妙なものでいっぱいなので、すべてを知ることは不可能です。この特定の奇妙さは私を追い払った。ここで、賛成票と私の謝罪があります!
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@@(予想YZs(677)=A@A(予想ZA
テイラー・スコット

1
@TaylorScottそのとおりです。...それに取り組んで
LS_ᴅᴇᴠ

1
@TaylorScott修正、+ 6バイト...ありがとう。
LS_ᴅᴇᴠ

1

Javascript、147バイト

同様の問題がありました。これが解決策のゴルフです。Excelの列は全単射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))}

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年前に尋ねられた質問に答えることは、本当に素晴らしいアイデアではありません。
ムハンマドサルマン

[OK]を、これは私が今までこの表示されませんでしたどのように多くのレベルで間違っているNVM
ムハンマドサルマン・

この質問をしたかったのですが、重複していました。私はあなたが@MuhammadSalmanで取得しているものではないよ
MattH

PPCGへようこそ。いい答えだ。Plzは、答えを書くときは、完全なプログラムまたは機能を提供する必要があることに注意してください
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、問題ありません。私は実際にScalaの回答から私のものを得ました。;)
ケビンクルーイッセン

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

ハスケル、48

私は他のHaskellエントリーを打ち負かすことができると本当に思っていましたが、

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

私はこれからいくつかの文字を剃ることが可能であると確信していますが、私はHaskellで1年近くコーディングしていないので、かなり錆びています。

それはあなたがエレガントと呼ぶものとは正確に異なります。


悪くない!:)しかし、ハ-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.