Die ersten 15 Primzahlen ausgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

pillmuncher hat geschrieben: Einer hat allen Ernstes in geschachtelten Schleifen mittels "+" XML-Dateien erzeugt. Nachdem ich das gesehen hatte, hätte ich mir wieder mal am liebsten die Augen mit Kernseife ausgewaschen.
Ach daher die Sonnenbrille :-D SCNR ;-)
Aber danke für die Belege - evtl. fruchtet da ja doch noch mal etwas...

PS: Deine Optiker-Parabel ist echt genial :twisted:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
problembär

Aus euren Beiträgen habe ich nunmehr gelernt, daß man eure eingebildete Code-Ideologie zugunsten der Freiheit der Gedanken (Art. 5 GG) aktiv bekämpfen muß.
Deshalb werde ich hier noch weiter auf Anfänger in dieser Weise Einfluß nehmen und dabei noch weniger Zugeständnisse an angebliche Code-Konventionen machen, siehe dazu meine neue Signatur.
Der Hinweis von bords0 war korrekt, insofern sieht der richtige Code jetzt so aus:

Code: Alles auswählen

#!/usr/bin/python
# coding: iso-8859-1

l = []
llen = 0
n = 2

while llen < 15:
    x = 0
    for i in l:
        if n % i == 0:
            x = 1
            break
    if x == 0:
        l.append(n)
        llen += 1
    n += 1

for i in range(llen):
    print str(i + 1) + ". " + str(l[i])
BlackJack

Och wie süss, ein Troll…
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

problembär hat geschrieben:Aus euren Beiträgen habe ich nunmehr gelernt, daß man eure eingebildete Code-Ideologie zugunsten der Freiheit der Gedanken (Art. 5 GG) aktiv bekämpfen muß.
LOL... YMMD :mrgreen:

Der Code wird ja immer kruder.... was ist `llen`... erinnert mich an "LLoyd" für alle ALF-Kenner ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

problembär hat geschrieben:Aus euren Beiträgen habe ich nunmehr gelernt, daß man eure eingebildete Code-Ideologie zugunsten der Freiheit der Gedanken (Art. 5 GG) aktiv bekämpfen muß.
Sehr schwach. Hättest du nicht wenigstens einen Nazi-Vergleich anstellen können?
problembär hat geschrieben:Deshalb werde ich hier noch weiter auf Anfänger in dieser Weise Einfluß nehmen und dabei noch weniger Zugeständnisse an angebliche Code-Konventionen machen, siehe dazu meine neue Signatur.
Auch schwach. PEP8 hat mit der Diskussion hier überhaupt nichts zu tun. Dort geht es um Formatierungsfragen und Besonderheiten, wie dass man Singleton-Vergleiche mittels "is" statt "==" durchführen sollte, hier aber darum, dass man - wenn man nicht total belämmert ist - die deklarativen Elemente von Python den prozeduralen vorziehen sollte.
problembär hat geschrieben:

Code: Alles auswählen

#!/usr/bin/python
# coding: iso-8859-1

l = []
llen = 0
n = 2

while llen < 15:
    x = 0
    for i in l:
        if n % i == 0:
            x = 1
            break
    if x == 0:
        l.append(n)
        llen += 1
    n += 1

for i in range(llen):
    print str(i + 1) + ". " + str(l[i])
Ich gebe gerne zu, dass das wie sehr übersichtliches BASIC aus dem Jahr 1986 aussieht. Hier meine Version in Python 3 aus dem Jahr 2011 (die vermutlich schon jemand anders ziemlich genau so gepostet hat - ich hab den Thread nur überflogen):

Code: Alles auswählen

from itertools import count

def primes():
    """ eine Generator-Funktion, die die Folge der Primzahlen erzeugt """
    ps = []                         # gefundene Primzahlen
    for n in count(2):              # gehe durch alle ganzen Zahlen, beginnend mit der kleinsten Primzahl
        if all(n % p for p in ps):  # Primzahlen sind ganze Zahlen, die durch keine kleinere Primzahl ohne Rest teilbar sind
            ps.append(n)            # n ist eine solche Zahl. Wir merken sie uns.
            yield n                 # wir geben sie aus

for i, p in zip(range(1, 16), primes()):
    print(i, ':', p)
Das sind 9 Zeilen ausführbarer Code im Vergleich zu deinen 15, mithin nur 60% XLOC. Succinctness Is Power. Und XLOC korrespondiert statistisch mit der Anzahl der Fehler, wie Les Hatton in diesem PDF darlegt. Wie übrigens auch die zyklomatische Komplexität statistisch mit XLOC und Fehler-Anzahl korreliert ist. Die ist bei dir ebenfalls höher, als bei mir.

Die funktionale Zerlegung meines Codes ist auch besser. Das kann man daran sehen, dass eine Analyse des Problems in Pseudo-Code ungefähr sowas ergibt:

Code: Alles auswählen

