diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2022-01-09 23:18:15 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-09 23:18:15 +0000 |
| commit | dd278e41e5749fe5f5f0d22de0b6350de5e4ffd3 (patch) | |
| tree | 5afbf56c3ece65a9f276b6b356bc8594ed5d9a6e /challenge-146 | |
| parent | aff9e315410956e2759c80b0cc62e1ee0b26f9e1 (diff) | |
| parent | b54418611320f77166702bb730a64b90f502ef75 (diff) | |
| download | perlweeklychallenge-club-dd278e41e5749fe5f5f0d22de0b6350de5e4ffd3.tar.gz perlweeklychallenge-club-dd278e41e5749fe5f5f0d22de0b6350de5e4ffd3.tar.bz2 perlweeklychallenge-club-dd278e41e5749fe5f5f0d22de0b6350de5e4ffd3.zip | |
Merge pull request #5495 from Util/branch-for-challenge-146
Add Raku and Perl solutions for TWC 146 by Bruce Gray.
Diffstat (limited to 'challenge-146')
| -rw-r--r-- | challenge-146/bruce-gray/README | 32 | ||||
| -rw-r--r-- | challenge-146/bruce-gray/Test_data/ch-2_test_generator.raku | 129 | ||||
| -rw-r--r-- | challenge-146/bruce-gray/Test_data/ch-2_tests.txt | 247 | ||||
| -rw-r--r-- | challenge-146/bruce-gray/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-146/bruce-gray/perl/ch-1.pl | 3 | ||||
| -rwxr-xr-x | challenge-146/bruce-gray/perl/ch-2.pl | 47 | ||||
| -rwxr-xr-x | challenge-146/bruce-gray/perl/ch-2_via_module.pl | 44 | ||||
| -rw-r--r-- | challenge-146/bruce-gray/raku/ch-1.raku | 2 | ||||
| -rw-r--r-- | challenge-146/bruce-gray/raku/ch-2.raku | 31 |
9 files changed, 536 insertions, 0 deletions
diff --git a/challenge-146/bruce-gray/README b/challenge-146/bruce-gray/README index 5d0deab51b..6511220e4d 100644 --- a/challenge-146/bruce-gray/README +++ b/challenge-146/bruce-gray/README @@ -1 +1,33 @@ Solutions by Bruce Gray. + +For ch-2, the Perl and Raku programs can take rationals on the command-line for experimentation, +or will run their test suites if invoked without arguments. + +Sample runs: +$ perl perl/ch-1.pl + 104743 + +$ raku raku/ch-1.raku + 104743 + +$ perl perl/ch-2.pl 4817/5410 + 4817/5410 has CW parent,grandparent of: 4817/593,4224/593 + +$ raku raku/ch-2.raku 4817/5410 + (4817/593 4224/593) + +$ prove perl/ch-2.pl + perl/ch-2.pl .. ok + All tests successful. + Files=1, Tests=202, 0 wallclock secs ( 0.04 usr 0.01 sys + 0.09 cusr 0.01 csys = 0.15 CPU) + Result: PASS + +$ prove -e raku raku/ch-2.raku + raku/ch-2.raku .. ok + All tests successful. + Files=1, Tests=202, 3 wallclock secs ( 0.05 usr 0.00 sys + 2.72 cusr 0.13 csys = 2.90 CPU) + Result: PASS + +$ perl -MMath::PlanePath::RationalsTree -wE 'my $CW = Math::PlanePath::RationalsTree->new( tree_type => "CW" ); say join "/", $CW->n_to_xy( $CW->tree_n_parent( $CW->xy_to_n(@ARGV) ) );' 4817 5410 + 4817/593 + (Fleshed out in ch-2_via_module.pl) diff --git a/challenge-146/bruce-gray/Test_data/ch-2_test_generator.raku b/challenge-146/bruce-gray/Test_data/ch-2_test_generator.raku new file mode 100644 index 0000000000..89b5b526e5 --- /dev/null +++ b/challenge-146/bruce-gray/Test_data/ch-2_test_generator.raku @@ -0,0 +1,129 @@ +# Lots of utility subs and support for generating, navigating, and exploring the Calkin-Wilf tree. +# Also, code to generate (the beginnings of) ch-2_tests.txt + +# Generate each row by calculating both branches of each elements of the prior row. +sub next-Calkin-Wilf-row ( $prior_row ) { + return cache gather for $prior_row.list -> Rat $r { + my $sum = [+] $r.nude; + take $r.numerator / $sum; + take $sum / $r.denominator; + } +} +constant @CW-rows = (1/1,), &next-Calkin-Wilf-row ... *; + + +# Linear navigation to next neighbor on same row (or jumping row if at end). +sub next-Calkin-Wilf-neighbor ( Rat \x --> Rat ) { + my \n = x.floor; + my \y = x - n; + return 1/( n + 1 − y ); +} +constant @CW-linear = 1/1, &next-Calkin-Wilf-neighbor ... *; + + +subset LR-Str of Str where / ^ <[LR]>* $ /; +sub Calkin-Wilf-to-LR ( Rat $r --> LR-Str ) { + my @lineage = $r, &Calkin-Wilf-tree-parent …^ 1/1; + return @lineage.reverse.map({ <L R>[$_ > 1] }).join; +} + +sub LR-to-Calkin-Wilf ( LR-Str $LRs --> Rat ) { + my $r = 1/1; + for $LRs.comb -> $lr { + my $sum = $r.nude.sum; + + $r = ($lr eq 'L') ?? $r.numerator / $sum + !! ($lr eq 'R') ?? $sum / $r.denominator + !! die "Cannot happen" + ; + } + return $r; +} + +sub Calkin-Wilf-tree-parent ( Rat $r --> Rat ) { # Copied from ch-2.raku + my ( Int \n, Int \d ) = $r.nude; + my Int \diff = [-] $r.nude; + + return diff > 0 + ?? diff / d + !! n / -diff; +} + +# Formatter +sub f ( Rat $r ) { + my ($n, $d) = $r.nude; + return $n.fmt( '%20d') + ~ '/' ~ $d.fmt('%-20d'); +} + +sub make-test ( LR-Str $s1 ) { + my @a = $s1, + $s1.substr(0, *-1), + $s1.substr(0, *-2), + ; + + return @a.map({ f LR-to-Calkin-Wilf($_) }).join(" ") ~ ' # ' ~ $s1; +} + +sub make-single-bit-tests ( $size ) { + for <L R>, <R L> -> ($a, $b) { + for ^$size -> $X { + my $Y = $size - $X - 1; # One is for the single $b. + say make-test( ( $a x $X ) ~ $b ~ ( $a x $Y ) ); + } + } + say ''; +} + +sub make-tests-from-counts ( @counts ) { + for @counts -> ( $A, $B, $C ) { + for <L R>, <R L> -> ($a, $b) { + for <L R> -> $final { + say make-test( ( ( ( $a x $A ) ~ ( $b x $B ) ) ) x $C ~ $final ); + } + } + } + say ''; +} + +# For power=6, returns <64 0 1>, <32 32 1>, <16 16 2>, <8 8 4>, <4 4 8>, <2 2 16>, <1 1 32>; +sub make-counts-from-power ( Int $power ) { + my $size = 2 ** $power; + return gather { + take ($size, 0, 1); # Solid line of $size Ls or Rs. + for $power ^... 0 -> $p { + my $s = 2 ** $p; + take ( $s, $s, $size/$s/2 ); + } + } +} + +say @CW-linear.head(33)».nude».join('/'); + +say $_».nude».join("/") for @CW-rows.head(10); + + +if 1==1 { + for @CW-rows.skip(10).head.list { + say f($_), ' => ', Calkin-Wilf-to-LR($_); + } +} + +# say Calkin-Wilf-to-LR(273/290); +# say Calkin-Wilf-to-LR(21/10); # LLLLLLLLLRR +# say LR-from(21/10); # LLLLLLLLLRR +# say f LR-to-Calkin-Wilf('LLLLLLLLLRR'); # 21/10 + +if 1==0 { # Demonstrate the first N Left/Right navigations down the tree, as translations from Integer to LR then to CW. + for ^127 -> $n { + my LR-Str $LRs = ($n+1).base(2).trans( '0' => 'L', '1' => 'R' ).substr(1); + say "$LRs => ", f LR-to-Calkin-Wilf($LRs); + } +} + +make-tests-from-counts( make-counts-from-power(5) ); +make-tests-from-counts( map { ( $_, 0, 1 ) }, (63 .. 68) ); +make-tests-from-counts( map { ( $_, 0, 1 ) }, (1, {$_ * 10} … 10_000) ); +make-tests-from-counts( map { ( 1, 1, $_ ) }, (1, {$_ + 4} … 45) ); + +make-single-bit-tests(16); diff --git a/challenge-146/bruce-gray/Test_data/ch-2_tests.txt b/challenge-146/bruce-gray/Test_data/ch-2_tests.txt new file mode 100644 index 0000000000..961d9e5df6 --- /dev/null +++ b/challenge-146/bruce-gray/Test_data/ch-2_tests.txt @@ -0,0 +1,247 @@ +# Test data for Perl and Raku, "Curious Fraction Tree", https://theweeklychallenge.org/blog/perl-weekly-challenge-146/#TASK2 +# Format: \d+/\d+ \s+ \d+/\d+ \s+ \d+/\d+ +# where the first rational number is the input, and 2nd and 3rd are expected result of parent and grandparent +# (Comments allowed) +# Many lines also have an end-of-line comment describing the LR navigation and/or position within the row. + +# From task examples: +3/5 3/2 1/2 +4/3 1/3 1/2 + +# From task diagram, 3rd level: +1/3 1/2 1/1 +3/2 1/2 1/1 +2/3 2/1 1/1 +3/1 2/1 1/1 + +# From task diagram, 4th level: +1/4 1/3 1/2 +4/3 1/3 1/2 +3/5 3/2 1/2 +5/2 3/2 1/2 +2/5 2/3 2/1 +5/3 2/3 2/1 +3/4 3/1 2/1 +4/1 3/1 2/1 + +# From https://www.jasondavies.com/calkin-wilf-tree/ , left side: + 7/1 6/1 5/1 + 6/7 6/1 5/1 +11/6 5/6 5/1 + 5/11 5/6 5/1 +14/5 9/5 4/5 + 9/14 9/5 4/5 +13/9 4/9 4/5 + 4/13 4/9 4/5 +15/4 11/4 7/4 +11/15 11/4 7/4 +18/11 7/11 7/4 + 7/18 7/11 7/4 +17/7 10/7 3/7 +10/17 10/7 3/7 +13/10 3/10 3/7 + 3/13 3/10 3/7 +14/3 11/3 8/3 +11/14 11/3 8/3 +19/11 8/11 8/3 + 8/19 8/11 8/3 +21/8 13/8 5/8 +13/21 13/8 5/8 +18/13 5/13 5/8 + 5/18 5/13 5/8 +17/5 12/5 7/5 +12/17 12/5 7/5 +19/12 7/12 7/5 + 7/19 7/12 7/5 +16/7 9/7 2/7 + 9/16 9/7 2/7 +11/9 2/9 2/7 + 2/11 2/9 2/7 + +# From https://www.jasondavies.com/calkin-wilf-tree/ , right side: +11/2 9/2 7/2 + 9/11 9/2 7/2 +16/9 7/9 7/2 + 7/16 7/9 7/2 +19/7 12/7 5/7 +12/19 12/7 5/7 +17/12 5/12 5/7 + 5/17 5/12 5/7 +18/5 13/5 8/5 +13/18 13/5 8/5 +21/13 8/13 8/5 + 8/21 8/13 8/5 +19/8 11/8 3/8 +11/19 11/8 3/8 +14/11 3/11 3/8 + 3/14 3/11 3/8 +13/3 10/3 7/3 +10/13 10/3 7/3 +17/10 7/10 7/3 + 7/17 7/10 7/3 +18/7 11/7 4/7 +11/18 11/7 4/7 +15/11 4/11 4/7 + 4/15 4/11 4/7 +13/4 9/4 5/4 + 9/13 9/4 5/4 +14/9 5/9 5/4 + 5/14 5/9 5/4 +11/5 6/5 1/5 + 6/11 6/5 1/5 + 7/6 1/6 1/5 + 1/7 1/6 1/5 + +# +# Below here is all my own test data, generated via LR in Test_data/ch-2_test_generator.raku +# + +# Alternating long groups of L|R, with the length of the group shortening until group-size is 1. + 1/34 1/33 1/32 # LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL + 34/33 1/33 1/32 # LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLR + 33/34 33/1 32/1 # RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRL + 34/1 33/1 32/1 # RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR + + 273/290 273/17 256/17 # LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRL + 290/17 273/17 256/17 # LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRRR + 17/290 17/273 17/256 # RRRRRRRRRRRRRRRRLLLLLLLLLLLLLLLLL + 290/273 17/273 17/256 # RRRRRRRRRRRRRRRRLLLLLLLLLLLLLLLLR + + 4817/5410 4817/593 4224/593 # LLLLLLLLRRRRRRRRLLLLLLLLRRRRRRRRL + 5410/593 4817/593 4224/593 # LLLLLLLLRRRRRRRRLLLLLLLLRRRRRRRRR + 593/5410 593/4817 593/4224 # RRRRRRRRLLLLLLLLRRRRRRRRLLLLLLLLL + 5410/4817 593/4817 593/4224 # RRRRRRRRLLLLLLLLRRRRRRRRLLLLLLLLR + + 121393/150050 121393/28657 92736/28657 # LLLLRRRRLLLLRRRRLLLLRRRRLLLLRRRRL + 150050/28657 121393/28657 92736/28657 # LLLLRRRRLLLLRRRRLLLLRRRRLLLLRRRRR + 28657/150050 28657/121393 28657/92736 # RRRRLLLLRRRRLLLLRRRRLLLLRRRRLLLLL + 150050/121393 28657/121393 28657/92736 # RRRRLLLLRRRRLLLLRRRRLLLLRRRRLLLLR + +1607521/2273378 1607521/665857 941664/665857 # LLRRLLRRLLRRLLRRLLRRLLRRLLRRLLRRL +2273378/665857 1607521/665857 941664/665857 # LLRRLLRRLLRRLLRRLLRRLLRRLLRRLLRRR + 665857/2273378 665857/1607521 665857/941664 # RRLLRRLLRRLLRRLLRRLLRRLLRRLLRRLLL +2273378/1607521 665857/1607521 665857/941664 # RRLLRRLLRRLLRRLLRRLLRRLLRRLLRRLLR + +5702887/9227465 5702887/3524578 2178309/3524578 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL +9227465/3524578 5702887/3524578 2178309/3524578 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRR +3524578/9227465 3524578/5702887 3524578/2178309 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLL +9227465/5702887 3524578/5702887 3524578/2178309 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + + +# Left and Right edges of the tree, focused around the 64th level. +# This is the point that `ch-2_via_module.pl` (based on Math::PlanePath::RationalsTree) fails. +# Math::PlanePath::RationalsTree fails 18 of these 24 tests. +# My own CW algorithms in my Perl and Raku code pass all of these tests. + 1/65 1/64 1/63 # 'L' x 63, then L +65/64 1/64 1/63 # 'L' x 63, then R +64/65 64/1 63/1 # 'R' x 63, then L +65/1 64/1 63/1 # 'R' x 63, then R + 1/66 1/65 1/64 # 'L' x 64, then L +66/65 1/65 1/64 # 'L' x 64, then R +65/66 65/1 64/1 # 'R' x 64, then L +66/1 65/1 64/1 # 'R' x 64, then R + 1/67 1/66 1/65 # 'L' x 65, then L +67/66 1/66 1/65 # 'L' x 65, then R +66/67 66/1 65/1 # 'R' x 65, then L +67/1 66/1 65/1 # 'R' x 65, then R + 1/68 1/67 1/66 # 'L' x 66, then L +68/67 1/67 1/66 # 'L' x 66, then R +67/68 67/1 66/1 # 'R' x 66, then L +68/1 67/1 66/1 # 'R' x 66, then R + 1/69 1/68 1/67 # 'L' x 67, then L +69/68 1/68 1/67 # 'L' x 67, then R +68/69 68/1 67/1 # 'R' x 67, then L +69/1 68/1 67/1 # 'R' x 67, then R + 1/70 1/69 1/68 # 'L' x 68, then L +70/69 1/69 1/68 # 'L' x 68, then R +69/70 69/1 68/1 # 'R' x 68, then L +70/1 69/1 68/1 # 'R' x 68, then R + +# Left and Right edges of the tree, at exponential depths. + 1/3 1/2 1/1 # 'L' x 1, then L + 3/2 1/2 1/1 # 'L' x 1, then R + 2/3 2/1 1/1 # 'R' x 1, then L + 3/1 2/1 1/1 # 'R' x 1, then R + 1/12 1/11 1/10 # 'L' x 10, then L + 12/11 1/11 1/10 # 'L' x 10, then R + 11/12 11/1 10/1 # 'R' x 10, then L + 12/1 11/1 10/1 # 'R' x 10, then R + 1/102 1/101 1/100 # 'L' x 100, then L + 102/101 1/101 1/100 # 'L' x 100, then R + 101/102 101/1 100/1 # 'R' x 100, then L + 102/1 101/1 100/1 # 'R' x 100, then R + 1/1002 1/1001 1/1000 # 'L' x 1000, then L + 1002/1001 1/1001 1/1000 # 'L' x 1000, then R + 1001/1002 1001/1 1000/1 # 'R' x 1000, then L + 1002/1 1001/1 1000/1 # 'R' x 1000, then R + 1/10002 1/10001 1/10000 # 'L' x 10000, then L +10002/10001 1/10001 1/10000 # 'L' x 10000, then R +10001/10002 10001/1 10000/1 # 'R' x 10000, then L +10002/1 10001/1 10000/1 # 'R' x 10000, then R + + +# Alternating L and R produces approximations of the Golden Ratio φ (1.618033988749...), and its inverse|conjugate. +# https://en.wikipedia.org/wiki/Golden_ratio +# 90 levels is the deepest we can go, without Rat collapsing into Num (or needing FatRat). +# Of interest: these numbers are all ratios of successive Fibonacci numbers. +# e.g. F(92)/F(93) == 7540113804746346429/12200160415121876738 ~~ 1.618033988749... + 3/5 3/2 1/2 # LRL + 5/3 2/3 2/1 # RLR + 144/233 144/89 55/89 # LRLRLRLRLRL + 233/144 89/144 89/55 # RLRLRLRLRLR + 6765/10946 6765/4181 2584/4181 # LRLRLRLRLRLRLRLRLRL + 10946/6765 4181/6765 4181/2584 # RLRLRLRLRLRLRLRLRLR + 317811/514229 317811/196418 121393/196418 # LRLRLRLRLRLRLRLRLRLRLRLRLRL + 514229/317811 196418/317811 196418/121393 # RLRLRLRLRLRLRLRLRLRLRLRLRLR + 14930352/24157817 14930352/9227465 5702887/9227465 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL + 24157817/14930352 9227465/14930352 9227465/5702887 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + 701408733/1134903170 701408733/433494437 267914296/433494437 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL + 1134903170/701408733 433494437/701408733 433494437/267914296 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + 32951280099/53316291173 32951280099/20365011074 12586269025/20365011074 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL + 53316291173/32951280099 20365011074/32951280099 20365011074/12586269025 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + 1548008755920/2504730781961 1548008755920/956722026041 591286729879/956722026041 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL + 2504730781961/1548008755920 956722026041/1548008755920 956722026041/591286729879 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + 72723460248141/117669030460994 72723460248141/44945570212853 27777890035288/44945570212853 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL + 117669030460994/72723460248141 44945570212853/72723460248141 44945570212853/27777890035288 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + 3416454622906707/5527939700884757 3416454622906707/2111485077978050 1304969544928657/2111485077978050 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL + 5527939700884757/3416454622906707 2111485077978050/3416454622906707 2111485077978050/1304969544928657 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + 160500643816367088/259695496911122585 160500643816367088/99194853094755497 61305790721611591/99194853094755497 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL + 259695496911122585/160500643816367088 99194853094755497/160500643816367088 99194853094755497/61305790721611591 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + 7540113804746346429/12200160415121876738 7540113804746346429/4660046610375530309 2880067194370816120/4660046610375530309 # LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL +12200160415121876738/7540113804746346429 4660046610375530309/7540113804746346429 4660046610375530309/2880067194370816120 # RLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR + + +# Single-bit set (or unset) produce the sequence 2,3,4...(size+1) as we slide the position of the bit: + 2/31 2/29 2/27 # RLLLLLLLLLLLLLLL position = 32768 + 3/44 3/41 3/38 # LRLLLLLLLLLLLLLL position = 16384 + 4/55 4/51 4/47 # LLRLLLLLLLLLLLLL position = 8192 + 5/64 5/59 5/54 # LLLRLLLLLLLLLLLL position = 4096 + 6/71 6/65 6/59 # LLLLRLLLLLLLLLLL position = 2048 + 7/76 7/69 7/62 # LLLLLRLLLLLLLLLL position = 1024 + 8/79 8/71 8/63 # LLLLLLRLLLLLLLLL position = 512 + 9/80 9/71 9/62 # LLLLLLLRLLLLLLLL position = 256 +10/79 10/69 10/59 # LLLLLLLLRLLLLLLL position = 128 +11/76 11/65 11/54 # LLLLLLLLLRLLLLLL position = 64 +12/71 12/59 12/47 # LLLLLLLLLLRLLLLL position = 32 +13/64 13/51 13/38 # LLLLLLLLLLLRLLLL position = 16 +14/55 14/41 14/27 # LLLLLLLLLLLLRLLL position = 8 +15/44 15/29 15/14 # LLLLLLLLLLLLLRLL position = 4 +16/31 16/15 1/15 # LLLLLLLLLLLLLLRL position = 2 +17/16 1/16 1/15 # LLLLLLLLLLLLLLLR position = 1 + +31/2 29/2 27/2 # LRRRRRRRRRRRRRRR position = 65535 - 32768 +44/3 41/3 38/3 # RLRRRRRRRRRRRRRR position = 65535 - 16384 +55/4 51/4 47/4 # RRLRRRRRRRRRRRRR position = 65535 - 8192 +64/5 59/5 54/5 # RRRLRRRRRRRRRRRR position = 65535 - 4096 +71/6 65/6 59/6 # RRRRLRRRRRRRRRRR position = 65535 - 2048 +76/7 69/7 62/7 # RRRRRLRRRRRRRRRR position = 65535 - 1024 +79/8 71/8 63/8 # RRRRRRLRRRRRRRRR position = 65535 - 512 +80/9 71/9 62/9 # RRRRRRRLRRRRRRRR position = 65535 - 256 +79/10 69/10 59/10 # RRRRRRRRLRRRRRRR position = 65535 - 128 +76/11 65/11 54/11 # RRRRRRRRRLRRRRRR position = 65535 - 64 +71/12 59/12 47/12 # RRRRRRRRRRLRRRRR position = 65535 - 32 +64/13 51/13 38/13 # RRRRRRRRRRRLRRRR position = 65535 - 16 +55/14 41/14 27/14 # RRRRRRRRRRRRLRRR position = 65535 - 8 +44/15 29/15 14/15 # RRRRRRRRRRRRRLRR position = 65535 - 4 +31/16 15/16 15/1 # RRRRRRRRRRRRRRLR position = 65535 - 2 +16/17 16/1 15/1 # RRRRRRRRRRRRRRRL position = 65535 - 1 diff --git a/challenge-146/bruce-gray/blog.txt b/challenge-146/bruce-gray/blog.txt new file mode 100644 index 0000000000..cc72368b42 --- /dev/null +++ b/challenge-146/bruce-gray/blog.txt @@ -0,0 +1 @@ +http://blogs.perl.org/users/bruce_gray/2022/01/twc-146-ten-k-prime-and-cw-trees.html diff --git a/challenge-146/bruce-gray/perl/ch-1.pl b/challenge-146/bruce-gray/perl/ch-1.pl new file mode 100755 index 0000000000..7797503bf5 --- /dev/null +++ b/challenge-146/bruce-gray/perl/ch-1.pl @@ -0,0 +1,3 @@ +use Modern::Perl; +use ntheory qw<nth_prime>; +say nth_prime(10_001); diff --git a/challenge-146/bruce-gray/perl/ch-2.pl b/challenge-146/bruce-gray/perl/ch-2.pl new file mode 100755 index 0000000000..f2e99f9b20 --- /dev/null +++ b/challenge-146/bruce-gray/perl/ch-2.pl @@ -0,0 +1,47 @@ +#!/usr/bin/env perl +use Modern::Perl; +use experimental qw<signatures>; +use File::Slurp; +use Test::More; + +sub task2 ( $s ) { + $s =~ m{ \A (\d+) / (\d+) \z }msx + or die; + my $parent = Calkin_Wilf_tree_parent([$1,$2]); + my $grand = Calkin_Wilf_tree_parent($parent); + + return map { $_->[0] . '/' . $_->[1] } $parent, $grand; +} +sub Calkin_Wilf_tree_parent ( $aref ) { + die if @{$aref} != 2; + my ( $numer, $denom ) = @{$aref}; + + my $diff = $numer - $denom; + + return $diff > 0 ? [ $diff , $denom ] + : [ $numer , -$diff ]; +} + + +sub run_test_suite ( ) { + my @tests = map { /\S/ ? [split] : () } + map { s{ \s* \# .* $ }{}msxr } + read_file './Test_data/ch-2_tests.txt'; + + plan tests => 0+@tests; + + for (@tests) { + die if @{$_} != 3; + my ( $in, $exp1, $exp2 ) = @{$_}; + my ( $got1, $got2 ) = task2($in); + + is_deeply [$got1, $got2], [$exp1, $exp2], "task2($in) == $exp1, $exp2"; + } +} + +if (@ARGV) { + say "$_ has CW parent,grandparent : ", join ',', task2($_) for @ARGV; +} +else { + run_test_suite(); +} diff --git a/challenge-146/bruce-gray/perl/ch-2_via_module.pl b/challenge-146/bruce-gray/perl/ch-2_via_module.pl new file mode 100755 index 0000000000..61fd738a91 --- /dev/null +++ b/challenge-146/bruce-gray/perl/ch-2_via_module.pl @@ -0,0 +1,44 @@ +#!/usr/bin/env perl +use Modern::Perl; +use experimental qw<signatures>; +use File::Slurp; +use Test::More; + +use Math::PlanePath::RationalsTree; +use constant CW => Math::PlanePath::RationalsTree->new( tree_type => 'CW' ); +# Note: Due to the use of `n` in the ::RationalsTree module (position vs navigation), +# this version of the code is only reliable below level 64 of the tree on 64-bit Perl. +# On my machine, this code fails 36 of the 202 tests. +sub task2 ( $s ) { + $s =~ m{ \A (\d+) / (\d+) \z }msx + or die; + + my $parent = CW->tree_n_parent( CW->xy_to_n($1, $2) ); + my $grand = CW->tree_n_parent( $parent ); + + return map { join "/", CW->n_to_xy($_) } $parent, $grand; +} + +# Below here is identical to this section of ch-2.pl +sub run_test_suite ( ) { + my @tests = map { /\S/ ? [split] : () } + map { s{ \s* \# .* $ }{}msxr } + read_file './Test_data/ch-2_tests.txt'; + + plan tests => 0+@tests; + + for (@tests) { + die if @{$_} != 3; + my ( $in, $exp1, $exp2 ) = @{$_}; + my ( $got1, $got2 ) = task2($in); + + is_deeply [$got1, $got2], [$exp1, $exp2], "task2($in) == $exp1, $exp2"; + } +} + +if (@ARGV) { + say "$_ has CW parent,grandparent : ", join ',', task2($_) for @ARGV; +} +else { + run_test_suite(); +} diff --git a/challenge-146/bruce-gray/raku/ch-1.raku b/challenge-146/bruce-gray/raku/ch-1.raku new file mode 100644 index 0000000000..62320de60f --- /dev/null +++ b/challenge-146/bruce-gray/raku/ch-1.raku @@ -0,0 +1,2 @@ +constant @primes = (2, 3, 5, 7 … *).grep(&is-prime); +say @primes.skip(10_000).head; diff --git a/challenge-146/bruce-gray/raku/ch-2.raku b/challenge-146/bruce-gray/raku/ch-2.raku new file mode 100644 index 0000000000..715498a3fa --- /dev/null +++ b/challenge-146/bruce-gray/raku/ch-2.raku @@ -0,0 +1,31 @@ +sub task2 ( Str $s where /^\d+\/\d+$/ ) { + + my Rat $r = [/] $s.split('/'); + + my @lineage = $r, &Calkin-Wilf-tree-parent ^… 1/1; + + return @lineage.head(2).map( *.nude.join('/') ); +} +sub Calkin-Wilf-tree-parent ( Rat $r --> Rat ) { + my ( Int \n, Int \d ) = $r.nude; + my Int \diff = [-] $r.nude; + + return diff > 0 + ?? diff / d + !! n / -diff; +} + +sub run-test-suite ( ) { + constant $comment_re = / \s* '#' .* $ /; + my @tests = './Test_data/ch-2_tests.txt'.IO.lines».subst($comment_re).map({ .words if /\S/ }); + + use Test; + plan +@tests; + for @tests -> ( Str $in, Str $exp1, Str $exp2 ) { + my ( Str $got1, Str $got2 ) = task2($in); + + is-deeply ($got1, $got2), ($exp1, $exp2), "task2($in) == $exp1, $exp2"; + } +} +multi sub MAIN ( Rat $rational_number ) { say task2($rational_number) } +multi sub MAIN ( ) { run-test-suite() } |
