Dizinden excel sütun adı oluştur


21

Bu gerçek bir yaşam probleminden geliyor. Elbette çözdük, ama daha iyi yapılabileceğini, çok uzun ve dolambaçlı bir çözüm olduğunu hissetmeye devam ediyor. Ancak hiçbir meslektaşım bunu yazmanın daha özlü bir yolunu düşünemez. Bu yüzden kod-golf olarak sunuyorum.

Amaç, Excel'in sütun başlıklarını sunduğu gibi negatif olmayan bir tamsayıyı bir dizeye dönüştürmektir. Böylece:

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

En az 16.383'e kadar çalışması gerekir, ancak ötesi de kabul edilebilir (yine de bonus puanı yok). Ben en çok C # çözümü için sabırsızlanıyorum, ancak, kod golf geleneklerine göre, herhangi bir gerçek programlama dili açığız.


16383'ün XFD olması gerektiğinden emin misiniz? 676 ve 702 için ne elde edersiniz?
Peter Taylor

Excel'in gösterdiği şey budur ve web'de 16384 sütun bulunduğunu gördüm. Yarın (işe yaradığı bilinen) kodumuzla test edeceğim (şu an yaşadığım gece geç saatlerde).
Vilx

Ayrıca, Excel ile yapılan testler 676 = ZA ve 702 = AAA olduğunu ortaya koymaktadır.
Vilx

1
Sormamın nedeni, basit bir taban-26 kodu yazdım, tam olarak size uyan sonuçlar aldım, ancak 676 ve 702'de kırıldı.
Peter Taylor

1
Evet. Base-26 değil. İşte sorun bu. ;)
Vilx-

Yanıtlar:



20

Excel Formula :), 36 karakter

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

Kullanımı:

resim açıklamasını buraya girin

Üzgünüm, dayanamadım ...


Arghh! Aslında bunu yasaklamayı düşünmüştüm, ancak yazıdan bahsetmeyi unuttum! : D Yine de, Excel formülleri bir programlama dili değildir (ve evet, Excel VBA da sınırlar dışındadır). : P
Vilx-

@ Vilx- Şükürler olsun ki birisi daha kısa bir çözüm buldu. Excel formüllerini kullanarak bir golf yarışması kazanan tek kişi olarak tarihe girmek istemiyorum :)
Dr. belisarius

Hala cevabını kabul edebilirim. D
Vilx-

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

4
Sen değiştirerek 2 bayt bırakabilirsiniz "1"ile1
Taylor Scott

9

Perl, 17 karakter

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

..Operatör büyülü otomatik artış olarak aynı şeyi yapar, fakat geçici değişken ve döngü için gerek kalmadan. strict subsKapsamda olmadıkça , barewordlar Ave XFDdize olarak yorumlanır.

( Bu cevap, anonim bir kullanıcı tarafından mevcut bir cevaba düzenleme olarak önerildi . Ayrı bir cevap olmayı hak ettiğini hissettim ve bir cevap verdim. Bundan tekrar kazanmak benim için adil olmaz, ' Topluluk Wiki'sini oluşturduk. )


