Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]12122[/thread]

Mit Perl rechnen (Seite 8)

Leser: 4


<< |< 1 ... 5 6 7 8 >| >> 77 Einträge, 8 Seiten
Ronnie
 2008-07-04 19:51
#111856 #111856
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Zu der Problemstellung Primzahlen, sollten sich dutzende Lösungen hier im Forum finden. Auf jeden Fall empfehle ich das Buch: "Einführung in Perl" erschienen bei O'Reilly. Als Anregung dient dir evtl. folgendes Snippet:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

sub is_prime {
    my $i = shift;
    die if $i < 2;
    
    return 2 if $i == 2;    
    $i % $_ == 0 and return for 2..(($i/2)+1);
    return $i;
}

my $number  = shift @ARGV || 129;
print Dumper [grep is_prime($_), 2..$number];
KurtZ
 2008-07-04 20:05
#111858 #111858
User since
2007-12-13
411 Artikel
BenutzerIn
[default_avatar]
Ronnie+2008-07-04 17:51:26--
Als Anregung dient dir evtl. folgendes Snippet:
Code (perl): (dl )
    $i % $_ == 0 and return for 2..(($i/2)+1);


Ich starre nun seit 2 Minuten auf diese Zeile und empfinde sie als Anregung Python zu erlernen!

NACHTRAG: so wirds etwas lesbarer
Code (perl): (dl )
1
2
3
        for my $teiler (2..(($i/2)+1)) {
                return 0 if $i % $teiler == 0;   # Abbrechen wenn kein Rest bleibt
        }


aber mathematisch wärs erstens sinnvoller nur die teiler bis wurzel i zu betrachten, und zwotens könnte man sich auf die bekannten Primzahlen kleiner sqrt(i) beschränken, statt alle Zahlen zu betrachten. Das käme dem Sieb des Erathostenes viel näher.
TMTOWTDYOG (there's more than one way to dig your own grave)
Ronnie
 2008-07-04 21:44
#111859 #111859
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Hallo Kurt,
KurtZ+2008-07-04 18:05:24--
Ich starre nun seit 2 Minuten auf diese Zeile und empfinde sie als Anregung Python zu erlernen!

*lacht* - ich müsste ausprobieren ob es als Listcomprehension in Python nicht ähnlich aussieht ;)
KurtZ+2008-07-04 18:05:24--
aber mathematisch wärs erstens sinnvoller nur die teiler bis wurzel i zu betrachten, und zwotens könnte man sich auf die bekannten Primzahlen kleiner sqrt(i) beschränken, statt alle Zahlen zu betrachten. Das käme dem Sieb des Erathostenes viel näher.

Ja, auf jeden Fall. Deshalb schrieb ich: "als Anregung". Es war das Erste was eine Volltext-Suche nach "prime" in meinem alten Code-Verzeichnis lieferte. Es funktioniert, ist aber nicht wirklich toll. Wer will schaut sich eben den Eintrag zum Sieb des Eratosthenes in Wikipedia an (hat AFAIR schon einer von euch gepostet).

Gruß,
Ronnie
pq
 2008-07-04 21:49
#111860 #111860
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
Napstack+2008-07-04 16:34:12--
ich bin im 7. und nein wir hatte es noch nicht

für die programmierung ist es wichtig, dass du die aufgabe und den lösungsweg erstmal
verstanden hast, sonst ist die umsetzung in eine programmiersprache nur rumprobieren,
bis es zufällig klappt.
Wikipedia:Sieb_des_Eratosthenes
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Linuxer
 2008-07-04 21:58
#111861 #111861
User since
2006-01-27
3875 Artikel
HausmeisterIn

user image
pq+2008-07-04 19:49:42--
Wikipedia:Sieb_des_Eratosthenes

++ dafür. Hab neue Einsichten bekommen ;o) (denn ich mir das bisher nicht angesehen)
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
Napstack
 2008-07-05 01:18
#111865 #111865
User since
2008-07-03
32 Artikel
BenutzerIn
[default_avatar]
So hier noch mal eine Ausführliche erklärung. An dieser Stelle nochmal ein ganz großes danke an Linuxer.

Dieser code basirt auf dem #46 Beitrag. Allerdings ist der Code hier von Linuxer mit infos voll gestopft.
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/perl
use strict;
use warnings;

my ($Zahl, $is_prime, $p);
my @prime = ("2");
print "Bis zu welcher Zahl sollen die Primzahlen gesucht werden?";
chomp(my $Ziel = <STDIN>);

