aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorboblied <boblied@gmail.com>2023-03-08 14:07:02 -0600
committerboblied <boblied@gmail.com>2023-03-08 18:40:41 -0600
commit470aa2b0e5065127df081d457a017d3c992fb8b6 (patch)
tree5ad6dcdea1a4d7b1f4102fe55e972faecb0a1746
parent39222b30c78b2727fa5786ed3205fdf50ee758b1 (diff)
downloadperlweeklychallenge-club-470aa2b0e5065127df081d457a017d3c992fb8b6.tar.gz
perlweeklychallenge-club-470aa2b0e5065127df081d457a017d3c992fb8b6.tar.bz2
perlweeklychallenge-club-470aa2b0e5065127df081d457a017d3c992fb8b6.zip
Week 176 task 2
-rw-r--r--challenge-176/bob-lied/perl/ch-2.pl55
-rw-r--r--challenge-176/bob-lied/perl/rev.c61
-rw-r--r--challenge-176/bob-lied/perl/rev.pl69
3 files changed, 185 insertions, 0 deletions
diff --git a/challenge-176/bob-lied/perl/ch-2.pl b/challenge-176/bob-lied/perl/ch-2.pl
new file mode 100644
index 0000000000..d59aabaeb0
--- /dev/null
+++ b/challenge-176/bob-lied/perl/ch-2.pl
@@ -0,0 +1,55 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# ch-2.pl Perl Weekly Challenge Task 2 Reversible Numbers
+#=============================================================================
+# Copyright (c) 2023, Bob Lied
+#=============================================================================
+# Write a script to find out all Reversible Numbers below 100.
+# A number is said to be a reversible if sum of the number and its
+# reverse had only odd digits.
+# For example,
+# 36 is reversible number as 36 + 63 = 99 i.e. all digits are odd.
+# 17 is not reversible as 17 + 71 = 88, none of the digits are odd.
+#=============================================================================
+
+use v5.36;
+
+use builtin qw/true false/;
+no warnings "experimental::builtin";
+
+# To be an odd number, it has to be the sum of an even and an odd number.
+# We're considering only two-digit numbers, so that means if the first digit
+# is odd, the second must be even, and vice versa. Generate the possibilities.
+my @candidate = ( glob("{1,3,5,7,9}{0,2,4,6,8}"), glob("{2,4,6,8}{1,3,5,7,9}") );
+
+say join ",", sort { $a <=> $b }
+ grep { $_ < 100 && allOdd($_ + revNum($_)) } @candidate;
+
+# There are two fairly obvious ways of reversing the number. We can treat
+# it as a string and reverse the digits, or we can do the math. The string
+# operations are actually faster.
+sub revNum($n)
+{
+ (my $r = reverse("$n")) =~ s/^0+//;
+ return +($r);
+}
+
+# Checking that all digits are odd. Again, two possibilities: do the math
+# one digit at a time, or treat as a string and test each digit.
+sub allOdd($n)
+{
+ my $isOdd = true; # Doesn't handle 0, but 0 is not happening here.
+ while ( $n && $isOdd )
+ {
+ $isOdd &&= ( $n % 10 ) % 2;
+ $n = int($n / 10);
+ }
+ return $isOdd;
+}
+
+sub allOdd_str($n)
+{
+ use List::Util qw/all/;
+ return all { $_ % 2 } split("", $n);
+}
diff --git a/challenge-176/bob-lied/perl/rev.c b/challenge-176/bob-lied/perl/rev.c
new file mode 100644
index 0000000000..0dff0ea4fb
--- /dev/null
+++ b/challenge-176/bob-lied/perl/rev.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <time.h>
+
+void reverse(char s[])
+{
+ int i, j;
+ char c;
+
+ for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
+ c = s[i];
+ s[i] = s[j];
+ s[j] = c;
+ }
+}
+
+int rev1(int n)
+{
+ int r = n % 10;
+ while ( (n = n / 10) != 0 )
+ {
+ r = r*10 + n % 10;
+ }
+ return r;
+}
+
+int rev2(int n)
+{
+ char s[16];
+ sprintf(s, "%d", n);
+ reverse(s);
+ return ( atoi(s) );
+}
+
+int main(int argc, char **argv)
+{
+ int r;
+
+ const int start = 123400000;
+ const int end = 123500000;
+
+ clock_t begin = clock();
+ for ( int n = start; n <= end; n++ )
+ {
+ r = rev1(n);
+ }
+ clock_t finish = clock();
+ double t = (double)(finish - begin) / CLOCKS_PER_SEC;
+ printf("rev numeric %d %f\n", r, t);
+
+ begin = clock();
+ for ( int n = start; n <= end; n++ )
+ {
+ r = rev2(n);
+ }
+ finish = clock();
+ t = (double)(finish - begin) / CLOCKS_PER_SEC;
+ printf("rev string %d %f\n", r, t);
+}
diff --git a/challenge-176/bob-lied/perl/rev.pl b/challenge-176/bob-lied/perl/rev.pl
new file mode 100644
index 0000000000..349c96cd1a
--- /dev/null
+++ b/challenge-176/bob-lied/perl/rev.pl
@@ -0,0 +1,69 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# rev.pl
+#=============================================================================
+# Copyright (c) 2023, Bob Lied
+#=============================================================================
+# We need to reverse a number (e.g, 632 -> 236). Which is faster: doing
+# the math, or treating it as a string?
+#=============================================================================
+
+use v5.36;
+
+use Benchmark qw/cmpthese/;
+
+use Getopt::Long;
+my $DoBenchmark = 0;
+my $DoTest = 0;
+
+GetOptions("test" => \$DoTest, "benchmark" => \$DoBenchmark);
+
+if ( $DoBenchmark )
+{
+ cmpthese(-5, {
+ numeric => sub {
+ rev1($_) for 123400 .. 124500;
+ },
+ string => sub {
+ rev2($_) for 123400 .. 124500;
+ },
+ }
+ );
+}
+exit(!runTest()) if $DoTest;
+
+sub rev1($n)
+{
+ use integer;
+ my $r = $n % 10;
+ while ( $n = int($n/10) )
+ {
+ $r = ($r * 10) + ($n % 10);
+ }
+ return $r;
+}
+
+sub rev2($n)
+{
+ (my $r = reverse("$n")) =~ s/^0+//;
+ return $r;
+}
+
+sub runTest
+{
+ use Test2::V0;
+
+ is( rev1( 2), 2, "Test 1");
+ is( rev1( 20), 2, "Test 2");
+ is( rev1(632), 236, "Test 3");
+ is( rev1(495632), 236594, "Test 6");
+
+ is( rev2( 2), 2, "Test 1");
+ is( rev2( 20), 2, "Test 2");
+ is( rev2(632), 236, "Test 3");
+ is( rev2(495632), 236594, "Test 6");
+
+ done_testing;
+}
+