aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Ferrari <fluca1978@gmail.com>2021-04-07 08:52:15 +0200
committerLuca Ferrari <fluca1978@gmail.com>2021-04-07 08:52:15 +0200
commit7d791436a75ffe72df26e90b480f16a926872f5c (patch)
treee2f03a9adb8a26d4ea161ba7482d0df9c163a1cc
parent51f9a6405288ffa575e73bf4b8cd0997d92ba1f9 (diff)
downloadperlweeklychallenge-club-7d791436a75ffe72df26e90b480f16a926872f5c.tar.gz
perlweeklychallenge-club-7d791436a75ffe72df26e90b480f16a926872f5c.tar.bz2
perlweeklychallenge-club-7d791436a75ffe72df26e90b480f16a926872f5c.zip
Task 1 done
-rw-r--r--challenge-107/luca-ferrari/raku/ch-1.p696
1 files changed, 96 insertions, 0 deletions
diff --git a/challenge-107/luca-ferrari/raku/ch-1.p6 b/challenge-107/luca-ferrari/raku/ch-1.p6
new file mode 100644
index 0000000000..7a0af37c98
--- /dev/null
+++ b/challenge-107/luca-ferrari/raku/ch-1.p6
@@ -0,0 +1,96 @@
+#!env perl6
+
+# see <https://perlweeklychallenge.org/blog/perl-weekly-challenge-107/>
+# Task 1: Descriptive Numbers
+# Write a script to generate Self-descriptive Numbers in a given base.
+
+# In mathematics, a self-descriptive number
+# is an integer m that in a given base b is b digits long
+# in which each digit d at position n (the most significant digit being at position 0 and the least significant at position b - 1) counts how many instances of digit n are in m.
+
+# For example, if the given base is 10, then script should print 6210001000.
+#
+# Invocation example:
+
+# % perl6 weekly-challenge/pwc_43_2.p6 --base=10
+# Starting generation for base 10
+# Batch between 6210001000 and 6219991000
+# Batch between 7210001000 and 7219991000
+# Batch between 8210001000 and 8219991000
+# Batch between 9210001000 and 9219991000
+
+# What did we generate?
+
+# [6210001000]
+
+# Bye bye!
+
+
+
+my $m = 6210001000;
+
+
+sub MAIN( :$base? where { (10,4,5,7,8,9,11,12,16,36).grep: $base } = 10 ){
+ say "Starting generation for base $base";
+
+ # I need to do something for other bases!
+ die "Not implemented!" if $base > 10;
+
+ if ( $base <= 5 ) {
+ my $end = ( $base - 1 ).Str x $base;
+ my @nums = grep { validate $_.Int, $base }, 0 .. $end.Int;
+ "\nWhat did we generate?\n".say;
+ for @nums {
+ .say
+ }
+ }
+ else {
+ # if the base is greater than 5 do a parallel scan
+
+ my @tasks;
+ for ( $base - 4 ) .. ( $base - 1 ) {
+ @tasks.push: Promise.start( {
+ # see <https://medium.com/@divyangrpatel/self-descriptive-number-best-algorithm-95b281e6de05>
+ my $start = '%d21%s1000'.sprintf: $_, '0' x ( $base - 4 - 3 ).Int;
+ my $end = '%d21%s1000'.sprintf: $_, ( $base - 1 ) x ( $base - 4 - 3 ).Int;
+ say "\tBatch between $start and $end";
+
+ my @nums = grep { validate $_.Int, $base }, $start .. $end;
+ } );
+ }
+
+ await @tasks;
+ "\nWhat did we generate?\n".say;
+ for @tasks {
+ .result.say if .result;
+ }
+
+ }
+
+ say "\nBye bye!";
+}
+
+
+# Splits the number into an array of single digits, so that the first element is
+# the most important digit of the number.
+# Then greps the digit in the whole array and counts how many times it appears.
+# If the digit appears the right number of times, the number is fine.
+sub validate( Int $number, Int $base ){
+ my @digits = $number.Str.split( '', :skip-empty );
+
+ # the number must have the same length
+ return False if @digits.elems != $base;
+
+ # the number must have at least one zero!
+ return False if ! @digits.grep: 0;
+
+ my $ok = True;
+ for @digits {
+ my $digit = $_;
+ my $position = $++;
+ $ok &&= @digits.grep( * == $position ).elems == $digit;
+ return False if ! $ok;
+ }
+
+ return True;
+}