aboutsummaryrefslogtreecommitdiff
path: root/challenge-195
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2022-12-19 05:11:06 +0000
committerGitHub <noreply@github.com>2022-12-19 05:11:06 +0000
commita44799ab84e6d4f55ec9264dd450e981ceccecf6 (patch)
tree95c87f35200a85330d34f2ca0c2849b3fc373155 /challenge-195
parent8268ff0e6843410c0aea9065a93f1e42fd7a41d4 (diff)
parent3dc894d3448f1562f2f134e90b742720859b924c (diff)
downloadperlweeklychallenge-club-a44799ab84e6d4f55ec9264dd450e981ceccecf6.tar.gz
perlweeklychallenge-club-a44799ab84e6d4f55ec9264dd450e981ceccecf6.tar.bz2
perlweeklychallenge-club-a44799ab84e6d4f55ec9264dd450e981ceccecf6.zip
Merge pull request #7273 from Util/branch-for-challenge-195
Add TWC 195 blog post and solutions by Bruce Gray
Diffstat (limited to 'challenge-195')
-rw-r--r--challenge-195/bruce-gray/blog.txt1
-rw-r--r--challenge-195/bruce-gray/perl/ch-1.pl30
-rw-r--r--challenge-195/bruce-gray/perl/ch-1_inline.pl45
-rw-r--r--challenge-195/bruce-gray/perl/ch-2.pl26
-rw-r--r--challenge-195/bruce-gray/raku/ch-1.raku88
-rw-r--r--challenge-195/bruce-gray/raku/ch-2.raku15
6 files changed, 205 insertions, 0 deletions
diff --git a/challenge-195/bruce-gray/blog.txt b/challenge-195/bruce-gray/blog.txt
new file mode 100644
index 0000000000..53d34f05c8
--- /dev/null
+++ b/challenge-195/bruce-gray/blog.txt
@@ -0,0 +1 @@
+https://blogs.perl.org/users/bruce_gray/2022/12/twc-195-special_speedy_frequency.html
diff --git a/challenge-195/bruce-gray/perl/ch-1.pl b/challenge-195/bruce-gray/perl/ch-1.pl
new file mode 100644
index 0000000000..a02c0b897a
--- /dev/null
+++ b/challenge-195/bruce-gray/perl/ch-1.pl
@@ -0,0 +1,30 @@
+use v5.36;
+use List::Util qw<uniq>;
+
+sub task1 ( $n ) {
+ return 0 + grep { length == uniq split '' } 1..$n;
+}
+
+
+my @tests = (
+ [ 15, 14 ],
+ [ 35, 32 ],
+
+ [ 99, 90 ],
+ [ 200, 162 ],
+ [ 180, 147 ],
+ [ 1_000, 738 ],
+ [ 10_000, 5_274 ],
+ [ 100_000, 32_490 ],
+ [ 1_000_000, 168_570 ],
+# [ 10_000_000, 712_890 ],
+# [ 100_000_000, 2_345_850 ],
+# [ 1_000_000_000, 5_611_770 ],
+# [ 9_876_543_210, 8_877_690 ],
+);
+use Test::More;
+plan tests => 0+@tests;
+for (@tests) {
+ my ($in, $expected) = @{$_};
+ is task1($in), $expected, "task1($in) == $expected";
+}
diff --git a/challenge-195/bruce-gray/perl/ch-1_inline.pl b/challenge-195/bruce-gray/perl/ch-1_inline.pl
new file mode 100644
index 0000000000..4ad91318f6
--- /dev/null
+++ b/challenge-195/bruce-gray/perl/ch-1_inline.pl
@@ -0,0 +1,45 @@
+use v5.36;
+use Inline 'C';
+my @tests = (
+ [ 15, 14 ],
+ [ 35, 32 ],
+
+ [ 99, 90 ],
+ [ 200, 162 ],
+ [ 180, 147 ],
+ [ 1_000, 738 ],
+ [ 10_000, 5_274 ],
+ [ 100_000, 32_490 ],
+ [ 1_000_000, 168_570 ],
+ [ 10_000_000, 712_890 ],
+ [ 100_000_000, 2_345_850 ],
+ [ 1_000_000_000, 5_611_770 ],
+ [ 9_876_543_210, 8_877_690 ],
+);
+use Test::More;
+plan tests => 0+@tests;
+for (@tests) {
+ my ($in, $expected) = @{$_};
+ is count_special($in), $expected, "count_special($in) == $expected";
+}
+__END__
+__C__
+int is_special(long x) {
+ int ds[10];
+ memset(ds, 0, 10*sizeof(int));
+ while (x) {
+ if (ds[x % 10]++)
+ return 0;
+ x /= 10;
+ }
+ return 1;
+}
+int count_special(long in) {
+ long x = in > 9876543210 ? 9876543210 : in;
+ int r = 0;
+ for ( ; x ; x-- ) {
+ if ( is_special(x) )
+ r++;
+ }
+ return r;
+}
diff --git a/challenge-195/bruce-gray/perl/ch-2.pl b/challenge-195/bruce-gray/perl/ch-2.pl
new file mode 100644
index 0000000000..23841e64ae
--- /dev/null
+++ b/challenge-195/bruce-gray/perl/ch-2.pl
@@ -0,0 +1,26 @@
+use v5.36;
+use List::Util qw<min>;
+use List::UtilsBy qw<max_by>;
+
+sub task2 (@ns) {
+ my %bag;
+ $bag{$_}++ for grep { $_ % 2 == 0 } @ns;
+ return -1 if not %bag;
+
+ return min max_by { $bag{$_} } keys %bag;
+}
+
+
+my @tests = (
+ [ [1,1,2,6,2], 2 ], # Of 2 and 6, 2 appears the most.
+ [ [1,3,5,7 ], -1 ], # No even numbers
+ [ [6,4,4,6,1], 4 ], # Of 4 and 6, both appear twice, so pick 4 (the smallest).
+
+ [ [2,4,4,6,6], 4 ], # Make sure min of evens does not impact min of max-group
+);
+use Test::More;
+plan tests => 0+@tests;
+for (@tests) {
+ my ($in, $expected) = @{$_};
+ is task2(@{$in}), $expected, "task2(@{$in}) == $expected";
+}
diff --git a/challenge-195/bruce-gray/raku/ch-1.raku b/challenge-195/bruce-gray/raku/ch-1.raku
new file mode 100644
index 0000000000..aa09d4398c
--- /dev/null
+++ b/challenge-195/bruce-gray/raku/ch-1.raku
@@ -0,0 +1,88 @@
+# https://oeis.org/A073531 Number of n-digit positive integers with all digits distinct.
+constant @n-digits-distinct = 0, 9, |( 9 X* [\*] (9...1) );
+constant @n-digits-distinct-sum = [\+] @n-digits-distinct;
+
+# See blog post for explanation.
+sub task1 ( UInt $n --> UInt ) {
+ constant MAX = 9_876_543_210;
+ return &?ROUTINE(MAX) if $n > MAX;
+
+ # Knuth's "falling powers"; kfp(9,3) == 9*8*7
+ sub kfp ($n, $k) { [*] ( ($n-$k) ^.. $n ) }
+
+ my $nc = $n.chars;
+ my @totals;
+
+ push @totals, @n-digits-distinct-sum[$nc - 1];
+
+ my SetHash $used;
+ for $n.combĀ».Numeric.kv -> UInt $k, UInt $digit {
+
+ my UInt $combinations_in_rightward_places = kfp(9 - $k, $nc - $k - 1);
+
+ my Range $space_below_digit = ( 0 + (1 if $k == 0 ) )
+ .. ( $digit - (1 if $k < $nc-1) );
+
+ my Set $using_for_this_digit = $space_below_digit (-) $used;
+
+ push @totals, $using_for_this_digit.elems
+ * $combinations_in_rightward_places;
+
+ $used{$digit}++;
+ }
+
+ return @totals.sum;
+}
+# This version is simpler to understand, but does not perform as well.
+# It does the initial optimization to skip over about .log10 places,
+# then generates all the combinations with the correct leading digit,
+# filters on which ones are less than $n.
+sub task1_one_big_skip ( UInt $n --> UInt ) {
+ constant MAX = 9_876_543_210;
+ return &?ROUTINE(MAX) if $n > MAX;
+
+ my @totals;
+ my $lead = $n.substr(0, 1);
+ my $core = $n.chars - 1;
+
+ push @totals, @n-digits-distinct-sum[$core];
+
+ push @totals, +combinations(9,$core) * ([*] 1..$core) * ($lead-1);
+
+ my $L3 = 0;
+ for (0..9).grep(* != $lead).combinations($core) -> @comb {
+ $L3 += +@comb.permutations.grep: { ($lead ~ .join) <= $n };
+ }
+ push @totals, $L3;
+ return @totals.sum;
+}
+
+
+my @tests =
+ ( 15, 14 ),
+ ( 35, 32 ),
+
+ ( 99, 90 ),
+ ( 200, 162 ),
+ ( 180, 147 ),
+ ( 1_000, 738 ),
+ ( 10_000, 5_274 ),
+ ( 100_000, 32_490 ),
+ ( 1_000_000, 168_570 ),
+ ( 10_000_000, 712_890 ),
+ ( 100_000_000, 2_345_850 ),
+ ( 1_000_000_000, 5_611_770 ),
+ ( 9_876_543_210, 8_877_690 ),
+;
+use Test;
+plan 1+@tests;
+
+is (map &task1, 1..99),
+ (flat (1..10,10..20,20..30,30..40,40..50,50..60,60..70,70..80,80..90,90)),
+ "First 99";
+
+for @tests -> ($in, $expected) {
+ my $got = task1($in);
+
+ is $got, $expected, "task1($in) == $expected";
+}
diff --git a/challenge-195/bruce-gray/raku/ch-2.raku b/challenge-195/bruce-gray/raku/ch-2.raku
new file mode 100644
index 0000000000..d38fca4107
--- /dev/null
+++ b/challenge-195/bruce-gray/raku/ch-2.raku
@@ -0,0 +1,15 @@
+sub task2 (@ns) { @ns.grep( * %% 2 ).Bag.max({ .value, -.key }).?key // -1 }
+
+
+my @tests =
+ ( (1,1,2,6,2), 2 ), # Of 2 and 6, 2 appears the most.
+ ( (1,3,5,7 ), -1 ), # No even numbers
+ ( (6,4,4,6,1), 4 ), # Of 4 and 6, both appear twice, so pick 4 (the smallest).
+
+ ( (2,4,4,6,6), 4 ), # Make sure min of evens does not impact min of max-group
+;
+use Test;
+plan +@tests;
+for @tests -> ($in, $expected) {
+ is task2($in), $expected, "task2($in) == $expected";
+}