aboutsummaryrefslogtreecommitdiff
path: root/challenge-070/sgreen
diff options
context:
space:
mode:
authorSimon Green <mail@simon.green>2020-07-20 15:05:03 +1000
committerSimon Green <mail@simon.green>2020-07-20 15:05:03 +1000
commit8cef174a65b89e1e2a3d844cea7d7b51abe123a1 (patch)
tree65d24f7a4d8521715b3682e91dc4f740eff01ca5 /challenge-070/sgreen
parent18a47cdd093ec8335cc7faa919f2f63c20e31ac3 (diff)
downloadperlweeklychallenge-club-8cef174a65b89e1e2a3d844cea7d7b51abe123a1.tar.gz
perlweeklychallenge-club-8cef174a65b89e1e2a3d844cea7d7b51abe123a1.tar.bz2
perlweeklychallenge-club-8cef174a65b89e1e2a3d844cea7d7b51abe123a1.zip
PWC 070 by Simon Green
Diffstat (limited to 'challenge-070/sgreen')
-rw-r--r--challenge-070/sgreen/README.md45
-rw-r--r--challenge-070/sgreen/blog.txt1
-rwxr-xr-xchallenge-070/sgreen/perl/ch-1.pl28
-rwxr-xr-xchallenge-070/sgreen/perl/ch-2.pl26
4 files changed, 71 insertions, 29 deletions
diff --git a/challenge-070/sgreen/README.md b/challenge-070/sgreen/README.md
index a4a45d0687..0f43e97b94 100644
--- a/challenge-070/sgreen/README.md
+++ b/challenge-070/sgreen/README.md
@@ -1,40 +1,27 @@
-Solution by Simon Green
-# Perl Weekly Challenge 069
+# Perl Weekly Challenge 070
-## TASK #1 › Strobogrammatic Number
+Solution by Simon Green.
-This is a lot harder than it looks. My first thought is to just do a foreach loop between `$a` and `$b` and add it to the list if the number is strobogrammatic. However when I ran
+
+## TASK #1 › Character Swapping
- perl -E '$b = 0; foreach my $a (0 .. 10**10) { $b++ } say $b;'
+For this I used the fact that `($a, $b) = ($b, a)` does what it should. Therefore it was a simple exercise of doing this for `$C` times, and then display the output.
-on my PC, that took nearly 3 minutes. With $b being up to 10<sup>15</sup> this was not a feasible approach. Even if I only had all the numbers between 1 and 10<sup>15</sup> containing only the digits 0, 6, 8, 9 that was still going to be in the billions.
+The task states that `$C + $O <= $O`. This however is not possible. When `$C + $O = $N`, you will get a `substr outside of string` error. For this reason, I've only allowed `$C + $O < $N` to be valid.
-So I took a different approach. I calculated the first half of all valid numbers, and then generated the second half. The logic is pretty simple. The first digit must be 6, 8 or 9 (as 0 isn't valid as a first digit). If the number of digits is odd, the middle number can only be 0 or 8.
+### Example
-Taking this approach, I can generate all 49,150 strobogrammatic numbers between 1 and 10<sup>15</sup> in less than half a second.
+ » ./ch-1.pl perlandraku 3 4
+ pndraerlaku
-### Examples
- » ./ch-1.pl 50 100
- 69 88 96
+ » perl/ch-1.pl helloworld 8 1
+ hlloworlde
- » ./ch-1.pl 50 900
- 69 88 96 609 689 808 888
+## TASK 2 › Gray Code Sequence
-## TASK #2 › 0/1 String
+Not really much to say about this task, as it is string forward. Given that `$N` can not be greater than five, I simply stored the array in memory. Even at 24 bits, it will run without any issues.
-After the first task, these seemed a lot easier. But it wasn't entirely straight forward. I thought I had a bug in my code when it was spewing out digits on my screen. It turns out that is expected. The length of a number is twice the length of a previous number plus one. This meant the expected length was:
+## Example
- 1st 1
- 2nd 3
- 3rd 7
- 4th 15
- 5th 31
- 10th 1,023
- 15th 32,767
- 20th 1,048,575
- 25th 33,554,431
- 30th 1,073,741,823
-
-No wonder the task was changed from 1,000 iterations to 30! It goes without saying I'm not posting an example here, as the final line is 1,073,741,823 characters long.
-
-Thankfully perl has a built in [reverse](https://perldoc.pl/functions/reverse) operator which does what you expect to do on a scalar (string). For the switch I used `tr/01/10/` which [translates](https://perldoc.pl/perlop#tr/SEARCHLIST/REPLACEMENTLIST/cdsr) the zeros to one and visa versa. \ No newline at end of file
+ » ./ch-2.pl 4
+ 0 1 3 2 6 7 5 4 12 13 15 14 10 11 9 8
diff --git a/challenge-070/sgreen/blog.txt b/challenge-070/sgreen/blog.txt
new file mode 100644
index 0000000000..35640c6242
--- /dev/null
+++ b/challenge-070/sgreen/blog.txt
@@ -0,0 +1 @@
+https://github.com/manwar/perlweeklychallenge-club/blob/master/challenge-070/sgreen/README.md
diff --git a/challenge-070/sgreen/perl/ch-1.pl b/challenge-070/sgreen/perl/ch-1.pl
new file mode 100755
index 0000000000..6af3741c93
--- /dev/null
+++ b/challenge-070/sgreen/perl/ch-1.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use 5.10.1;
+
+sub main (@) {
+ my ( $string, $count, $offset ) = @_;
+
+ # Sanity checks
+ my $length = length $string;
+ die "A string must be supplied\n" unless $string;
+ die "The count must be a postive integer\n"
+ unless $count =~ /^[0-9]+$/ and $count >= 1;
+ die "The offset must be a postive integer\n"
+ unless $offset =~ /^[0-9]+$/ and $offset >= 1;
+ die "The count + offset must be less than the length of the string\n"
+ unless $count + $offset < $length;
+
+ for my $i ( 1 .. $count ) {
+ ( substr( $string, $i, 1 ), substr( $string, $i + $offset, 1 ) ) =
+ ( substr( $string, $i + $offset, 1 ), substr( $string, $i, 1 ) );
+ }
+
+ say $string;
+}
+
+main(@ARGV);
diff --git a/challenge-070/sgreen/perl/ch-2.pl b/challenge-070/sgreen/perl/ch-2.pl
new file mode 100755
index 0000000000..381699e096
--- /dev/null
+++ b/challenge-070/sgreen/perl/ch-2.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use 5.10.1;
+
+sub main (@) {
+ my ($bits) = @_;
+
+ # Sanity check
+ die "Bits must be a postive integer between 2 and 5"
+ unless $bits =~ /^[2-5]$/;
+
+ # Seed the array
+ my @values = (0);
+
+ # Double the array for each required bit
+ for my $bit ( 1 .. $bits ) {
+ my $half = 2**( $bit - 1 );
+ push @values, reverse map { $half + $_ } @values;
+ }
+
+ say join ' ', @values;
+}
+
+main(@ARGV);