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

Kombinationen und ihre Umkehrung

Leser: 2


<< >> 8 Einträge, 1 Seite
Linuxer
 2006-09-29 03:00
#70391 #70391
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Hallo zusammen,

ich habe da auch mal eine Frage/Aufgabe...

Zur Vorgeschichte und Erläuterung: Gegeben seien 3 Gruppen: Quelle (IP), Ziel (IP), Service (Port)

Nun kann man durch Verknüpfung jedes Elements einer Gruppe mit jedem Element einer anderen Gruppe eine Liste aller möglichen Verbindungen aufbauen:

Quelle x Ziel x Service = Liste

Bei 2 Quellen, 2 Zielen und 2 Services wäre das also eine Ergebnisliste von 2 x 2 x 2 = 8 Verbindungen.

Quote
Quelle: A, B
Ziel: 1, 2
Service: a, b

(A,B) x (1,2) x (a,b) =

A 1 a
A 1 b
A 2 a
A 2 b
B 1 a
B 1 b
B 2 a
B 2 b


Ich hoffe, soweit konnte ich mich verständlich machen. Nun zum eigentlichen Problem:

Ich habe mehrere Listen von Verbindungen (teilweise mehr als 100 Einzelverbindungen). Diese Listen würde ich gerne in einem Skript umwandeln in Gruppendefinitionen. Allerdings fehlt mir derzeit ein passender gedanklicher Ansatz, wie ich dieses Problem in einem Perl-Skript lösen könnte.
Ich bräuchte also Ansätze und Hinweise (oder Code), wie ich z.B. folgende Liste in Gruppen erfassen könnte:

Quote
A 1 a
A 1 b
A 2 a
A 2 b
B 1 a
B 1 b
B 2 a
B 2 b
C 3 c
D 4 d
D 5 d


Rauskommen müssten dann diese Gruppierungen (wenn ich um diese Uhrzeit keine gedankliche Fehlleistung vollbringe):

Quote
(A,B) x (1,2) x (a,b)
( C ) x ( 3 ) x ( c )
( D ) x (4,5) x ( d )


Ansätze, (dokumentierte) Code-Beispiele, Dokumentationshinweise würden mich freuen.

Hoffe mein Problem ist einigermaßen klar geworden. Danke im Voraus fürs Mitdenken ;o)

Linuxer

PS: Was mir gerade so in Gedanken vorschwebt:
- Gruppendefinitionen in HoA oder AoA? Wie füllen?
- evtl. pro Quelle / Ziel / Service ein eigener AoA;
\_ der Index stellt die Beziehung zwischen den drei Elementen her?
- oder ein HoHoH, um die Beziehungen zu definieren?
Code: (dl )
1
2
3
4
5
6
7
8
%hash = (
'quelle1' => {
'ziel1' => 'service1'
},
'quelle2' => {
'ziel2' => 'service2'
},
}

\_ Gruppendefinitionen müßten dann evtl. in HoH's liegen, damit die Namenszuordnungen erhalten bleiben...
- wie kann ich berücksichtigen, dass eine Gruppe in mehreren Regeln auftauchen kann?
\_ evtl. später bei den Gruppen auf Gleichheit prüfen und Beziehungen dann anpassen?
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!
docsnyder
 2006-09-29 12:40
#70392 #70392
User since
2005-09-08
300 Artikel
BenutzerIn
[Homepage] [default_avatar]
@Linuxer

Dein Problem ist verstanden, aber Du musst schon noch Hinweise geben, welche Grupierung-Methode anzuwenden ist. Um das zu verstehen, folgendes Beispiel:
Code: (dl )
1
2
3
4
A 1 a
A 2 b
B 2 b
B 3 c

Dies kann so
Code: (dl )
1
2
(A)x(1,2)x(a,b)
(B)x(2,3)x(b,c)

oder so
Code: (dl )
1
2
3
(A)x(1)x(a)
(B)x(3)x(c)
(A,B)x(2)x(b)

aufgedröselt werden. Nach welchen Kriterien soll Gruppiert werden? Wenn Du die Antwort auf diese Frage kennst, kannst Du daraus wahrscheinlich einen Algorithmus ableiten.

Gruß, Doc
Linuxer
 2006-09-29 13:13
#70393 #70393
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
[quote=docsnyder,29.09.2006, 10:40]
Code: (dl )
1
2
3
4
A 1 a
A 2 b
B 2 b
B 3 c

Dies kann so
Code: (dl )
1
2
(A)x(1,2)x(a,b)
(B)x(2,3)x(b,c)

oder so
Code: (dl )
1
2
3
(A)x(1)x(a)
(B)x(3)x(c)
(A,B)x(2)x(b)

aufgedröselt werden. Nach welchen Kriterien soll Gruppiert werden? Wenn Du die Antwort auf diese Frage kennst, kannst Du daraus wahrscheinlich einen Algorithmus ableiten.[/quote]
Hi,