gib die ersten 15 Primzahlen aus:
    erzeuge die Folge der Primzahlen
    gib die ersten 15 davon aus

erzeuge Primzahlen:
    für jede ganze Zahl n >= 2:
        wenn n eine Primzahl ist:
            gib n aus

Primzahl-Test:
    jede ganze Zahl >= 2, die durch keine kleinere Primzahl ohne Rest teilbar ist, ist prim
Das ist schon sehr nah an meinem Code, aber nicht an deinem.
In specifications, Murphy's Law supersedes Ohm's.
deets

problembär hat geschrieben:Ich will mich wohl immer noch nicht voll und ganz auf Python einlassen. Eigentlich ist C wohl mein Ideal; leider ist es eher eine Haßliebe. Wenn ich versuche, mich C zu nähern, kommt als schroffe Antwort meist nur "Speicherzugriffsfehler". ;)
Mit anderen Worten: du begreifst C nicht, aber glaubst, was du da schon nicht beherrschst, ist dann properes Programmieren wenn man es mit Gewalt in Python genauso versucht zu machen?

Na, man muss man Leuten wie dir im Grunde dankbar sein - sonst wuerde the daily WTF ja nicht seinen hohen Unterhaltungswert behalten...
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

problembär hat geschrieben:
Hyperion hat geschrieben:...
Dieses " " + " " + " " + ... Gefrickel liest sich ja furchtbar.
...
Das ist so auch viel lesbarer als dieser '" ".join()'-Schwachsinn ...
Ich betreibe den join-Schwachsinn sogar so gut wie es geht in anderen Sprachen, z.B. Javascript:

Code: Alles auswählen

var foo = ''.concat(
    'dies ist ein sehr langer und langweiliger Text mit vielen Zeilen ',
    'und noch mehr Zeilen und noch mehr ',
    'denn leider kann Javascript keine mehrzeiligen Strings wie z.B. Python '
    'mit den drei """ ...'
);
Find ich deutlich übersichtlicher als foo immer mit += zu verketten :K
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Tja, frabron, hättest du mal CoffeeScript genutzt, da gibt es die Python-Multiline-Strings. :)

Ist es wieder Puzzle-Zeit? Ich mach mal den Anfang:

Code: Alles auswählen

(defn prime? [n]
  (not-any? zero? (for [i (range 2 n)] (rem n i))))

(defn all-primes []
  (for [candidate (iterate inc 2)
        :when (prime? candidate)]
        candidate))
        
(println (take 15 (all-primes)))
(Wobei ich mich ja schon frage, warum ``rem`` in Clojure drin ist, aber ``sqrt`` zu esoterisch ist und in contrib zu finden ist)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Der Haskell-Klassiker (mit ein bisschen Unicode garniert):

Code: Alles auswählen

{-# LANGUAGE UnicodeSyntax #-}
import Prelude.Unicode

primes :: [ℤ]
primes = sieve [2..]
    where sieve (p:xs) = p : sieve [x | x ← xs, x `mod` p ≠ 0]

main = putStrLn ∘ show $ take 15 primes
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich hätte da noch Lösung in C++:

Edit: ausgelagert
Zuletzt geändert von EyDu am Dienstag 29. November 2011, 14:16, insgesamt 1-mal geändert.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

EyDu hat geschrieben:Ich hätte da noch Lösung in C++:
:shock: Ich hab auch mal in C++ programmiert, aber hier verstehe ich kein Wort :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ich hab eine Lösung in D, mit einem kleinen Schmankerl ;)

Code: Alles auswählen

import std.stdio : writefln;
import std.array : join;
import std.algorithm : map;
import std.conv : to;

enum NUM_PRIMES = 15;

uint[] primes(uint num) {
    uint[] res;
    
    for(int n = 2; res.length < num; n++) {       
        bool is_prime = true;
        foreach(uint p; res) {
            if(n % p == 0) {
                is_prime = false;
                break;
            }
        }
        
        if(is_prime) {       
            res ~= n;
        }
    }

    return res;
}

version(ctfe) {
    uint[] pr = primes(NUM_PRIMES);
}

void main() {
    version(ctfe) {
        uint p[] = pr;
    } else {
        uint p[] = primes(NUM_PRIMES);
    }
    writefln("%s", join(map!(to!string)(p), ", "));
}
Hat einer eine Idee wie man:

Code: Alles auswählen

        bool is_prime = true;
        foreach(uint p; res) {
            if(n % p == 0) {
                is_prime = false;
                break;
            }
        }
mithilfe von map, reduce und filter formulieren kann?

PS:

Code: Alles auswählen

dmd -ofprimes1 primes.d    
dmd -ofprimes2 -version=ctfe primes.d
time ./primes1
time ./primes2
(erst bei höheren NUM_PRIMES erkennbar)

//Edit: @C++-Lösung, wtf
the more they change the more they stay the same
BlackJack

