Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mär 28, 2024 12:28

Foren-Übersicht » Programmierung » Design Challenges
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Spaltennamen wie in Excel
BeitragVerfasst: Mi Feb 08, 2012 02:04 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1944
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
Habe einen Vorschlag:

Schreibe eine Methode, die Spaltennamen (wie aus Excel, Calc, Numbers, etc. bekannt) zurückliefert. Also:

A, B, C, D, ..., Z, AA, AB, AC, AD, AE, ..., AZ, BA, BB, BC, ...

Die Methode nimmt einen Int, der die Spaltennummer darstellt. Wobei 0 = A, 1 = B, 2 = C, usw. und liefert den entsprechenden Spaltennamen als String zurück.

Mfg
~ Frase

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Design Challenge Vorschläge
BeitragVerfasst: Mi Feb 08, 2012 12:20 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Frase hat geschrieben:
Schreibe eine Methode, die Spaltennamen (wie aus Excel, Calc, Numbers, etc. bekannt) zurückliefert.

Ist das nicht etwas zu simpel?

Code:
  1. QString getColumnName(int index)
  2. {
  3.     QString result;
  4.     while (index >= 0) {
  5.         int c = (index % 26);
  6.         index = index / 26 - 1;
  7.  
  8.         result.insert(0, (char)(65 + c));
  9.     }
  10.     return result;
  11. }


Aya


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Spaltennamen wie in Excel
BeitragVerfasst: Mi Feb 08, 2012 13:45 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Rekursiv:
Code:
  1. ORD_A = ord("A")
  2. def colname_rec(i):
  3.     (d,m) = divmod(i, 26)
  4.     return (colname_rec(d-1) if d > 0 else "") + chr(m+ORD_A)


Iterativ:
Code:
  1. def colname_it(i):
  2.     d = i+1
  3.     s = ""
  4.     while d > 0:
  5.         (d,m) = divmod(d-1, 26)
  6.         s = chr(m+ORD_A) + s
  7.     return s


Als (effizienter) Generator:
Code:
  1. def colname_gen(start=0,count=None):
  2.     def inc(col):
  3.         for idx, ch in enumerate(col):
  4.             col[idx] = ch + 1
  5.             if ch < 25:
  6.                 return
  7.             else:
  8.                 col[idx] = 0
  9.         # if we end up here, we need to insert a new designator
  10.         col.append(0)
  11.    
  12.     col = list((ord(ch)-ORD_A for ch in colname(start)))
  13.     col.reverse()
  14.     if count is not None:
  15.         for i in range(start, start+(count-1)):
  16.             yield "".join((chr(ch+ORD_A) for ch in reversed(col)))
  17.             inc(col)
  18.         yield "".join((chr(ch+ORD_A) for ch in reversed(col)))
  19.     else:
  20.         while True:
  21.             yield "".join((chr(ch+ORD_A) for ch in reversed(col)))
  22.             inc(col)


Anwendung:
Code:
  1. Python 3.2.1 (default, Jul 11 2011, 18:54:42)
  2. [GCC 4.6.1 20110627 (Red Hat 4.6.1-1)] on linux2
  3. Type "help", "copyright", "credits" or "license" for more information.
  4. >>> from cols import *
  5. >>> colname_rek(0)
  6. 'A'
  7. >>> colname_rek(25)
  8. 'Z'
  9. >>> colname_rek(26)
  10. 'AA'
  11. >>> colname_it(0)
  12. 'A'
  13. >>> colname_it(25)
  14. 'Z'
  15. >>> colname_it(26)
  16. 'AA'
  17. >>> list(colname_gen(25, 10))
  18. ['Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI']
  19. >>> list(colname_gen(50, 10))
  20. ['AY', 'AZ', 'BA', 'BB', 'BC', 'BD', 'BE', 'BF', 'BG', 'BH']
  21. >>> list(colname_gen(700, 10))
  22. ['ZY', 'ZZ', 'AAA', 'AAB', 'AAC', 'AAD', 'AAE', 'AAF', 'AAG', 'AAH']


//edit: Generator-Code korrigiert
Wer sich übrigens fragt, wofür man einen unendlichen Generator braucht, dem sei der Ausdruck:
Code:
  1. cells = [["row {0}, col {1}".format(y, x) for y in range(10)] for x in range(10)]
  2. table = list(zip(*zip(colname_gen(), *zip(*cells))))
  3. for row in table:
  4.   print(" ".join("{0:15s}".format(col) for col in row))

ans Herz gelegt ;). Anstatt der List Comprehension für cells kann man auch wunderbar eine bestehendes 2D-Array mit erstem Index ≙ Spalte und zweitem Index ≙ Zeile nehmen. Wenn das Array transponiert ist, lässt man einfach den *zip()-Aufruf um *cells herum weg (also *zip(*cells) => *cells). Dank des unendlichen Generators ist der Ausdruck unabhängig von den Dimensionen des Arrays.

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Spaltennamen wie in Excel
BeitragVerfasst: Mi Feb 08, 2012 19:40 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1944
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
Code:
  1. def colName(index: Int): String = index match {
  2.   case x if index < 26 => ('A' + x).toChar.toString
  3.   case _ => colName(index / 26 - 1) + colName(index % 26)
  4. }


Und in Verwendung:
Code:
  1. println((0 to 25).map(colName).mkString(", "))
  2. println((26 to 51).map(colName).mkString(", "))
  3. println((52 to 77).map(colName).mkString(", "))
  4. println((650 to 710).map(colName).mkString(", "))

