diff options
| author | boblied <boblied@gmail.com> | 2023-03-08 14:07:02 -0600 |
|---|---|---|
| committer | boblied <boblied@gmail.com> | 2023-03-08 18:40:41 -0600 |
| commit | 470aa2b0e5065127df081d457a017d3c992fb8b6 (patch) | |
| tree | 5ad6dcdea1a4d7b1f4102fe55e972faecb0a1746 | |
| parent | 39222b30c78b2727fa5786ed3205fdf50ee758b1 (diff) | |
| download | perlweeklychallenge-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.pl | 55 | ||||
| -rw-r--r-- | challenge-176/bob-lied/perl/rev.c | 61 | ||||
| -rw-r--r-- | challenge-176/bob-lied/perl/rev.pl | 69 |
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; +} + |
