1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Yjuq

Beiträge von Yjuq

  • primzahlenrechner

    • Yjuq
    • 12. April 2015 um 19:08

    Bevor ich es vergesse, hier mal eine andere Version des Algo in Beitrag #18.
    Könnt ihr mal eure Ergebnisse posten? Bei mir braucht das mit den String Funktionen etwas unter einer Sekunde. ^^

    Spoiler anzeigen
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $hTime = TimerInit()
    Global Const $aPrimes = SieveOfEratosthenes(1000000)
    ConsoleWrite(Round(TimerDiff($hTime) / 1000, 3) & ' Sekunden' & @CRLF)
    _ArrayDisplay($aPrimes)

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Func SieveOfEratosthenes($limit)
    Local $sievebound = ($limit -1) / 2
    Local $sieve[$sievebound +1]
    Local $crosslimit = (Sqrt($limit) -1) / 2
    Local $primes = '2|'
    Local $i, $j

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To $crosslimit
    If Not $sieve[$i] Then
    For $j = 2 * $i * ($i +1) To $sievebound Step 2 * $i +1
    $sieve[$j] = True
    Next
    EndIf
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To $sievebound
    If Not $sieve[$i] Then $primes &= 2 * $i +1 & '|'
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return StringSplit(StringTrimRight($primes, 1), '|', 2)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]
  • primzahlenrechner

    • Yjuq
    • 12. April 2015 um 18:54

    Hey ProgrammingDonkey! :)
    Ich bin zu faul um mich hinter deinen Gedanken zu deinem Skript einzulesen, das eine oder andere Kommentar hätte sicherlich geholfen. Was mir jedoch konkret ins Auge springt ist das _ArrayDelete(). Bei jedem Aufruf wird das Array neu dimensioniert, das kostet viel Zeit. Um Optimierungen vorzunehmen muss man erst einmal genau wissen was man möchte. Bei dieser Primzahlen-Geschichte kann man bereits mathematische Gesetze ausnutzen. So wie ich das sehe tust du das nur bedingt, da kann man tatsächlich viel mehr rausholen als wie es den Anschein hat. Du hattest mich um eine Erklärung zu meinen Skript gebeten, um das allerdings zu verstehen muss der Gedanke dahinter verstanden werden. Ich versuche es mal zu erklären, eine Optimierung deines Codes kannst du anhand des gewonnenen Wissens dann selber vornehmen.

    Mein Algorithmus tut eigentlich nur folgendes:
    1. Es wird eine Liste angelegt von 2 bis N Elementen (in Form eines 1D Arrays)
    2. Es wird die kleinste Zahl aus der Liste gesucht welche noch nicht „durchgestrichen“ ist, dies muss eine Primzahl sein.
    3. Alle Vielfachen der Gefunden Zahl werden „durchgestrichen“.
    4. Gehe wieder zu Schritt 2 und wiederhole die Schritte bis das Ende der Liste erreicht wurde.
    5. Alle nicht durchgestrichenen Zahlen sind Primzahlen.

    Anders gesagt arbeitet dieser nach dem Sieb des Eratosthenes. Eine einfache Implementierung würde folgendermaßen aussehen:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Dim $limit = 100
    Dim $crosslimit = Sqrt($limit) ; Erklärung folgt...
    Dim $sieve[$limit +1] = [True, True] ; 0 und 1 sind keine Primzahlen

    [/autoit] [autoit][/autoit] [autoit]

    ; Alle geraden Zahlen werden "durchgestrichen", sind ja Vielfachen von 2.
    For $n = 4 To $limit Step 2
    $sieve[$n] = True
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ; Wir können in Zweierschritten vorgehen, da alle geraden Zahlen keine Primzahlen sein können.
    For $n = 3 To $crosslimit Step 2
    If Not $sieve[$n] Then ; Wenn die Zahl noch nicht durchgestrichen wurde...

    [/autoit] [autoit][/autoit] [autoit]

    ; Auch hier folgt noch eine Erklärung...
    For $m = $n ^ 2 To $limit Step 2 * $n
    $sieve[$m] = True
    Next
    EndIf
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ; Alle durchgestrichenen Zahlen sind mit "True" markiert, alle anderen sind demnach Primzahlen.
    _ArrayDisplay($sieve)

    [/autoit]

    Wenn wir uns mal Zeile 4 anschauen, so sehen wir folgende Rechnung:Sqrt($limit). Es ist so, dass nur alle Zahlen bis zu der Quadratwurzel der Endzahl abgeklappert werden müssen. Bei 100 Primzahlen müssen also nur alle Vielfachen von 2 bis 10 tatsächlich durchgestrichen werden. Alle anderen Zahlen zu überprüfen und deren Vielfache durchzustreichen wäre lediglich nur Zeitverschwendung. Dies liegt daran dass wir jede Zahl in ihre Primfaktoren zerlegen können. Das bedeutet, dass die Zahl eine Vielfache des Primfaktor ist. Und maximal 1 Primfaktor (und das muss nicht mal unbedingt so sein) kann größer sein als die Quadratwurzel jener Zahl. Alle anderen Primfaktoren liegen damit unter der Quadratwurzel. Ein Beispiel wird dies nochmal verdeutlichen:

    Nehmen wir an wir wollen alle Primzahlen bis 1000 ermitteln. Die Quadratwurzel dieser Zahl ist 31,62. Wenn wir die Zahl 1000 in ihre Primfaktoren zerlegen erhalten wir die Faktoren 2^3 * 2^5. Das bedeutet dass 1000 die Vielfache von 2 und 5 ist. Nun zerlegen wir die 999: 3^3 * 37 Wir sehen dass ein Faktor über der Quadratwurzel von 31,62 liegt. Ist aber soweit nicht tragisch da der Faktor 3 noch darunter liegt. Streichen wir also alle Vielfachen von 3 weg, so ist auch die 999 durchgestrichen. Dies kann man jetzt für jede Zahl fortführen, das System geht auf. Deshalb brauchen wir nur alle Zahlen von 2 bis Sqrt(n) durchlaufen da sowieso alle Vielfachen weggestrichen werden. Ich hoffe es ist so verständlich.

    Schauen wir uns jetzt noch Zeile 17 an: For $m = $n ^ 2 To $limit Step 2 * $n
    Wir starten bei $n ^ 2. Warum ist das allerdings so? Potenzieren wir unsere Startzahl (meinetwegen die 3) so stellen wir fest dass die 6 dabei übersprungen wird. Durch das Step 2 * $n werden auch die 12, 18 und 24 übersprungen. Bei der 5 wären dies die Zahlen 10, 15, 20, 30, 40 usw. Wir sehen also, dass (beinahe) nur gerade Zahlen übersprungen werden, die Schleifendurchläufe werden weniger und so brauchen wir weniger Zeit. Was ist aber nun mit der 15? Nun ja, die 15 wird durch die 3 (da diese dort nicht übersprungen wird) durchgestrichen, dies verhält sich bei allen Zahlen so. Die kleineren Zahlen streichen jene Zahlen durch, welche die größeren überspringen. Zeit wird so aber definitiv eingespart.

    Nun ist der Algorithmus aber noch nicht perfekt da es noch sehr lange dauert bis alle Primzahlen ermittelt wurden. Bei 1'000'000 als Limit braucht dieses Verfahren ca. 9 Sekunden bei mir. Da geht aber noch mehr.

    Eine weitere Erklärung zu dem Rest folgt noch ^^
    Gerade keine Lust mehr zu tippen :D

  • hallo von MX3ver

    • Yjuq
    • 12. April 2015 um 01:01

    Willkommen! :)
    Da wünsche ich dir viel Glück bei deinem Projekt, hatte mich da auch mal dran versucht.
    Ist aber gar nicht so einfach, vielleicht bin ich es damals auch nur falsch angegangen.
    Hier der Thread dazu: BlueStacks Mauseingabe per Tastatur

    Vielleicht hilft dir dieser irgendwann mal weiter ^^

  • Forum Problemsammlung

    • Yjuq
    • 9. April 2015 um 01:15

    Zu Beitrag #31:
    Hatte mal meine ganzen User Daten gelöscht: C:\Users\Cederik\AppData\Local\Google\Chrome
    Jetzt funktioniert unter Chrome wieder alles, anscheinend hatte ich da irgend ein Extension was die Website hier blockiert.
    Hat sich irgendwie eingeschlichen, keine Ahnung wie ^^

    Falls jemand ähnliche Probleme mit Chrome haben sollte, einfach den Ordner löschen.
    Sofern ihr euch registriert habt werden sämtliche Lesezeichen (welche mit euren Account verknüpft sind) wieder hergestellt.

  • Forum Problemsammlung

    • Yjuq
    • 5. April 2015 um 20:21

    Noch ein Problem was ich gerade feststellen musste nachdem ich meine Cookies etc. gelöscht habe:
    Man kann sich nicht wieder einloggen, oben links öffnet sich das übliche Popup nicht zum einloggen.
    Jedoch kann man mit Rechtsklick > Link in neuen Tab öffnen < auf die Login-Seite wechseln.

    Benutze Google Chrome neuste Version :)

  • Forum Problemsammlung

    • Yjuq
    • 5. April 2015 um 20:11

    Irgendwie kann ich drz. nichts mehr in die ShoutBox schreiben. Warum weiß ich nicht...
    Die Seite wird nur neu refresht und das war's, aber die Nachrichten der anderen Teilnehmer kann ich doch schon lesen. :S

  • Revision 2015

    • Yjuq
    • 5. April 2015 um 20:09

    Ich hab ja noch nie ein Foto von Andy gesehen, aber irgendwie schaut er ganz anders aus als wie ich ihn mir ausgemalt habe. :D
    Und, wie war's? :)

  • primzahlenrechner

    • Yjuq
    • 2. April 2015 um 18:36

    Klar geht das schneller: Alle Primzahlen bis 1'000'000 in 1,5 Sekunden ^^

    Spoiler anzeigen
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $hTime = TimerInit()
    Global Const $aPrimes = SieveOfEratosthenes(1000000)
    ConsoleWrite(Round(TimerDiff($hTime) / 1000, 3) & ' Sekunden' & @CRLF)
    _ArrayDisplay($aPrimes)

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Func SieveOfEratosthenes(Const $iLimit)
    Local $iUBound = Floor(($iLimit -1) / 2)
    Local $i, $aSieve[$iUBound +1], $j, $iC, $iT, $aPrimes

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To Floor(Sqrt($iLimit) -1) / 2
    If Not $aSieve[$i] Then
    For $j = 2 * $i * ($i +1) To $iUBound Step 2 * $i +1
    If Not $aSieve[$j] Then
    $aSieve[$j] = True
    $iC += 1
    EndIf
    Next
    EndIf
    Next

    [/autoit] [autoit][/autoit] [autoit]

    $iT = $iC

    [/autoit] [autoit][/autoit] [autoit]

    Dim $aPrimes[$iUBound - $iC +1] = [2]
    For $i = 1 To $iUBound
    If Not $aSieve[$i] Then
    $aPrimes[$iT - $iC +1] += 2 * $i +1
    $iC -= 1
    EndIf
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $aPrimes
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]
  • Wenn beenden - MsgBox

    • Yjuq
    • 1. April 2015 um 19:50

    Meinst du vielleicht die OnAutoItExitRegister() Funktion?

  • Codeoptimierungen anhand von Beispielen

    • Yjuq
    • 1. April 2015 um 06:56

    Schönen guten Tag Community! :)
    In der letzten Zeit habe ich mich intensiv mit Algorithmen beschäftigt, darunter auch um die Optimierungen dieser. Durch die Project Euler bin ich auf ein paar interessante Aufgaben gestoßen, welche das Thema Primzahlen betrifft. Ich bin erstaunt was sich mit ein wenig Fachwissen an einem Algorithmus alles an Geschwindigkeit heraus holen lässt. Ich möchte mit euch meine Erkenntnisse teilen und einfach mal niederschreiben was ich gelernt habe. In Zukunft werde ich Probleme so angehen, wie ich es durch diese Website gelernt habe. Nun denn, fangen wir einmal an:


    Die Primfaktorzerlegung:
    Eine natürliche Zahl über 1 lässt sich in Primzahlen zerlegen (sofern diese nicht selber eine Primzahl ist). In diesen Teilabschnitt geht es darum einen Algorithmus zu entwickeln, der eine beliebige Zahl in ihre Primfaktoren zerlegt und diese als 2 dimensionales Array aus gibt. Gehen wir beispielsweise einmal von der Zahl 140 aus, ihre Primfaktoren sind 2^2 * 5 * 7. Doch wie genau können wir jetzt vorgehen um diese Primzahlen zu ermitteln?

    Ein Denkbarer (und einfacher) Ansatz wäre, einfach die Zahl ständig durch 2 zu dividieren, bis ein Rest entsteht. Danach dividieren wir die Zahl durch 3, 4 und 5 (usw.) bis aus unserer ursprünglichen Zahl 1 geworden ist. Versuchen wir das mal mit der 140:

    Code
    140 / 2 = 70 Rest 0
    70 / 2 = 35 Rest 0
    35 / 2 = 17 Rest 1 > Da ein Rest besteht, kann 2 als weiterer Faktor nicht mehr zutreffen...
    35 / 3 = 11 Rest 2
    35 / 4 = 8 Rest 3
    35 / 5 = 7 Rest 0
    7 / 5 = 1 Rest 2
    7 / 6 = 1 Rest 1
    7 / 7 = 1 Rest 0 > Abbruchbedingung erfüllt! Ergebnis ist 1 und Rest = 0.


    Wir sehen nun in unseren Rechnungen, dass jener Divisor welche als Faktor in Frage kommt ein restloses Ergebnis liefert. Dadurch sehen wir auch welche die Primfaktoren sind und wie oft diese vorkommen. Hier der dazu passende AutoIt Code:

    Spoiler anzeigen
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $zahl = 140
    Global $faktoren[Int(Sqrt($zahl))][2] ; Genug Speicher reservieren
    Global $zaehler = 0 ; Der Zähler um auf das Array zuzugreifen
    Global $divisor = 2 ; Der Divisor
    Global $time = TimerInit() ; Zum Zeit messen ^^

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    While $zahl <> 1 ; Da bei $zahl = 1 die Abbruchbedingung erfüllt ist...
    If Not Mod($zahl, $divisor) Then ; Wenn eine restlose Teilung besteht haben wir einen Faktor gefunden
    $faktoren[$zaehler][0] = $divisor ; Faktor in das Array schreiben
    $faktoren[$zaehler][1] = 1 ; Und die Anzahl

    [/autoit] [autoit][/autoit] [autoit]

    ; Den Faktor von der Zahl abziehen...
    $zahl /= $divisor

    [/autoit] [autoit][/autoit] [autoit]

    ; ... und gucken ob dieser nicht mehrmals vorkommt:
    While Not Mod($zahl, $divisor)
    $faktoren[$zaehler][1] += 1
    $zahl /= $divisor
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ; Da ein Faktor gefunden wurde und jetzt der nächste folgt muss der Zähler erhöht werden:
    $zaehler += 1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ; Nicht vergessen den Divisor um eins zu erhöhen!
    $divisor += 1
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ; Zuletzt das Array auf die passende Größe zuschneiden:
    ReDim $faktoren[$zaehler][2]

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite('Benötigte Zeit: ' & Round(TimerDiff($time) / 1000, 3) & ' Sekunden' & @CRLF)
    _ArrayDisplay($faktoren)

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]

    Funktioniert doch, erste Sahne. Nun fangen wir an mit den Optimierungen an. Sicherlich fragt sich jetzt der schlaue Leser, warum überhaupt Optimierungen vorgenommen werden sollten? Tja, ich sag nur eins: Setzt doch mal die Zahl 98765432123 spaßeshalber ein und lasst euch davon die Primfaktoren ausrechnen. Mein Rechner hat 2 Minuten gebraucht um herauszufinden dass die Primfaktoren von 98765432123 = 1447^1 * 68255309^1 sind. Jetzt wird auch schnell klar weshalb das unser Algorithmus für solch eine Zahl so lange braucht. Es muss 68255309 Schleifendurchgänge durchlaufen, um auch diesen großen Primfaktor zu ermitteln. Nicht gerade optimal. Jedoch können wir mit ein wenig Know-How die Laufzeit um 50% verringern ohne dass wir auf irgend eine Akademie gegangen sein müssen. Es gibt (außer der 2) keine geraden Primzahlen! Wie denn auch? Jede gerade Zahl lässt sich durch 2 teilen und ist daher keine Primzahl, wir können uns also ersparen die geraden Zahlen zu durchlaufen und überspringen diese einfach. Das bedeutet wir müssen am Anfang überprüfen ob die Zahl durch 2 teilbar ist, danach nur noch ob diese durch eine ungerade Zahl teilbar ist. Unser Algorithmus verändert sich also folgendermaßen:

    Spoiler anzeigen
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $zahl = 98765432123
    Global $faktoren[Int(Sqrt($zahl))][2]
    Global $zaehler = 0
    Global $divisor = 3 ; Da wir die Teilung durch 2 explizit behandeln können wir direkt bei 3 loslegen.
    Global $time = TimerInit()

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    ; Explizite Behandlung bei geraden Zahlen:
    If Not Mod($zahl, 2) Then
    $faktoren[0][0] = 2

    [/autoit] [autoit][/autoit] [autoit]

    While Not Mod($zahl, 2)
    $faktoren[0][1] += 1
    $zahl /= 2
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    $zaehler = 1
    EndIf

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While $zahl <> 1
    If Not Mod($zahl, $divisor) Then
    $faktoren[$zaehler][0] = $divisor
    $faktoren[$zaehler][1] = 1

    [/autoit] [autoit][/autoit] [autoit]

    $zahl /= $divisor
    While Not Mod($zahl, $divisor)
    $faktoren[$zaehler][1] += 1
    $zahl /= $divisor
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    $zaehler += 1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ; Divisor muss nur noch um 2 erhöht werden
    $divisor += 2
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ReDim $faktoren[$zaehler][2]

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite('Benötigte Zeit: ' & Round(TimerDiff($time) / 1000, 3) & ' Sekunden' & @CRLF)
    _ArrayDisplay($faktoren)

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]

    Super, damit haben wir unseren Anwender eine Wartezeit von einer Minute beschert, auf Toilette gehen kann er also auch nicht mehr, also müssen wir die Rechenzeit doch noch etwas verkürzen damit unsere Arbeit doch nicht ganz umsonst ist. Damit das allerdings klappt müssen wir eine andere Eigenschaft der Primzahlen ausnutzen. Jede Zahl kann(!) genau ein Primfaktor besitzen, welcher die Quadratwurzel der Zahl übersteigt. Dadurch müssen alle anderen Primfaktoren auf jeden Fall unter der Quadratwurzel der Zahl liegen. Damit haben wir schon mal ein Limit für unsere Schleifendurchgänge, und zwar die Quadratwurzel der Zahl. Damit können wir unseren Code noch mehr optimieren:

    Spoiler anzeigen
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $zahl = 98765432123
    Global $faktoren[Int(Sqrt($zahl))][2]
    Global $zaehler = 0
    Global $divisor = 3
    Global $time = TimerInit()
    Global $wurzel

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    If Not Mod($zahl, 2) Then
    $faktoren[0][0] = 2

    [/autoit] [autoit][/autoit] [autoit]

    While Not Mod($zahl, 2)
    $faktoren[0][1] += 1
    $zahl /= 2
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    $zaehler = 1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $wurzel = Sqrt($zahl)
    While $zahl <> 1 And $divisor <= $wurzel ; Weitere Abbruchbedingung ;)
    If Not Mod($zahl, $divisor) Then
    $faktoren[$zaehler][0] = $divisor
    $faktoren[$zaehler][1] = 1

    [/autoit] [autoit][/autoit] [autoit]

    $zahl /= $divisor
    While Not Mod($zahl, $divisor)
    $faktoren[$zaehler][1] += 1
    $zahl /= $divisor
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Wurzel neu berechnen da sich die Zahl verändert hat:
    $wurzel = Sqrt($zahl)
    $zaehler += 1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    $divisor += 2
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ; Da es noch eine Primfaktor geben könnte der die Quadratwurzel übersteigt (wenn $zahl <> 1 ist):
    If $zahl <> 1 Then
    $faktoren[$zaehler][0] = $zahl
    $faktoren[$zaehler][1] = 1
    $zaehler += 1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ReDim $faktoren[$zaehler][2]

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite('Benötigte Zeit: ' & Round(TimerDiff($time) / 1000, 3) & ' Sekunden' & @CRLF)
    _ArrayDisplay($faktoren)

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]

    Und wenn wir den Code jetzt ausführen, brauchen wir für die gleiche Zahl, die uns vorhin mit unverschämten 120 Sekunden geärgert hat, knapp nur noch 10 Millisekunden. Wenn das mal keine Steigerung der Geschwindigkeit von unseren ursprünglichen Algorithmus ist! Die Geschwindigkeit hat sich um den Faktor 12000 verringert! Nun könnten wir nur noch berechnen wie viele Primfaktoren in etwa die Zahl hat und somit den Speicherbedarf für das Array senken. Eine Möglichkeit wäre es, alle Primzahlen zu multiplizieren (ab 2 aufwärts) bis wir die Zahl 2^64 -1 (x64) bzw. 2^32 -1 (x86) übersteigen. Die Anzahl der Faktoren entspricht somit die Anzahl der meist möglichen Primfaktoren für den überhaupt möglichen Speicherbereich. Dadurch können wir dem Array eine fixe Größe Zuteilen dessen Anzahl der Elemente wir nicht zur Laufzeit berechnen müssen.

    >> Weiteres folgt noch...
    Gerne dürft ihr auch selber was dazu schreiben :)

  • Forum Problemsammlung

    • Yjuq
    • 1. April 2015 um 03:45

    Achja, der Server... ^^
    IRC ist noch Neuland für mich, bin froh dass ich zmd. einen Client gefunden haben *g*
    Ich glaube der Server ist folgender: sinisalo.freenode.net

    €dit:
    Hmn, auch hier: irc.afterworkchat.de
    Also beide ^^

  • Forum Problemsammlung

    • Yjuq
    • 1. April 2015 um 03:27

    Gab's dazu auch irgendwo eine Ankündigung oder woher weißt du das? ^^
    Mich hat's jedenfalls etwas geärgert...

    Naja, ich verweile dann mal (bis alles fertig ist) im IRC Channel #autoit
    Wer ein wenig Konversation führen will kann ja dazu stoßen. :S

  • Forum Problemsammlung

    • Yjuq
    • 1. April 2015 um 03:10

    Servus, kommt es mir nur so vor oder funktioniert das Forum nicht so wie es soll?
    Bei mir habe ich im Titel "Burning Board" und der Aufruf ging die letzten 3 Tage überhaupt nicht.
    Zudem fehlt bei mir komplett die ShoutBox, wenigstens geht die Anmeldung drz.

    Was ist los? Ist das nur bei mir so oder ist das Forum unangekündigt im Wartungsmodus?


    €dit: 1. April 2015 – 16:53 Uhr
    Da es mir so vorkommt als würde der Thread zum neuen Sammlung an Problemen, war ich mal so frei den Titel zu ändern. ^^
    Ich versuche mal im Laufe der Zeit hier die aktuellen Probleme als Liste festzuhalten, sodass Gun-Food sich da nicht durch die Beiträge wühlen muss.


    €dit: 25. August 2015 - 19:17 Uhr

    • Codeformatierungen werden im Online Editor drz. nicht übernommen. (https://autoit.de/index.php/Thre…ne-Alternative/)

    Sorry dass ich so spät erst die Liste erstelle, aber nach dem Thread hier schien @Gun-Food mit Hochdruck dran zu arbeiten dass ich dachte, eine Liste sei nicht mehr notwendig. Falls weitere Dinge auftauchen werde ich diese hier ergänzen.

  • primzahlenrechner

    • Yjuq
    • 29. März 2015 um 20:23

    GegX:
    Dein Algorithmus hat eine Ausführungszeit von 25 Sekunden bei mir. Ich habe mal versucht mithilfe des Sieb des Eratosthenes die benötigte Zeit zu verringert. Alle Primzahlen von 2 bis 1000000 werden bei mir in 18~19 Sekunden ermittelt. Da geht bestimmt noch mehr:

    Spoiler anzeigen
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <Array.au3>
    #include <MsgBoxConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $iNumb = 1000000
    Global $hTimer, $aPrimes

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    $hTimer = TimerInit()
    $aPrimes = SieveOfEratosthenes($iNumb)
    ConsoleWrite('Time => ' & TimerDiff($hTimer) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayDisplay($aPrimes)

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Func SieveOfEratosthenes($iNumb)
    Local $aPrimes[Ceiling($iNumb / 2) +1] = [1, 2]
    Local $i, $n, $aFindAll

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 3 To 2 * UBound($aPrimes) -2 Step 2
    $aPrimes[0] += 1
    $aPrimes[$aPrimes[0]] = $i
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 2 To Sqrt($aPrimes[0])
    If Not $aPrimes[$i] Then ContinueLoop

    [/autoit] [autoit][/autoit] [autoit]

    For $n = $i + $aPrimes[$i] To $aPrimes[0] Step $aPrimes[$i]
    $aPrimes[$n] = False
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    $aFindAll = _ArrayFindAll($aPrimes, False)
    _ArrayInsert($aFindAll, 0, UBound($aFindAll))
    _ArrayDelete($aPrimes, $aFindAll)
    $aPrimes[0] = UBound($aPrimes)

    [/autoit] [autoit][/autoit] [autoit]

    Return $aPrimes
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]
  • primzahlenrechner

    • Yjuq
    • 29. März 2015 um 01:49

    Servus, ich war gerade dabei die Aufgabe 3 (deutsche Übersetzung) in den Project Eulers zu bewerkstelligen. Es ging um Primfaktorzerlegung, da dies ganz gut zum Thema passt würde ich gerne das Skript hier veröffentlichen. Aufgrund der hohen Zahl musste ein effizienter Algorithmus her ~ Naja ^^

    Primfaktorzerlegung
    [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    #include <Array.au3>
    #include <MsgBoxConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $aPrimeFactors = GetPrimeFactors(600851475143)

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox($MB_TOPMOST, 'Problem 3 - Largest prime factor', $aPrimeFactors[$aPrimeFactors[0]])

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit] [autoit][/autoit] [autoit]

    Func GetPrimeFactors($iNumb)
    Local $aPrimes[] = [2, 2, 3]
    Local $aPrimeFactors[1]
    Local $iC

    [/autoit] [autoit][/autoit] [autoit]

    While $iNumb <> 1
    $iC = 1
    While Mod($iNumb, $aPrimes[$iC])
    $iC += 1
    If $iC > $aPrimes[0] Then AddNextPrime($aPrimes)
    WEnd
    $iNumb /= $aPrimes[$iC]
    _ArrayAdd($aPrimeFactors, $aPrimes[$iC])
    $aPrimeFactors[0] += 1
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _ArraySort($aPrimeFactors, 0, 1)
    Return $aPrimeFactors
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func AddNextPrime(ByRef $aPrimes)
    Local $iNumb = $aPrimes[$aPrimes[0]]
    Local $i

    [/autoit] [autoit][/autoit] [autoit]

    While True
    $iNumb += 2
    For $i = 1 To $aPrimes[0] -1
    If Not Mod($iNumb, $aPrimes[$i]) Then ContinueLoop(2)
    Next
    _ArrayAdd($aPrimes, $iNumb)
    $aPrimes[0] += 1
    Return
    WEnd
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +

    [/autoit]
  • [Sammelthread] Fangfragen, Rätsel & Co

    • Yjuq
    • 28. März 2015 um 22:10

    Rätsel #1:
    Ein Mann geht nach einer langen Sauftour stark angetrunken nach Hause. Auf der Straße entdeckt er eine Münze am Boden liegen. Obwohl weder Mond noch Sterne am Himmel sichtbar sind und auch keine Straßenlaterne an ist, hat er das Geldstück schon von weitem gesehen. Wie ist das möglich?

    Lösung

    Es war Tag!

    Rätsel #2:

    Code
    56784 = 4
    11111 = 0
    72348 = 3
    88652 = 5
    88811 = 6
    75213 = 0
    65465 = 3
    62257 = ?

    Welche Zahl wird gesucht? Mit Begründung bitte! :)

    Lösung

    62257 = 1
    Man zähle alle Flächen in den Zahlen ^^
    4, 6, 9 und 0 haben jeweils eine Fläche. 8 sogar schon 2 Flächen. :P

    Rätsel #3:
    Loch an Loch und hält doch?

    Lösung

    Die Kette!

    Rätsel #4
    Was haben Leetspeak, die Kreiszahl Pi und die Antwort auf Alles gemeinsam?

    Lösung
    [autoit]

    If Round(13.37 * 3.141) = 42 Then MsgBox(0x40000, 'Rätsel #4', 'Des Rätsels Lösung!')

    [/autoit]
  • [Sammelthread] Fangfragen, Rätsel & Co

    • Yjuq
    • 28. März 2015 um 21:54
    Lösung
    Code
    | x |          | x |           x |
     ---     =>       ---    =>     ---
      |              |             |   |
  • [Sammelthread] Fangfragen, Rätsel & Co

    • Yjuq
    • 28. März 2015 um 21:28

    Das Rätsel ist mir ja schon beinahe zu einfach. ^^
    Die Lösung setze ich einfach mal vorsichtshalber in einen Spoiler:

    Spoiler anzeigen

    Voraussetzung für die Lösung dieses Rätsel ist es, dass die 3 Personen intelligent genug sind um auf folgenden Zusammenhang zu kommen:

    Die letzte Person in der Reihe sieht natürlich sofort wer die weiße Mütze auf hat. Ist dies keiner, so muss er diese zwangsläufig selber aufhaben. Hat er sie auf, so meldet er sich zu Wort, hat er sie nicht auf, so schweigt er. Der zweite in der Reihe sieht den ersten in der Reihe. Hat er eine schwarze Mütze auf so kann er davon ausgehen dass entweder er oder die Person hinter ihnen die weiße auf hat. Sagt der letzte nichts, so weiß er dass er die weiße Mütze auf hat. Der erste in der Reihe muss lediglich ein wenig warten, meldet sich keiner der beiden Personen hinter ihnen zu Wort, so muss er zwangsläufig die weiße Mütze aufhaben. Und hier die Lösung des Rätsels als kleines AutoIt Skript:

    [autoit]

    Global Const $iPrs = 100 ; Anzahl der Personen
    Global Const $iRnd = Random(0, $iPrs -1, 1)
    Global $aPrs[$iPrs], $i, $n, $bState

    [/autoit] [autoit][/autoit] [autoit]

    ; Einer der Personen die weiße Mütze zuteilen
    $aPrs[$iRnd] = True
    ConsoleWrite('> Person #' & ($iRnd +1) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    ; Weiße Mütze raussuchen durch Zeitverzögerung (könnte man mit Timer realisieren)
    For $i = $iPrs -1 To 0 Step -1
    $bState = False
    For $n = $i -1 To 0 Step -1
    $bState = $bState Or $aPrs[$n]
    Next
    If Not $bState Then Exit MsgBox(0x40000, 'Mütze', 'Person #' & ($i +1) & ' hat die weiße Mütze auf.')
    Next

    [/autoit]
  • [Sammelthread] Fangfragen, Rätsel & Co

    • Yjuq
    • 28. März 2015 um 19:37

    Lol, da bin ich nicht drauf gekommen :D

  • Frage: bezüglich Button aus einem externen Programm in eigenes GUI spiegeln

    • Yjuq
    • 25. März 2015 um 10:57

    Rein theoretisch kannst du zu dem control einzelne messages senden um ein screenshot vom jeweiligen zustand des controls zu machen. Danach musst du lediglich die paint messages vom gleichen controltyp uberschreiben und die kopierten screenshots anzeigen. Funktioniert bei einem button natuerlich besser als bei einem edit control. Besser ist es natuerlich doch lieber das design der controls per hand zu verfassen da du da mehr spielraum hast. Beides ist sowieso auf gleicher weise aufwendig.

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™