liefert:
Code:
  1. A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
  2. AA, AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU, AV, AW, AX, AY, AZ
  3. BA, BB, BC, BD, BE, BF, BG, BH, BI, BJ, BK, BL, BM, BN, BO, BP, BQ, BR, BS, BT, BU, BV, BW, BX, BY, BZ
  4. YA, YB, YC, YD, YE, YF, YG, YH, YI, YJ, YK, YL, YM, YN, YO, YP, YQ, YR, YS, YT, YU, YV, YW, YX, YY, YZ, ZA, ZB, ZC, ZD, ZE, ZF, ZG, ZH, ZI, ZJ, ZK, ZL, ZM, ZN, ZO, ZP, ZQ, ZR, ZS, ZT, ZU, ZV, ZW, ZX, ZY, ZZ, AAA, AAB, AAC, AAD, AAE, AAF, AAG, AAH, AAI
  5.  


Featuring Pattern Matching und so.

@Horazont: Das Divmod sieht ja putzig aus :) Die Generatoren-Lösung ist alles andere als putzig. Die ist eher... strange. Klingt nach einem Konzept, was man sich mal zu Gemüte führen sollte.

@Aya: Yay, eine iterative C++ Lösung :) Muss man den QString nicht erst mit irgendwas initialisieren? Oder liegt der da jetzt schon so auf dem Stack herum? Der Aufruf an result.insert kommt mir etwas spanisch vor ansonsten.

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Spaltennamen wie in Excel
BeitragVerfasst: Mi Feb 08, 2012 20:29 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Frase hat geschrieben:
@Horazont: Das Divmod sieht ja putzig aus :) Die Generatoren-Lösung ist alles andere als putzig. Die ist eher... strange. Klingt nach einem Konzept, was man sich mal zu Gemüte führen sollte.

Nun, ein Generator ist nichts weiter als ein parametrisierter Iterator. Jedes yield gibt ein neues Element zurück (d.h. die Funktion wird dort bis zum nächsten aufruf von next() praktisch unterbrochen). Wenn nichts mehr rauskommt (return oder einfach ende der Funktion) wird implizit ne EndOfIteration Exception geworfen… Die Python-Schleifen wissen dann, das Schluss ist ;). Der Benutzer merkt davon nichts, wenn er nicht per Hand next() aufruft.

greetings

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Spaltennamen wie in Excel
BeitragVerfasst: Fr Feb 17, 2012 15:42 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
Zeit für ein bissl Shell :P
Code:
  1.  
  2. let rec xls index =
  3.     if(index >= 0) then (char (index % 26 + 65)).ToString() + xls(index/26-1)
  4.     else ""
  5.  
  6. printfn "Columns %A"(List.map xls [900 .. 970])
  7.  

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Spaltennamen wie in Excel
BeitragVerfasst: So Feb 19, 2012 15:41 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
Code:
  1. void GetColumnName(Int32 Index, String& Result)
  2. {
  3.     Int32 columnCount=0;
  4.     Int32 ind=Index;
  5.     while(ind>=0)
  6.     {
  7.         ind=ind/26-1;
  8.         ++columnCount;
  9.     }
  10.  
  11.     String result(columnCount);
  12.     char* ptr=const_cast<char*>(result.c_str());
  13.     for (Int32 i=columnCount-1;i>=0;--i)
  14.     {
  15.         ind=(Index%26);
  16.         Index=Index/26-1;
  17.         ptr[i]='A'+ind;
  18.     }
  19.     Result.Swap(result);
  20. }


Die Variante ist auf Performance ausgelegt, es wird zuerst die Anzahl der Spalten errechnet, um dann den benötigten Speicher zu allozieren und direkt auf einen Array zu arbeiten. Ich muss aus meiner Stringklasse den char* pointer ziehen, da der Array operator[] ein Funktionsaufruf ist und entsprechend overhead und unnötig mehr CPU aufwand produziert(im release build kann je nach compiler das natürlich inlined werden aber halt je nach compiler und nicht für alle).
Der erzeugte String wird dann mit dem übergebenen ausgetauscht(ist die Stringklasse aus Radon Framework, die arbeitet intern mit nen Array pointer).
Das Resultat wird als Referenz-Parameter zurück gegeben, damit nicht noch zwischenobjekte auf dem Stack erzeugt werden, wie bei der Funktionsrückgabe(C# z.B. würde Speicher für object erzeugen und dann den pointer hin und her kopieren aber bei C++ würde er die Klasse neu anlegen, copy constructor aufrufen und ne riesen sauerei produzieren).

CPU's sind immer schneller als der Speicher(je mobiler des so stärker der Unterschied) daher kann man unmengen an Berechnungen machen, bevor Speicherzugriffe günstiger sind und wenn man dann noch dynamische Speicheralloziierung im Code hat, dann sowieso.
Ich hab noch ein bisschen mit Caching experimentiert aber das macht hier kein Sinn, das es zu wenig Daten und zu einfache Berechnungen sind. Da reicht das CPU interne Caching und Predicted-Caching aus.

Ich hab beim experimentieren noch ein Bug in meiner Insert Methode, von der Stringklasse, gefunden und gefixt :)

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Foren-Übersicht » Programmierung » Design Challenges


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.047s | 17 Queries | GZIP : On ]