Algorithmus gesucht



  • Hallo Leute,

    ich suche einen ganz bestimmten Algorithmus, der mir nicht einfällt. 😕
    Ich habe mir schon den Kopf zerbrochen 😉

    Also er sollte das können:

    Wir haben die Buchstaben A - Z, er soll nun ausgeben:

    erst a, b, c, ... , z
    dann aa, ab, ac, ... ,az
    danach ba,bb, bc, ... , ... , ... ca, cb, ... ,... ,...........
    ...
    ...
    dann irgendwann aaa, aab,
    ...

    also letztlich um eine Art Excel - Spalte zu füllen, dort sin die ja auch so numeriert (bzw. buchstabiert 😉 )

    Könnt ihr mir da helfen??
    Ich habe grade ein BlackOut 😃

    DANKESCHÖN!!

    Player894


  • Mod

    Nummerieren ist schon das Stichwort. Du zählst einfach hoch. Bloß sind deine Ziffern nicht '0' bis '9', sondern 'a' bis 'z'. Das Prinzip bleibt aber das gleiche wie beim dezimalen Ziffernsystem. Wenn eine Ziffer überläuft, dann wird die Ziffer daneben um eines erhöht (und eventuell überhaupt erst eine Ziffer hinzugefügt, falls noch keine vorhanden ist).

    P.S.: Falls du dich nicht darauf verlassen möchtest, dass 'a' + 1 == 'b', usw. (z.B. EBCDIC-Codierung), dann ist vielleicht auch ein Array

    char ziffern[27]="abcdefghijklmnopqrstuvxyz";
    

    ganz hilfreich.
    Dieser Tipp ist für C, falls du in einer anderen Sprache programmierst, ist dieser Tipp natürlich eventuell anzupassen.
    Ich würde mich jedoch erst einmal auf ASCII verlassen. Es kann aber sehr hilfreich sein, falls später einmal der Ziffernraum vergrößert/geändert werden soll/könnte, dann ist man schon auf diesen Fall vorbereitet.



  • Ich hatte jetzt in C++ / CLI erst einmal gearbeitet und dort einen Dictionary - Container hinzugefügt:

    Dictionary<int, String^>^Daten = gcnew Dictionary<int, String^>();
    
    Daten->Add(0, "A");
    Daten->Add(1, "B");
    //...
    

    Ich habe das Prinzip verstanden, danke!
    Allerdings wüsste ich nicht genau, wie ich es im Quellcode umsetzen sollte...
    Ich habs schon probiert, hat nicht ganz geklappt 😉

    Kannst mir bitte jemand grob ein CodeBeispiel machen??

    Danke!!



  • Wie wärs mal erst mit selber nachdenken? Stift raus und ausprobieren, dann coden... Bei Problemen wird gefragt, nicht aus Faulheit!


  • Mod

    Ich kann kein C++/CLI, aber mal eben auf die Schnelle in C++ hin geschmiert:

    #include <string>
    
    class Counter
    {
      char max_digit;
      std::string alphabet;
      std::string current_number;
    public:
      Counter(char num_digits, std::string const& alphabet) : 
        max_digit(num_digits - 1), alphabet(alphabet), current_number(1, 0) { }
      std::string get_next_number()
      {
        std::size_t size = current_number.size();
        std::string result(size, ' ');
        for (std::size_t pos = 0; pos != size; ++pos)
          result[size - 1 - pos] = alphabet[current_number[pos]];    
    
        for (std::size_t pos = 0;;++pos)
          {
            if (pos == size)
              {
                current_number.push_back(1);
                break;
              }
            if (current_number[pos] == max_digit)
              {
                current_number[pos] = 0;
              }
            else
              {
                ++current_number[pos];
                break;
              }
          }
    
        return result;
      }
    };
    
    #include <iostream>
    int main()
    {
      Counter counter(16, "0123456789ABCDEF");
      for (int i = 0; i < 1024; ++i)
        std::cout << counter.get_next_number() << '\n';
    }
    

    http://ideone.com/WdOTtL



  • SeppJ: Warum so kompliziert? Mit dem üblichen Modulo-Divisionsalgo zum Umrechnen von Zahlensystemen wirds nur halb so viel Code. Außerdem sollte die Alphabetgröße nicht manuell übergeben, sondern von der Klasse selbst berechnet werden, um Benutzungsfehler zu vermeiden.


  • Mod

    Weil es tatsächlich nur schnell hin geschmiert war. So ist es natürlich schon wesentlich besser:

    class Counter
    {
      std::string alphabet;
      char max_digit;
      unsigned long current_number;
    public:
      Counter(std::string const& alphabet) : 
        alphabet(alphabet), max_digit(alphabet.size()), current_number(0) { }
      std::string get_next_number()
      {
        std::string result;
        unsigned long number = current_number;
        do
          {
            result.insert(0, 1, alphabet[number % max_digit]);
            number /= max_digit;
          }
        while (number);
    
        ++current_number;
        return result;
      }
    };
    


  • Ein Problem ist die "fehlende Null" bei Excel und Co..
    Loese ich hier z.B. durch eine bedingte Subtraktion (auch C++):

    class excel_col{
      const static char alphabet[];
      std::string buf;
    public:
      excel_col(int i){
        for(bool been_here_before=false;;been_here_before=true){
          const int rem = been_here_before && i<25 ? i%26-1 : i%26;
          buf+=alphabet[rem];
          i = (i-rem) / 26;
          if(i==0)
            break;
        }
        std::reverse(buf.begin(), buf.end());
      }
    
      const std::string& to_string() const { return buf; }
    };
    
    const char excel_col::alphabet[] = "abcdefghijklmnopqrstuvwxyz";
    

  • Mod

    Kann man das Problem mit der Null in Excel nicht so lösen wie bei meinem (zweiten) C++-Code? do...while ist schließlich keine Raketenwissenschaft.



  • SeppJ schrieb:

    Kann man das Problem mit der Null in Excel nicht so lösen wie bei meinem (zweiten) C++-Code? do...while ist schließlich keine Raketenwissenschaft.

    Ich meinte dass das Zahlensystem z.B. an der Stelle 26 nicht "ba" (analog zu "10" im dezimalen), sondern "aa" zählt.

    Aber ein Fehler steckte trotzdem drin:

    class excel_col{
      const static char alphabet[];
      std::string buf;
    public:
      explicit excel_col(long i){
        if(i<0L)
          return;
        for(bool been_here_before=false;;been_here_before=true){
          const long rem = been_here_before ? i%26-1 : i%26;
          buf+=alphabet[rem];
          i = (i-rem) / 26;
          if(i==0)
            break;
        }
        std::reverse(buf.begin(), buf.end());
      }
    
      const std::string& to_string() const { return buf; }
    };
    
    const char excel_col::alphabet[] = "abcdefghijklmnopqrstuvwxyz";
    

  • Mod

    Hehe, gar nicht dran gedacht 🙂 . Da ist dann wieder mein allererster Schnellversuch gut für. Da geht das ganz einfach ohne Verrenkungen.



  • ja, ich hab grad iwie ein Brett vorm kopf...

    also ich hab die beispiele nicht ganz verstanden, allerdings mal ausprobiert, und keines funktionierte richtig:

    meist begannen die Ausgaben mit "CF5" warum auch immer.

    Kann mir jemand bitte einfach genau erklären, wie er das machen würde?

    also meine idee war:

    using namespace System::Collections;
    using namespace System::Collections::Generic;
    
    array<System::String^> ^Alphabet = gcnew array<System::String>(25);
    Alphabet[0] = "a";
    Alphabet[1] = "b";
    // und so weiter...
    
       array<System::String^> ^Daten;
       Daten = gcnew array<System::String^>(99); //Hundert-stelliges array
    
    for (int counter = 0; ; counter++)
    {
       // allerdings habe ich keine ahnung, was jetzt hier rein muss!!
    }
    
    void Ausgabe(void) // gibt alle möglichen Zeichenzusammenstellungen bis zu 100 an - hoffentlich  :) 
    {
       for (int m = 0; ; m++)
       {
          Console::WriteLine(Ausgabe[m]);
       }
       Console::ReadLine();
    }
    

    Ich komme mir ziemlich blöd vor, aber kann mir nochmal jemand helfen 😉 ?

    Dankeschön!!



  • Player894 schrieb:

    also ich hab die beispiele nicht ganz verstanden, allerdings mal ausprobiert, und keines funktionierte richtig:

    meist begannen die Ausgaben mit "CF5" warum auch immer.

    Kann mir jemand bitte einfach genau erklären, wie er das machen würde?

    Habe mich noch ein wenig damit beschäftigt, da mir auch aufgefallen ist, dass ich da Mist gebaut habe.
    In der englischsprachigen Wikipedia habe ich aufgrund dieser Diskussion eine Variante hiervon eingetragen:

    #include <algorithm> // reverse
    #include <iostream>
    #include <string>
    
    std::string hexavigesimal(int i){
      std::string builder;
      while(0<i){
        --i;
        builder += "abcdefghijklmnopqrstuvwxyz"[i%26];
        i/=26;
      }
      std::reverse(begin(builder), end(builder));
      return builder;
    }
    
    int main(){
        std::cout << hexavigesimal(81202789) << ' ' << hexavigesimal(283186181) << '\n';
    }
    

    Das ist jetzt wirklich mit "fehlender 0", also A=1, B=2, ..., Z=26, AA=27...



  • Vielen Dank, Furble Wurble!

    Es funktioniert!

    Mfg

    Player894



  • @furble wurble

    wie wäre es denn damit möglich Sonderzeichen wie zb ß oder € zu schreiben?

    man könnte es ja als Unicode wert zuweisen:

    std::string abc = 0040;
    //...
    

    das geht wohl im Array, doch nicht in deinem Beispiel, hast du da eine Idee?

    dankeschön!


Anmelden zum Antworten