Lösung zu Blatt 4 --- Software Engineering Praxis (SS 2002)
Was mag ich denn?
#!/usr/local/bin/perl -w
use strict;
sub vq {
my $res = 0;
return 0 if scalar(@_) == 0;
foreach (@_) {
$res += $_;
}
return $res / scalar(@_);
}
sub p {
my ($user, $film, $votes) = @_;
my ($k, $sum, $w) = (0, 0, 0);
while (my ($cuser, $cvotes) = each %{$votes}) { # Alle Stimmen
next unless defined $cvotes->{$film}; # Film bewertet?
$w = w($user, $cuser, $votes);
$k += abs($w);
$sum += $w * ($cvotes->{$film} - vq(values %{$cvotes}));
}
return 0 if $k == 0;
return vq(values %{$votes->{$user}}) + $sum / $k;
}
sub w { # Pearson
my ($user, $cuser, $votes) = @_;
my $vq1 = vq(values %{$votes->{$user}});
my $vq2 = vq(values %{$votes->{$cuser}});
my $votes1 = $votes->{$user};
my $votes2 = $votes->{$cuser};
return 0 unless ($vq1 and $vq2);
my ($num, $denum1, $denum2) = (0, 0, 0);
foreach my $films (keys %{$votes1}) {
next unless defined $votes2->{$films};
$num += ($votes1->{$films} - $vq1) * ($votes2->{$films} - $vq2);
$denum1 += ($votes1->{$films} - $vq1) ** 2;
$denum2 += ($votes2->{$films} - $vq2) ** 2;
}
return 0 if ($denum1 * $denum2) == 0;
return $num * ($denum1 * $denum2) ** (-0.5);
}
sub readvotes {
my ($file) = @_;
open(FH, "$file") or die "Cannot open $file\n";
my %user = ();
while (<FH>) {
chomp;
my ($name, $film, $vote) = split /\|/;
$user{$name}->{$film} = $vote;
}
close FH;
return \%user;
}
my $filename = "/www/turing/htdocs/sai/ss02/sep/votes";
my $votes = readvotes($filename);
my $login = shift || "melzer";
print p("melzer", 'Psycho (1960)', $votes), "\n";
print p("borchert", 'Casablanca (1942)((aka Casablanca (1942)))', $votes), "\n";
foreach my $film (<>) {
chomp $film;
print "$film: ", p($login, $film, $votes), "\n";
}
Ingo Melzer, 10. Mai 2002