die Gruppierung sollte originalgetreu erfolgen. Bei Deinem Beispiel wäre also die 2. Gruppenbildung das gewünschte Ergebnis.
Wenn man die Gruppen wieder zu einer Liste rekombiniert, soll die originale Liste wieder erscheinen, damit scheidet die erste Variante aus.

Hoffe, damit eine Antwort auf die Frage geliefert zu haben. Ich weiß grad nicht, wie ich das in gescheitere Worte fassen kann :o(

Danke && Gruß,
Linuxer
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!
docsnyder
 2006-09-29 13:44
#70394 #70394
User since
2005-09-08
300 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hi!

Mein Beispiel war doof, bzw. es drückt nicht die Mehrdeutigkeit aus, die ich meine.

Schaue Dir folgendes Beispiel an:
Code: (dl )
1
2
3
4
A 1 a
A 2 a
B 2 a
B 3 a

Das kannst Du so:
Code: (dl )
1
2
3
(A)x(1)x(a)
(B)x(3)x(a)
(A,B)x(2)x(a)

oder so
Code: (dl )
1
2
(A)x(1,2)x(a)
(B)x(2,3)x(a)

gruppieren. Welche Gruppierung würdest Du bevorzugen und warum?

Gruß, Doc
Linuxer
 2006-09-29 17:11
#70395 #70395
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
[quote=docsnyder,29.09.2006, 11:44]Hi!

Mein Beispiel war doof, bzw. es drückt nicht die Mehrdeutigkeit aus, die ich meine.

Schaue Dir folgendes Beispiel an:
Code: (dl )
1
2
3
4
A 1 a
A 2 a
B 2 a
B 3 a

Das kannst Du so:
Code: (dl )
1
2
3
(A)x(1)x(a)
(B)x(3)x(a)
(A,B)x(2)x(a)

oder so
Code: (dl )
1
2
(A)x(1,2)x(a)
(B)x(2,3)x(a)

gruppieren. Welche Gruppierung würdest Du bevorzugen und warum?

Gruß, Doc[/quote]
Hi,

hm, diese Variation ist mir bisher nicht in den Sinn gekommen ...

Wenn ich mir die beiden Varianten anschaue, dann bevorzuge ich die zweite.

meine Gründe für die 2. Variante:
- irgendwie scheint mir die Auftrennung der Quellen A und B schlüssiger und übersichtlicher
- Die Reihenfolge der Regeln ist durch die zweite Variante genau wiedergegeben (mag Zufall sein; Prio wäre für mich erstmal, überhaupt die Gruppenbildung und Zuordnung untereinander hinzubekommen)
- man hat nur 2 Gruppenbeziehungen im Ggs. zur ersten Variante

Dankend,
Linuxer
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!
topeg
 2006-09-30 00:56
#70396 #70396
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Ich habe mich mal was programmiert, das deinen Vorstellungen wohl recht nahe kommt. Etwas Dokumentiert ist es auch. :-)
Code: (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/perl
use strict;
use warnings;

######################################################
# Funktionen #
##############

# Liste einlesen
# Werte:
# > Name des ersten Eintrages
# > Name des zweiten Eintrages
# > Name des dritten Eintrages
# > Filehandle
# < gelesenen Liste
sub parse_liste($$$$)
{
my ($erst,$dann,$letzt,$fh)=@_;
my @liste=();

while(my $l=<$fh>)
{ push(@liste,{$erst=>[$1], $dann=>[$2], $letzt=>[$3]}) if($l=~/^([^\s]+)\s+(\d+)\s+([^\s]+)$/); }

return @liste;
}

# Einträge zusammenfassen
# Werte:
# > die Hashrefferenz
# > Name des Wertes, dessen Ihnalt zusammengefst werden soll
# < String, der die vereinte liste enthält.
sub myjoin($$)
{
my ($ref,$name)=@_;
# ich benutze hier den "Nullsring" als Trenner,
# da er normalerweise niemals in einem String vorkommt
return join("\000", @{$ref->{$name}});
}

# Werte vergelichen (als Aufruf aus "sort" heraus)
# Werte:
# > erste Hashreferenz
# > zweite Hashreferenz
# > Name des primären Sortierwertes
# > Name des sekundären Sortierwertes
# > Name des terziären Sortierwertes
sub vergleiche($$$$$)
{
my ($wa,$wb,$erst,$dann,$letzt)=@_;
if( myjoin($wa,$erst) eq myjoin($wb,$erst) )
{
return myjoin($wa,$letzt) cmp myjoin($wb,$letzt) if( myjoin($wa,$dann) eq myjoin($wb,$dann) );
return myjoin($wa,$dann) cmp myjoin($wb,$dann);
}
return myjoin($wa,$erst) cmp myjoin($wb,$erst);
}

# Liteneinträge zusammenfassen
# Werte:
# > Name des ersten Wertes der übereinstimmen muss
# > Name des zweiten Wertes der übereinstimmen muss
# > Name des Wertes der bei positiver Prüfung zusammengefasst wird
# < zusammengefasste Liste
sub komibiere($$$@)
{
my ($erst,$dann,$letzt,@liste)=@_;

# erstmal sortieren
@liste=sort{ vergleiche($a,$b,$erst,$dann,$letzt) }@liste;

# ein Eintrag kommt immer in die Ausgabeliste
my @liste_k=({ $erst => $liste[0]->{$erst}, $dann => $liste[0]->{$dann}, $letzt => $liste[0]->{$letzt} });
shift(@liste);

# Die Eingabeliste durcharbeiten
while(@liste)
{
my $eintrag=shift(@liste);
if(
myjoin($eintrag,$erst) eq myjoin($liste_k[-1],$erst) &&
myjoin($eintrag,$dann) eq myjoin($liste_k[-1],$dann)
)
{ push(@{$liste_k[-1]->{$letzt}},@{$eintrag->{$letzt}}); }
else
{ push(@liste_k,{ $erst=>$eintrag->{$erst}, $dann=>$eintrag->{$dann}, $letzt=>$eintrag->{$letzt} }); }
}
return @liste_k;
}

# Listeneinträge ausgeben
# Werte:
# > Name des ersten Eintrages
# > Name des zweiten Eintrages
# > Name des dritten Eintrages
sub my_print($$$@)
{
my ($erst,$dann,$letzt,@l)=@_;
print '/','#'x32,"\\\n";
printf("|%10s|%10s|%10s|\n",$erst,$dann,$letzt);
print '+','-'x10,'+','-'x10,'+','-'x10,"+\n";
for my $i (@l)
{
my $e= join(',',@{$i->{$erst}});
my $d= join(',',@{$i->{$dann}});
my $l= join(',',@{$i->{$letzt}});
printf("|%10s|%10s|%10s|\n",$e,$d,$l);
}
print '\\','#'x32,"/\n";
}

######################################################
# Programm #
############

my @l=parse_liste('quelle','port','ziel',*DATA);

print "Rohdaten\n";
my_print('quelle','port','ziel',@l);

print "\"Ports\" zusammengefasst\n";
@l=komibiere('quelle','ziel','port',@l);
my_print('quelle','port','ziel',@l);

print "\"Quellen\" zusammengefasst\n";
@l=komibiere('ziel','port','quelle',@l);
my_print('quelle','port','ziel',@l);

print "\"Ziele\" zusammengefasst\n";
@l=komibiere('quelle','port','ziel',@l);
my_print('quelle','port','ziel',@l);

exit(0);

######################################################
# DATAZEILEN #
##############
__DATA__
A 1 b
A 2 b
K 24 c
P 2 d
B 3 b
B 1 b
B 22 a
K 2 d
P 1 a
P 1 b
K 1 c
K 2 a
K 4 a
C 22 c
C 4 a
K 22 a
B 11 c
D 2 e
D 1 a
A 33 c
W 1 q
L 3 w
Z 11 q
W 11 q
Z 1 q
D 1 c
P 1 c


edit: Fehler behoben...\n\n

<!--EDIT|topeg|1159564090-->
Linuxer
 2006-10-02 17:51
#70397 #70397
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
[quote=topeg,29.09.2006, 22:56]Ich habe mich mal was programmiert, das deinen Vorstellungen wohl recht nahe kommt. Etwas Dokumentiert ist es auch. :-)[/quote]
Hi topeg,