Şimdiye kadarki en kısa yanıt olduğundan, daha kısa bir çözüm bulunana kadar (muhtemelen yalnızca JonSkeetScript'te mevcuttur): "Kabul" olarak işaretlenmeyi hak ettiğini düşünüyorum.
Vilx-

1
Soru, girdi ve çıktının nasıl yapıldığı konusunda belirsiz olduğundan, bu aslında bunu önemli ölçüde kısaltmaya izin verir. Örneğin, girdi içeriyse $_ve çıktı ifadenin değeriyse (A..XFD)[$_], meydan okumayı yalnızca 12 karakterle çözer .
Ilmari Karonen

Pardon, bu nasıl yapılmalı? Perl 5.18 ile -E'ye argüman olarak verildiğinde hiçbir şey yazdırmaz.
Ed Avis

@EdAvis: Bir sayı yazmanızı bekliyor. Veya numarayı bir dosyaya koyabilir ve yapabilirsiniz perl -E 'say[A..XFD]->[<>]' < number.txt. Veya onu destekleyen kabuklarda, komut satırındaki girişi ile verin perl -E 'say[A..XFD]->[<>]' <<< 123.
Ilmari Karonen

1
Bence bu optimize edilebilirsay+(A..XFD)[<>]
Konrad Borowski

6

C, 53 karakter

Çekiçle golf oynamak gibi ...

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

Normal sürüm:

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

Ve kullanımı şöyle:

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

Daha az golf:

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

açıklama

Haskell'in sequencebirleştiricisi, eylemlerin bir listesini alır ve bunları gerçekleştirir ve listedeki her eylemin sonucunu döndürür. Örneğin:

sequence [getChar, getChar, getChar]

şuna eşittir:

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

Haskell'de eylemler değerler gibi ele alınır ve >>=(bind) ve returnilkeller kullanılarak birbirine yapıştırılır . Herhangi bir tür, bir Monad örneğine sahip olarak bu işleçleri uygularsa "eylem" olabilir .

Bu arada, liste türünün bir monad örneği vardır. Örneğin:

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

Bu eşittir [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]. Liste kavrayışının çarpıcı şekilde benzer olduğuna dikkat edin:

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

Listeler bir tür "eylem" olduğundan, sequencelistelerle birlikte kullanabiliriz . Yukarıdakiler şu şekilde ifade edilebilir:

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

Böylece, sequencebize ücretsiz kombinasyonlar verir!

Böylece, listeyi oluşturmak için:

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

Sadece geçmek için listeler yapmam lazım sequence

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

Ardından concatMap, hem sequencelistelere uygulamak hem de sonuçta oluşan listeleri birleştirmek için düğmelerini kullanın . Tesadüfen, concatMapbir =<<liste monad benim de burada birkaç karakter tıraş sağlar, böylece listeleri için fonksiyon.


5

Perl, 26 karakter

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

3

Ruby, 35 karakter

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

Kullanımı:

puts e[16383]   # XFD

Not: Özyineleme kullanan daha kısa bir sürüm (30 karakter) de vardır.

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

Ancak bu işlevi kullanarak, yakut yorumcunuza bağlı olarak büyük sayılar için yığın boyutunu artırmanız gerekebilir.


3

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

+chr(65+i%26)içeri çekerek ve test ederek 2 parantez kaldırabilirsiniz i>=0, size 1 karakter kazandırır :)
quasimodo

Ayrıca kullanarak kapalı 4 karakter tıraş olabilir f=lambda i:ziyadedef f(i):return
Strigoides

aslında 37 ve üzeri rakamlar için işe yaramıyor. Bu kodu biraz güncellemek zorunda kaldım: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

Kullanımı:

println(f(16383))

İadeler:

XFD

Bunu sadece scala'da deneyebilirsiniz . İşlevi kopyalayıp yapıştırın f(some integer)ve sonucu görmek için kullanın .


Buna gerek yok ""+üzerinde elsedurumda.
Peter Taylor

2

Excel VBA, 31 Bayt

Hücreden girdi alan [A1]ve VBE anında penceresine çıkış sağlayan anonim VBE anında pencere işlevi

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

2

JavaScript (Node.js) , 50 bayt

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

Çevrimiçi deneyin!

Birçok insanın buna cevap vermeye başladığını görünce ben de cevapladım.

Not :

Bu temelde @ kevinCruijssen'in Java'daki cevabının JS olması nedeniyle kısaldığı bir kopuş.


2

PHP, 30 bayt

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

-Nr ile pipo olarak çalıştırın veya çevrimiçi deneyin .