foreach $Zahl (3..$Ziel) {

    ### $is_prime ist ein Anzeiger, ob $Zahl eine Primzahl ist;
    ### wir gehen erstmal davon aus, dass sie eine ist (1 bedeutet hier WAHR)
    $is_prime = 1;

    #Wofür ist $p was macht sie und brauche ich das for noch?
    ### $p ist die Laufvariable innerhalb der Schleife;
    ### das foreach macht klar, dass Du hier in einer Schleife jedes Element aus @prime
    ### durchforsten willst; dafuer wird jedes Element einmal in $p abgelegt, damit du
    ### damit arbeiten kannst;
    foreach $p (@prime) {

        ### also pruefen, ob die aktuelle $Zahl durch eine der zuvor gefundenen Primzahlen
        ### teilbar ist; d.h. wenn kein Rest bei der Division uebrig bleibt
        if ($Zahl % $p == 0){

            ### $Zahl ist durch $p teilbar und kann also keine Primzahl sein
            ### deswegen setzen wir $is_prime auf 0 (0 bedeutet UNWAHR)
            $is_prime = 0;

            ### Bevor du sicher bist, dass $Zahl eine Primzahl ist, gibst Du hier die $Zahl
            ### schon aus und packst sie zu den Primzahlen? 
            ### Das kann nicht richtig sein; denn wie eben gerade festgestellt, kommen
            ### wir nur hier hin, weil $Zahl durch $p teilbar ist; damit ist es *keine*
            ### Primzahl... als raus damit...
            #weg: print $Zahl, "\n";
            #weg: push @prime, $Zahl;
            
            #Was macht das last?
            ### Weil wir ein $p gefunden haben, durch das $Zahl teilbar ist, brauchen wir
            ### kein weiteres $p pruefen; $Zahl ist keine Primzahl;
            ### also brechen wir mit 'last' die (innere) Schleife ab
            last;
        }

    } ### Ende innerer Schleife

    ### $Zahl kann nur dann eine Primzahl sein, wenn sie durch keine in @prime enthaltene
    ### Zahl teilbar ist; damit Du sicher sein kannst, dass $Zahl eine Primzahl ist, musst
    ### Du nun $is_prime pruefen, um $Zahl zu den Primzahlen in @prime packen zu koennen.
    ### Welchen Wert musst $is_prime dafuer haben?
}


Schauen wir uns mal an, was passiert wenn wir in der inneren Schleife $Zahl % $p >= 1 verwenden.
Code: (dl )
1
2
3
4
5
6
7
8
$Zahl = 3; @p = (2);
3 % 2 = Rest 1, also wird 3 an @p gepackt; ### das ist OK

$Zahl = 4; @p = ( 2, 3 );
4 % 2 = Rest 0; also nächste Zahl aus @p testen
4 % 3 = Rest 1, also wird 4 an @p gepackt ### das ist nicht mehr OK

Wir müssen dabei bedenken, dass $Zahl jetzt 4 enthaelt, und wir diese 4 an @p anhaengen ...


Also muss
print $Zahl, "\n";
push @prime, $Zahl;
außerhalb der inneren Schleife eingefügt werden.

Eine komplettlösung will ich hier nicht reinstellen weil dann kein lernefekt da ist.



Zum Schluss möchte ich mich nochmal bei allen, die ich "angeprollt" habe entschuldigen.
KurtZ
 2008-07-05 20:35
#111888 #111888
User since
2007-12-13
411 Artikel
BenutzerIn
[default_avatar]
hallo Ronnie
Ronnie+2008-07-04 19:44:59--
*lacht* - ich müsste ausprobieren ob es als Listcomprehension in Python nicht ähnlich aussieht ;)


mach mal, würd mich sehr interessieren!

Hab mich grob mit Python befasst, und finde vieles deutlich unintuitiver als man eigentlich erwartet (was natürlich auch an der Erwartungshaltung liegt)

mal geschaut ... http://en.wikipedia.org/wiki/List_comprehension#In_Python

zugegeben an diesen klammerfreien Syntax muss man sich auch gewöhnen

aber semantisch entspricht das doch in PL einem mit grep erzeugtem Array, oder?

Da könnte ich auch schreiben
Code (perl): (dl )
1
2
return scalar  grep { $i % $_ == 0 } (2 .. sqrt($i)); 
# 0 wenn es keinen restfreien Teiler gibt


Ich finde man sollte "Bedingte Ausführung" mit AND oder OR der Lesbarkeit willen sparsam verwenden, insbesondere kombiniert mit Postfix-Schleifen.

wenn man einen Einzeiler mit schnellem Abbruch beim ersten Teiler will, kann man ja auch den Schleifenkörper inlinen.
Code (perl): (dl )
 for ( 2 .. sqrt($i) )  { return $_  unless $i % $_ }  

bzw.
Code (perl): (dl )
 for ( 2 .. sqrt($i) )  { return $_  if $i % $_  == 0} 


IMHO lesbarer ...
TMTOWTDYOG (there's more than one way to dig your own grave)
<< |< 1 ... 5 6 7 8 >| >> 77 Einträge, 8 Seiten



View all threads created 2008-07-03 17:04.