@Hyperion: Die Berechnungen erfolgen in den Templates bei der Übersetzung. Im übersetzen Programm sind die Primzahlen dann schon fertig berechnet drin. :-)

Hier ist mal eine Lösung die problembär gefallen dürfte. So hat man Anfang der 90er in Pascal programmiert:

Code: Alles auswählen

Program FirstPrimes;
Const
    N = 15;
Var
    i, pn : Byte;
    candidate : Word;
    isPrime : Boolean;
    primes : Array[1..N] Of Word;
Begin
    primes[1] := 2;
    pn := 1;
    candidate := 3;
    While pn < N Do
    Begin
        isPrime := True;
        For i := 2 To pn Do
        Begin
            If candidate MOD primes[i] = 0 Then
            Begin
                isPrime := False;
                Break;
            End;
        End;
        If isPrime Then
        Begin
            Inc(pn);
            primes[pn] := candidate;
        End;
        Inc(candidate, 2);
    End;
    For i := 1 To N Do
    Begin
        WriteLn(i:2, '. Primzahl = ', primes[i]);
    End;
End.
@Dav1d: Das wurde ja schon mit `all()` gezeigt. Das kann man zwar mittels `reduce()` ausdrücken, aber nicht so effizient, da man nicht abbrechen kann sobald ein Element `False` ist.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dav1d hat geschrieben:Hat einer eine Idee wie man:

Code: Alles auswählen

        bool is_prime = true;
        foreach(uint p; res) {
            if(n % p == 0) {
                is_prime = false;
                break;
            }
        }
mithilfe von map, reduce und filter formulieren kann?
Ungetestet:

Code: Alles auswählen

bool(reduce(lambda x, y: x and n%y, res, True))
Natürlich nicht besonders effizient, da reduce alle Ziffern durchlaufen wird. Daher kann man es eigentlich gleich mit map und all lösen.
Das Leben ist wie ein Tennisball.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

@BlackJack, ich habe kein `all` in D
the more they change the more they stay the same
BlackJack

@Dav1d: Darum schrieb ich ja, dass man das mit `reduce()` ausdrücken kann.

@all: Eine Io-Lösung:

Code: Alles auswählen

#!/usr/bin/env io
Range

n := 15
primes := List with(2)
3 toBy(Number unsignedLongMax, 2) foreach(candidate,
    primes detect(prime, candidate mod(prime) == 0) ifNil(
        (primes append(candidate) size == n) ifTrue(break(primes))
    )
) foreach(i, prime, "#{i + 1}. Primzahl = #{prime}" interpolate println)
BlackJack

Noch zwei eher unmoderne Lösungen, die im Gegensatz zum Pascal-Quelltext aber deutlich kompakter sind.

Die erste ist ohne ``while`` und ``break`` — hauptsächlich weil CBM BASIC V2 beides nicht kennt. :-)

Code: Alles auswählen

   10 N=15:DIM P(N):P(1)=2:PN=1:C=3
   20 FOR I=1 TO PN:T=INT(C/P(I)):F=T*P(I)=C:IF F THEN I=PN
   30 NEXT
   40 IF NOT F THEN PN=PN+1:P(PN)=C:IF PN=N THEN 60
   50 C=C+2:GOTO 20
   60 FOR I=1 TO N:PRINT I;"{LEFT}. PRIMZAHL =";P(I):NEXT
Die zweite ist in RPL geschrieben was auf Taschenrechnern von Hewlett Packard wie dem HP48G als Programmiersprache zur Verfügung steht:

Code: Alles auswählen

« 15 { 2 } 3 → M PS I
  «
    WHILE PS SIZE M <
    REPEAT I PS MOD 0 POS NOT
      « PS { I } EVAL + 'PS' STO
      » IFT 'I' 2 STO+
    END PS
  »
»
Benutzeravatar
snafu
User
Beiträge: 6857
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sag mal BlackJack, wieviele Sprachen kannst du eigentlich? :mrgreen:
BlackJack

@snafu: Ich hatte halt mal so eine Phase in der ich alle möglichen Sprachen durchprobiert habe. Einiges ist dabei hängen geblieben. :-)

Bei manchen Sprachen, die ich dann hier bei solchen Gelegenheiten wieder ausgrabe, muss ich mein Wissen aber auch wieder auffrischen und mal einen Blick in die Dokumentation werfen. Beim RPL aus meinem letzten Beitrag zum Beispiel. Den Taschenrechner besitze ich zwar, aber Programme habe ich darauf/dafür schon relativ lange nicht mehr geschrieben. Das habe ich gemacht als das Gerät für mich noch neu wahr. Den gab es 1998 als Weihnachtsgeschenk.

Für das CBM-BASIC V2 habe ich auch noch die Hardware. Das war meine erste Programmiersprache.

Ansonsten sammelt man halt ein paar Sprachen an, wenn man etwas länger und auf verschiedenen Systemen programmiert. :-)
Antworten