Schrift
[thread]12313[/thread]

(Verständnis)Probleme mit verschachtelten foreach-Schleifen und If-Abfragen

Leser: 1


<< |< 1 2 >| >> 12 Einträge, 2 Seiten
Wurzel
 2008-08-07 19:28
#113205 #113205
User since
2008-08-07
3 Artikel
BenutzerIn
[default_avatar]
Guten Abend

Ich verzweifle ... :( Ich versuche mit Perl (5.8.8 -> Cygwin unter WinXP) ein kleines Skript zu basteln, das mir Buchstabenkombinationen erstellt, gleichzeitig aber bestimmte "nicht erlaubte" rausfiltert. Ich bin der Lösung ziemlich nahe, denn das Skript gibt mir genau diese "nicht erlaubten Kombis" aus, mehr jedoch leider nicht :(

Die beiden "Kommentar"zeilen innerhalb der Schleife können als Ersatz für die einzeilige IF-Abfrage herhalten. Das Resultat ist genau das gleiche. Ach ja, und es spielt auch keine Rolle, ob ich in den geschweiften Klammern next stehen habe oder nicht.

Die IF-Abfrage in Zeile 20 funktioniert wie sie soll. Nur beim "Rest" hätte ich es gerne, dass genau das Umgekehrte rauskommt.

Wenn ich mich nicht verrechnet habe müssten es 348 erlaubte Kombinationen werden.

Mir ist klar, warum ich bei diesem Skript eben dieses Resultat erhalte, aber ich sehe absolut nicht, wie ich das Resultat erhalte, das ich eigentlich will ....

Hat mir jemand einen Tip wo mein Denkfehler liegen könnte?

Besten Dank und einen schönen Abend
Marc


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
#!/usr/bin/perl -w

@konsonants = ( "p", "b", "t", "d", "k", "g", "m", "n", "f", "v", "h", "ch", "l", "r", "s", "sch", "ts", "ds", "tsch", "dsch", "x" ); #21
@not_first = ( "p", "b", "t", "d", "k", "g" ); #6
@not_second = ( "p", "b", "t", "d", "k", "g", "m", "n", "ts", "ds", "tsch", "dsch", "x" ); #13

$j = 0;
$konso1 = 0;
$konso2 = 0;

$len_not_first = @not_first;
$len_not_second = @not_second;

# CC

foreach $konso1 (@konsonants)
{
        foreach $konso2 (@konsonants)
        {
                if ($konso1 eq $konso2) { next }
                
                for ($i = 0; $i < $len_not_first; $i++)
                {
                        for ($y = 0; $y < $len_not_second; $y++)
                        {
                                if ($konso1.$konso2 ne $not_first[$i].$not_second[$y]) { next }
#                               if ($konso1 ne $not_first[$i]) { }
#                               elsif ($konso2 ne $not_second[$y]) { }
                                else
                                {
                                        print $konso1.$konso2."\n";
                                        $j++;
                                }
                        }
                }
        }
}
                                
        print $j;
        print "\n";
Linuxer
 2008-08-07 21:17
#113213 #113213
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Du brauchst keine eigene for-Schleife, um die Arrays der verbotenen Werte zu durchwandern.
Ein einfaches grep sollte reichen, um zu kontrollieren, ob der aktuelle Wert einem "verbotenen" Wert entspricht.

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
#!/usr/bin/perl -w
use strict;

my @konsonants = qw( p b t d k g m n f v h ch l r s sch ts ds tsch dsch x ); #21
my @not_first  = qw( p b t d k g ); #6
my @not_second = qw( p b t d k g m n ts ds tsch dsch x ); #13


foreach my $konso1 (@konsonants) {

    next if ( grep { $konso1 eq $_ } @not_first );

    foreach my $konso2 (@konsonants) {

        next if ( $konso1 eq $konso2 );
        
        next if ( grep { $konso2 eq $_ } @not_second );

        print $konso1, $konso2, $/;
    }
}
    
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!
Wurzel
 2008-08-08 13:24
#113234 #113234
User since
2008-08-07
3 Artikel
BenutzerIn
[default_avatar]
Erstmal vielen Dank für die Antwort. Sie zeigte mir Möglichkeiten auf und schubste mich in die richtige Richtung.

Das endgültige Resultat sieht zwar ein kleines bisschen anders aus, aber ohne die Hilfe hier wäre ich wohl noch ewig im Dunkeln getappt :) Sehr schön.

Ach ja, hier das Resultat

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
#!/usr/bin/perl -w
use strict;

my @konsonants = qw( p b t d k g m n f v h ch l r s sch ts ds tsch dsch x ); #21
my @not_first  = qw( p b t d k g ); #6
my @not_second = qw( p b t d k g m n ts ds tsch dsch x ); #13

my $j = 0;

foreach my $konso1 (@konsonants)
{
    foreach my $konso2 (@konsonants)
        {
                next if ( $konso1 eq $konso2 );
                if ( grep { $konso1 eq $_ } @not_first )
                {
                        next if ( grep { $konso2 eq $_ } @not_second );
                }
        print $konso1, $konso2, $/;
                $j++;
    }
}

print $j;


Der Zähler dient lediglich der Ueberprüfung, ob die Anzahl der erzeugten Kombinationen auch der errechneten Anzahl an Möglichkeiten entspricht.

Mein Problem war, dass ich nicht wusste, wie ich die beiden if-Abfragen kombinieren konnte. Durch das Wegfallen der for-Schleifen wars auf einmal ziemlich einfach. Super! Danke.

LGW
bloonix
 2008-08-08 15:43
#113240 #113240
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Linuxer+2008-08-07 19:17:32--
Code (perl): (dl )
        print $konso1, $konso2, $/;

$/ hier zu verwenden halte ich für ziemlich schmutzig!
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
Linuxer
 2008-08-08 16:10
#113241 #113241
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
bloonix+2008-08-08 13:43:54--
Linuxer+2008-08-07 19:17:32--
Code (perl): (dl )
        print $konso1, $konso2, $/;

$/ hier zu verwenden halte ich für ziemlich schmutzig!

Steht Dir frei. Aber erwarte von mir nicht, dass ich mir davon was annehme, wenn Du mir keine Erklärung dazu lieferst.

[edit]umformuliert[/edit]
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!
Wurzel
 2008-08-08 17:56
#113244 #113244
User since
2008-08-07
3 Artikel
BenutzerIn
[default_avatar]
Wofür steht $/ ? ich habe nichts dazu gefunden. Vermute aber, dass es eine Art Ersatz für "\n" ist. Macht es noch was anderes? Ich meine ausser zwei Zeichen kürzer zu sein.

Ich gehe mal davon aus, dass sich Linuxer was dabei gedacht hat, oder? In diesem Zusammenhang (und weil ich was lernen will) interessiert mich das schon.

Den Umgang mit $_ habe ich noch nicht ganz begriffen, aber das werde ich wohl noch häufig antreffen, es gibt also Hoffnung für mich.

Manche Fragen mögen euch etwas naiv erscheinen. Ich bin kein totaler Programmierneuling, aber mit Perl kenne ich mich so gut wie gar nicht aus.

Danke trotzdem und im Voraus für Hilfe und Antworten.

LGW
murphy
 2008-08-08 18:10
#113246 #113246
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Linuxer+2008-08-08 14:10:38--
bloonix+2008-08-08 13:43:54--
Linuxer+2008-08-07 19:17:32--
Code (perl): (dl )
        print $konso1, $konso2, $/;

$/ hier zu verwenden halte ich für ziemlich schmutzig!

Steht Dir frei. Aber erwarte von mir nicht, dass ich mir davon was annehme, wenn Du mir keine Erklärung dazu lieferst.


Ich finde es zwar nicht schmutzig, aber auch nicht sonderlich elegant. $/ ist der Eingabedatensatztrenner. Wenn man ein immer gleiches Trennzeichen zwischen Ausgabedaten haben will, gibt's dafür ja $\:
Code (perl): (dl )
1
2
3
4
local $\ = $/; # ausserhalb der Schleifen
[...]

print $konso1, $konso2; # $\ wird automatisch am Ende angehängt
When C++ is your hammer, every problem looks like your thumb.
Linuxer
 2008-08-08 18:12
#113247 #113247
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Schau Dich mal in perldoc perlvar um, da sollte $/ erklärt werden ($INPUT_RECORD_SEPARATOR ).

Möglicherweise meinte bloonix, ich hätte eher $\ setzen sollen. Aber das ist mal nur geraten; mehr ist nicht drin...
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!
MatthiasW
 2008-08-08 18:12
#113248 #113248
User since
2008-01-27
367 Artikel
BenutzerIn
[default_avatar]
perlvar
Quote
$/

The input record separator, newline by default. This influences Perl's idea of what a "line" is. Works like awk's RS variable, including treating empty lines as a terminator if set to the null string. (An empty line cannot contain any spaces or tabs.) You may set it to a multi-character string to match a multi-character terminator, or to undef to read through the end of file. Setting it to "\n\n" means something slightly different than setting to "" , if the file contains consecutive empty lines. Setting to "" will treat two or more consecutive empty lines as a single empty line. Setting to "\n\n" will blindly assume that the next input character belongs to the next paragraph, even if it's a newline. (Mnemonic: / delimits line boundaries when quoting poetry.)
...
Setting $/ to a reference to an integer, scalar containing an integer, or scalar that's convertible to an integer will attempt to read records instead of lines, with the maximum record size being the referenced integer.

MfG
perl -E'*==*",s;;%ENV=~m,..$,,$&+42;e,$==f;$"++for+ab..an;@"=qw,u t,,print+chr;sub f{split}say"@{=} me"'
bloonix
 2008-08-08 19:13
#113252 #113252
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Mit "schmutzig" meine ich die Verwendung einer globalen Variable
in der Hoffnung, dass drin steht, was man sich erhofft ;)

Mir ist ein "\n" oder eine 'local $/="\n"' um einiges lieber,
aber das bleibt jedem selbst überlassen ;)
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
<< |< 1 2 >| >> 12 Einträge, 2 Seiten



View all threads created 2008-08-07 19:28.