ich danke Dir. Ich habe auf Basis Deines Skripts ein eigenes Skript erstellt. Lediglich der Aufbau und einige Kleinigkeiten sind verändert worden.
Je mehr ich damit mache, desto klarer wird mir, wie Deine Lösung arbeitet ;o))
Jetzt werde ich mich daran machen, die eigentlichen Daten aufzubereiten; damit ich Produktivdaten habe, die ich diesem Skript vorwerfen kann...
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!
topeg
 2006-10-02 23:19
#70398 #70398
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
hmm ja stimmt, ich hätte vielleicht dazu schreiben sollen was das Script eigendlich macht. :-)
Mal schnell zusammengefasst:
Ich sortiere die einträge nach den vorgebenen Haschnamen (besser gesagt nach deren einträgen.) in der Priorität absteigend. So kommen immer die Einträge in der Liste zusammen, die möglicherweise zusammenfassbar sind. Sind sie es fasse ich sie zusammen, ansonsten kommt der einzelne Eintrag in die Ausgabeliste.

Durch das zusammenfassen in "my_join" spare ich mir eine zusätzliche schleife zum überprüfen der einzelnen Einträge. Das funktioniert, da ich schon zu Anfang (wenn nur ein Wert in den HashListen sind) sortiere, dadurch kommen die Werte auch sortiert in die Hashlisten.

Na ich hoffe das war wenigstens einigermaßen verständlich...
<< >> 8 Einträge, 1 Seite



View all threads created 2006-09-29 03:00.