diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2023-03-10 21:43:52 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-10 21:43:52 +0000 |
| commit | 2dfb0bc1a3779d88d7fc6fa881ba0187b1b3f38a (patch) | |
| tree | 45a52a7e31b030f485337f825868d8244ab00145 | |
| parent | f2e33c0038917ad43651d0c4e8b0bb310eaed541 (diff) | |
| parent | 7c25bd7c2f37595d67c2e37723a6aca650bc216f (diff) | |
| download | perlweeklychallenge-club-2dfb0bc1a3779d88d7fc6fa881ba0187b1b3f38a.tar.gz perlweeklychallenge-club-2dfb0bc1a3779d88d7fc6fa881ba0187b1b3f38a.tar.bz2 perlweeklychallenge-club-2dfb0bc1a3779d88d7fc6fa881ba0187b1b3f38a.zip | |
Merge pull request #7698 from boblied/master
Backlog week 176
| -rw-r--r-- | challenge-176/bob-lied/README | 4 | ||||
| -rw-r--r-- | challenge-176/bob-lied/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-176/bob-lied/perl/ch-1.pl | 73 | ||||
| -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 |
6 files changed, 261 insertions, 2 deletions
diff --git a/challenge-176/bob-lied/README b/challenge-176/bob-lied/README index c231e3a589..a6a80e8eea 100644 --- a/challenge-176/bob-lied/README +++ b/challenge-176/bob-lied/README @@ -1,3 +1,3 @@ -Solutions to weekly challenge 138 by Bob Lied +Solutions to weekly challenge 176 by Bob Lied -https://perlweeklychallenge.org/blog/perl-weekly-challenge-138/ +https://perlweeklychallenge.org/blog/perl-weekly-challenge-176/ diff --git a/challenge-176/bob-lied/blog.txt b/challenge-176/bob-lied/blog.txt new file mode 100644 index 0000000000..234f398ef6 --- /dev/null +++ b/challenge-176/bob-lied/blog.txt @@ -0,0 +1 @@ +https://dev.to/boblied/pwc-176-reversing-a-number-39gg diff --git a/challenge-176/bob-lied/perl/ch-1.pl b/challenge-176/bob-lied/perl/ch-1.pl new file mode 100644 index 0000000000..2c663c5d77 --- /dev/null +++ b/challenge-176/bob-lied/perl/ch-1.pl @@ -0,0 +1,73 @@ +#!/usr/bin/env perl +# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu: +#============================================================================= +# ch-1.pl Perl Weekly Challenge Week 176 Task 1 Permuted Multiples +#============================================================================= +# Copyright (c) 2023, Bob Lied +#============================================================================= +# Write a script to find the smallest positive integer x +# such that x, 2x, 3x, 4x, 5x and 6x are permuted multiples of each other. +# For example, the integers 125874 and 251748 are permutated multiples +# of each other as 251784 = 2 x 125874 +# and also both have the same digits but in different order. +# Output 142857 +#============================================================================= + +use v5.36; + +use builtin qw/true false/; +no warnings "experimental::builtin"; + +use List::Util qw/all/; + +use Getopt::Long; +my $DoTest = false; +my $DoAll = false; +my $Size = 6; + +GetOptions("test" => \$DoTest, "all" => \$DoAll, "size:i" => \$Size); +exit(!runTest()) if $DoTest; + +sub isPermutation($digits, $m) +{ + my @m = sort split("", $m); + return false if $#m != $#{$digits}; + return all { $digits->[$_] == $m[$_] } 0 .. $#m; +} + +say join(" ", smallestPermuted($Size, $DoAll)->@*); + +sub smallestPermuted($size = 6, $doAll = false) +{ + my @result; + MAG: for ( my $magnitude = 100 ; $magnitude <= 10**$size ; $magnitude *= 10 ) + { + my $max = int( $magnitude / 6 ); + my $base = int ( $max / 10 ); + for ( my $i = $base + 1 ; $i <= $base + $max ; $i++ ) + { + my @digits = sort split("", $i); + + if ( all { isPermutation(\@digits, $i * $_) } 2 .. 6 ) + { + push @result, $i; + last MAG unless $doAll; + } + } + } + return \@result; +} + +sub runTest +{ + use Test2::V0; + + is( smallestPermuted(2), [], "2 digits"); + is( smallestPermuted(3), [], "3 digits"); + is( smallestPermuted(4), [], "4 digits"); + is( smallestPermuted(5), [], "5 digits"); + is( smallestPermuted(6), [ 142857 ], "6 digits"); + + done_testing; +} + 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; +} + |
