Thread Pythagorische Tripel (18 answers)
Opened by Ronnie at 2008-10-19 15:57

MatthiasW
 2008-10-31 19:20
#115889 #115889
User since
2008-01-27
367 Artikel
BenutzerIn
[default_avatar]
Mit nachfolgendem Modul gehts auch so:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
my( $i, $j, $k );
my $li = lazy { ${$_[0]}++ } 1;
my $lj = lazy { ${$_[0]} > $i ? undef : ${$_[0]}++ } 1;
my $lk = lazy { ${$_[0]} > $j ? undef : ${$_[0]}++ } 1;

my $iterator = sub {
        lcomp { $i**2 == $j**2 + $k**2 ? [$k,$j,$i] : undef }
                \$i => $li,
                \$j => $lj,
                \$k => $lk;
};

while ( defined( my $elem = $iterator->() ) ) {
        print Dumper( $elem );
        <STDIN> eq "q\n" and exit;
} # while

Wobei $iterator eigentlich überflüssig ist. lazy() spart im Prinzip nur Tipparbeit, beim erstellen einer Closure und lcomp() funktioniert fast genauso wie comp(), nur dass die einzelnen Funktionen undef zurückgeben um zu signalisieren, dass sie keine weiteren Werte mehr liefern.

Hier das Modul:
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package Comp;

use strict qw( vars subs );
use warnings;

sub import
{
        my( $class, $file, $line ) = caller();

        #
        # comp { ... } ?VAR? => SUB, ...
        #
        my $comp;
        $comp = sub (&;@) {
                my( $sub, $var, $list, @x ) = @_;

                if ( my $r = ref($var) )
                {
                        if ( $r eq 'CODE' )
                        {
                                push @x, $list;
                                $list = $var;
                                $var  = undef;
                        } # if
                        elsif ( $r ne 'SCALAR' )
                        {
                                die
"Neither a SCALAR nor a CODE reference in comp() in file '$file' at line $line.\n";
                        } # elsif
                } # if
                else
                {
                        $var = \${$class.'::'.$var};
                } # else

                my @l;

                for ( $list->() )
                {
                        $$var = $_ if defined $var;
                        push @l, @x ? $comp->( $sub, @x ) : $sub->();
                } # for

                return @l;
        };

        #
        # lcomp { ... } ?VAR? => LAZYSUB, ...
        #
        my $lcomp;
        $lcomp = sub (&;@) {
                my( $sub, $var, $list, @x ) = @_;

                if ( my $r = ref($var) )
                {
                        if ( $r eq 'CODE' )
                        {
                                push @x, $list;
                                $list = $var;
                                $var  = undef;
                        } # if
                        elsif ( $r ne 'SCALAR' )
                        {
                                die
"Neither a SCALAR nor a CODE reference in comp() in file '$file' at line $line.\n";
                        } # elsif
                } # if
                else
                {
                        $var = \${$class.'::'.$var};
                } # else

                while ( defined( my $elem = $list->() ) )
                {
                        $$var = $elem if defined $var;

                        my($res) = @x ? $lcomp->( $sub, @x ) : $sub->();
                        return $res if defined $res;
                } # for

                return undef;
        };

        #
        # lazy { ... } START
        #
        my $lazy = sub (&$) {
                my( $sub, $val ) = @_;

                my $start = $val;

                return sub{
                        my($res) = $sub->(\$val);
                        $val = $start if ! defined $res;
                        return $res;
                };
        };

        *{$class.'::comp' } = $comp ;
        *{$class.'::lcomp'} = $lcomp;
        *{$class.'::lazy' } = $lazy ;
} # import

1;

__END__

Falls man die Werte der Listen bei comp() / lcomp() in Variablen speichern möchte, kann man jetzt anstatt eines Strings eine Skalar-Referenz übergeben, in die geschrieben wird.
Ein String ist immer noch möglich, dann wird die jeweilige package-Variable verändert.

edit: Die Fehlermeldung der beiden die()s in die nächste Zeile geschoben.

MfG
perl -E'*==*",s;;%ENV=~m,..$,,$&+42;e,$==f;$"++for+ab..an;@"=qw,u t,,print+chr;sub f{split}say"@{=} me"'

View full thread Pythagorische Tripel