-
Notifications
You must be signed in to change notification settings - Fork 325
/
Copy pathch-1.pl
executable file
·91 lines (80 loc) · 2.67 KB
/
ch-1.pl
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
#!/usr/bin/perl
use warnings;
use strict;
use experimental 'signatures';
sub first_unique_character_regex ($s) {
local $_ = $s;
s/\Q$1//g while /(.).*\1/g;
return length ? index $s, substr $_, 0, 1 : -1;
}
use List::Util qw{ min };
sub first_unique_character_hash ($s) {
my %pos;
my $i = 0;
my %is_unique;
for my $ch (split //, $s) {
$is_unique{$ch} = ! exists $pos{$ch};
$pos{$ch} = $i++;
}
return min(@pos{ grep $is_unique{$_}, keys %pos }) // -1
}
use Hash::Ordered;
sub first_unique_character_ho ($s) {
my $unique = 'Hash::Ordered'->new;
my %seen;
my @chars = split //, $s;
for my $i (0 .. $#chars) {
my $ch = $chars[$i];
if ($seen{$ch}++) {
$unique->delete($ch);
} else {
$unique->set($ch, $i);
}
}
return $unique->shift // -1
}
use Tie::Hash::Indexed;
sub first_unique_character_thi ($s) {
my $unique = 'Tie::Hash::Indexed'->new;
my %seen;
my @chars = split //, $s;
for my $i (0 .. $#chars) {
my $ch = $chars[$i];
if ($seen{$ch}++) {
$unique->delete($ch);
} else {
$unique->set($ch, $i);
}
}
return $unique->shift // -1
}
use Test::More tests => 15;
my @EXPECT = (
['Perl Weekly Challenge', 0, 'Example 1'],
['Long Live Perl', 1, 'Example 2'],
['ABCDDCBA', -1, 'Everything repeats'],
);
for my $e (@EXPECT) {
my ($input, $output, $name) = @$e;
is first_unique_character_hash($input), $output, $name;
is first_unique_character_regex($input), $output, $name;
is first_unique_character_ho($input), $output, $name;
is first_unique_character_thi($input), $output, $name;
}
use Benchmark qw{ cmpthese };
my $s = join "", map chr(65 + rand 26), 1 .. 100;
is first_unique_character_hash($s), first_unique_character_regex($s), $s;
is first_unique_character_hash($s), first_unique_character_ho($s), $s;
is first_unique_character_hash($s), first_unique_character_thi($s), $s;
cmpthese(-3, {
regex => sub { first_unique_character_regex($s) },
hash => sub { first_unique_character_hash($s) },
hash_ordered => sub { first_unique_character_ho($s) },
tie_hash_indexed => sub { first_unique_character_thi($s) },
});
__END__
Rate hash_ordered regex tie_hash_indexed hash
hash_ordered 8857/s -- -20% -54% -68%
regex 11094/s 25% -- -43% -60%
tie_hash_indexed 19303/s 118% 74% -- -30%
hash 27491/s 210% 148% 42% --