Bunun gerekli olanı yapmadığından eminim. Sonra Zgitmek [yerine AA.
Vilx-

@ Vilx- Bunu çok fazla PHP bilmediğinizin kanıtı olarak görüyorum. Bir TiO ekledim; kendin için gör.
Titus

Holy ... haklısın! PHP'yi oldukça iyi tanıyorum, ama o kadar tuhaf şeylerle dolu ki, hepsini bilmek imkansız. Bu tuhaflık beni attı. Burada bir oylama ve özür dilerim!
Vilx-

1

VBA / VB6 / VBScript (Excel dışı), 73 bayt

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

Arama s(16383)geri dönecek XFC.


PPCG'ye Hoşgeldiniz! VB'ye aşina olmayan kullanıcılar için bir açıklama ekleyebilir misiniz?
AdmBorkBork

1
@AdmBorkBork Önceki yanıtlara eklenecek fazla bir şey yok, sadece dil bağlama!
LS_ᴅᴇᴠ

Bu, i>675 - s(676)=A@@(beklenen YZ), s(677)=A@A(beklenen ZA)
Taylor Scott'un

1
@TaylorScott Haklısın. Üzerinde çalışıyor ...
LS_ᴅᴇᴠ

1
@TaylorScott Düzeltildi, +6 bayt ... Teşekkürler.
LS_ᴅᴇᴠ

1

Javascript, 147 bayt

Benzer bir sorun yaşadım. Bu çözümün golfü. Excel sütunları iki yönlü taban-26'dır .

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 endeks kullanmak dışında genişletilmiş:

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
Bir TIO bağlantısı ekleyebilirsiniz. Bunun dışında harika bir ilk cevap. Ayrıca PPCG'ye hoş geldiniz.
Muhammed Salman

Ayrıca 7 yıl önce sorulan bir soruyu cevaplamak gerçekten harika bir fikir değil.
Muhammed Salman

Tamam, nvm bu pek çok seviyede yanlış, bunu nasıl görmedim
Muhammed Salman

Bu soruyu sormak istedim ama bu bir kopyaydı. @MuhammadSalman
MattH'de

Bir dakika içinde size geri döneceğim, Neyse PPCG'ye hoş geldiniz. güzel cevap. Plz, bir cevap yazarken tam bir program veya işlev sağlamanız gerektiğini unutmayın
Muhammad Salman

1

Java, 57 bayt (özyinelemeli)

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

Çevrimiçi deneyin.

Açıklama:

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 bayt (yinelemeli)

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

Çevrimiçi deneyin.

Açıklama:

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

Merhaba. Üzgünüm ama kodunu çaldım: İşte . :)
Salman Salman

@MuhammadSalman Hehe, sorun değil. Aslında Scala cevabından benimkini aldım . ;)
Kevin Cruijssen

1

İleri (gforth) , 59 bayt

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

Çevrimiçi deneyin!

açıklama

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 bayt

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

Alternatif özyinelemeli sürüm, 68 bayt:

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

Test komut dosyası:

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

Çıktı:

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

Not: Powershell bir divoperatör sağlamaz .


0

Haskell, 48

Gerçekten diğer Haskell girişini yenebileceğini düşündüm, ama ne yazık ki ...

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

Bundan birkaç karakteri traş etmenin mümkün olduğundan eminim, ancak Haskell'de yaklaşık bir yıldır kod yazmadım, bu yüzden oldukça paslıyım.

Tam olarak zarif dediğin şey değil.


Fena değil! :) Ama Ha - 3 yıldan fazla sonra, hala C # çözümü yok. : D
Vilx-

Haha, gerçekten. Ancak bir C # çözümü, aynı yöntemi kullanarak yazmak önemsizdir. string f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}57 karakter, bu yüzden cevap olarak göndererek neredeyse kendimi kötü hissederdim.
Fors

0

Jq 1,5 , 71 bayt

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

Giriş bekleniyor N. Örneğin

def N:16383;

Expanded:

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

Çevrimiçi deneyin!



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.