aboutsummaryrefslogtreecommitdiff
path: root/challenge-022
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2019-08-25 23:06:11 +0100
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2019-08-25 23:06:11 +0100
commit21827844f817625f2bb0fe969fccd047be1cef90 (patch)
treeddb37fa9eda36b469587d35568f4a2da9e60eb89 /challenge-022
parentbe4d089986233ecdc9119a0a08c4553e56ed31b2 (diff)
downloadperlweeklychallenge-club-21827844f817625f2bb0fe969fccd047be1cef90.tar.gz
perlweeklychallenge-club-21827844f817625f2bb0fe969fccd047be1cef90.tar.bz2
perlweeklychallenge-club-21827844f817625f2bb0fe969fccd047be1cef90.zip
- Added solutions by Guillermo Ramos.
Diffstat (limited to 'challenge-022')
-rw-r--r--challenge-022/guillermo-ramos/perl5/ch-1.pl34
-rw-r--r--challenge-022/guillermo-ramos/perl5/ch-2.pl139
2 files changed, 173 insertions, 0 deletions
diff --git a/challenge-022/guillermo-ramos/perl5/ch-1.pl b/challenge-022/guillermo-ramos/perl5/ch-1.pl
new file mode 100644
index 0000000000..f6b2de4b1d
--- /dev/null
+++ b/challenge-022/guillermo-ramos/perl5/ch-1.pl
@@ -0,0 +1,34 @@
+#!/usr/bin/env perl
+#
+# Write a script to print first 10 Sexy Prime Pairs. Sexy primes are prime
+# numbers that differ from each other by 6. For example, the numbers 5 and 11
+# are both sexy primes, because 11 - 5 = 6. The term “sexy prime” is a pun
+# stemming from the Latin word for six: sex. For more information, please
+# checkout wiki page.
+#
+# (https://en.wikipedia.org/wiki/Sexy_prime).
+################################################################################
+
+use strict;
+use warnings;
+
+use List::Util qw<any>;
+
+my $MAX_SEXY = 10;
+
+my @primes = ();
+my @sexy;
+my $p = 2;
+
+while (@sexy < $MAX_SEXY*2) {
+ unless (any { $p % $_ == 0 } @primes) {
+ push @primes, $p;
+ push @sexy, $primes[-2], $primes[-1]
+ if @primes > 1 && $primes[-1] == $primes[-2] + 6;
+ }
+ $p++;
+}
+
+foreach my $i (0 .. @sexy/2-1) {
+ printf "%s-%s\n", $sexy[$i*2], $sexy[$i*2+1];
+}
diff --git a/challenge-022/guillermo-ramos/perl5/ch-2.pl b/challenge-022/guillermo-ramos/perl5/ch-2.pl
new file mode 100644
index 0000000000..22a49d87dd
--- /dev/null
+++ b/challenge-022/guillermo-ramos/perl5/ch-2.pl
@@ -0,0 +1,139 @@
+#!/usr/bin/env perl
+#
+# Write a script to implement Lempel–Ziv–Welch (LZW) compression algorithm. The
+# script should have method to encode/decode algorithm. The wiki page explains
+# the compression algorithm very nicely.
+#
+# (https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch).
+################################################################################
+
+use strict;
+use warnings;
+
+################################################################################
+# Naïve implementation of a bidirectional map
+my $MAX_BIT_WIDTH = 12;
+sub bimap_new {
+ return {binwidth=>0, sym2bin=>{}, bin2sym=>{}};
+}
+sub bimap_extend {
+ my ($dict, $binwidth) = @_;
+ return unless $binwidth > $dict->{binwidth} && $binwidth <= $MAX_BIT_WIDTH;
+ my ($sym2bin, $bin2sym) = @$dict{'sym2bin', 'bin2sym'};
+ foreach my $sym (keys %$sym2bin) {
+ my $bin = $sym2bin->{$sym};
+ delete $bin2sym->{$bin};
+ $bin = "0" x ($binwidth - length $bin) . $bin;
+ $sym2bin->{$sym} = $bin;
+ $bin2sym->{$bin} = $sym;
+ }
+ $dict->{binwidth} = $binwidth;
+}
+sub bimap_insert {
+ my ($dict, $sym) = @_;
+ my ($sym2bin, $bin2sym) = @$dict{'sym2bin', 'bin2sym'};
+ return $dict->{sym2bin}{$sym} if exists $dict->{sym2bin}{$sym};
+ my $ord = keys %{$dict->{sym2bin}}; # Ordinal of symbol to insert in decimal
+ my $bin = sprintf "%b", $ord; # ... and in binary (string of 1/0s)
+ return unless length $bin <= $MAX_BIT_WIDTH;
+ $sym2bin->{$sym} = $bin; # Update symbol -> binary mapping
+ $bin2sym->{$bin} = $sym; # Update binary -> symbol mapping
+
+ # Extend with left zeroes the previously inserted binaries
+ bimap_extend($dict, length($bin));
+
+ return $bin;
+}
+
+
+################################################################################
+# Default dictionary
+my $DEFAULT_DICT = bimap_new();
+my $STOP = '';
+bimap_insert($DEFAULT_DICT, $_) foreach (map(chr, 1..254), $STOP);
+
+sub binary_encode {
+ my $text = shift;
+ my $binary = pack("B*", $text);
+ return $binary;
+}
+
+sub binary_decode {
+ my $binary = shift;
+ my $text = unpack("B*", $binary);
+ return $text
+}
+
+sub lzw_encode {
+ my $dict = shift;
+ my $input = shift;
+ my ($sym2bin, $bin2sym) = @{$dict}{'sym2bin', 'bin2sym'};
+
+ my $out = '';
+ my $w = '';
+ foreach my $i (0 .. length($input)-1) {
+ my $char = substr($input, $i, 1);
+ my $dict_seq = $w . $char;
+ unless (exists $sym2bin->{$dict_seq}) {
+ $out .= $sym2bin->{$w};
+ bimap_insert($dict, $dict_seq);
+ $w = '';
+ }
+ $w .= $char;
+ }
+ $out .= $sym2bin->{$w} . $sym2bin->{$STOP};
+ return binary_encode($out);
+}
+
+sub lzw_decode {
+ my $dict = shift;
+ my $input = binary_decode(shift());
+ my ($sym2bin, $bin2sym) = @{$dict}{'sym2bin', 'bin2sym'};
+
+ my $out = '';
+ my $lastsym;
+ while ($input) {
+ my $sym;
+ foreach my $bin (keys %$bin2sym) {
+ if ($input =~ /^$bin/) {
+ $sym = $bin2sym->{$bin};
+ $input = substr($input, $dict->{binwidth});
+ last;
+ }
+ }
+ unless (defined $sym) {
+ $sym = $lastsym . substr($lastsym, 0, 1);
+ $input = substr($input, $dict->{binwidth});
+ }
+ $out .= $sym;
+ if ($sym eq $STOP) {
+ return $out;
+ }
+ return $out if $sym eq $STOP;
+ if (defined $lastsym) {
+ my $bin = bimap_insert($dict, $lastsym . $sym);
+ if ((log($dict->{binwidth}) / log(2)) =~ /^\d+$/) {
+ bimap_extend($dict, $dict->{binwidth}+1);
+ }
+ }
+ $lastsym = $sym;
+ }
+}
+
+sub usage {
+ die "Usage: $0 -e | --encode | -d | --decode\n";
+}
+my $mode = shift || usage;
+if ($mode eq '-e' || $mode eq '--encode') {
+ my $input = join "", <>;
+ my $out = lzw_encode($DEFAULT_DICT, $input);
+ my $comprate = 100 * length($out) / length($input);
+ printf STDERR "Compressed to %.2f%% of original size\n", $comprate;
+ print $out;
+} elsif ($mode eq '-d' || $mode eq '--decode') {
+ my $input = join "", <>;
+ my $out = lzw_decode($DEFAULT_DICT, $input);
+ print $out;
+} else {
+ usage;
+}