aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Proctor <simon.proctor@zoopla.co.uk>2020-04-15 14:15:05 +0100
committerSimon Proctor <simon.proctor@zoopla.co.uk>2020-04-15 14:15:05 +0100
commit09354a370b75d7fc91c86d6b40b94866f9797569 (patch)
tree95e38243fa6fd73f30ba92af7a6b05c0a2a03a0f
parentf9af7643c2d12b53f0f8a11ed189c38e739dda00 (diff)
downloadperlweeklychallenge-club-09354a370b75d7fc91c86d6b40b94866f9797569.tar.gz
perlweeklychallenge-club-09354a370b75d7fc91c86d6b40b94866f9797569.tar.bz2
perlweeklychallenge-club-09354a370b75d7fc91c86d6b40b94866f9797569.zip
A bit OTT and it doen't pretty print but it's kinda cool and does the job
-rw-r--r--challenge-056/simon-proctor/raku/ch-2.p6130
1 files changed, 130 insertions, 0 deletions
diff --git a/challenge-056/simon-proctor/raku/ch-2.p6 b/challenge-056/simon-proctor/raku/ch-2.p6
new file mode 100644
index 0000000000..29475428b1
--- /dev/null
+++ b/challenge-056/simon-proctor/raku/ch-2.p6
@@ -0,0 +1,130 @@
+#!/usr/bin/env raku
+
+use v6;
+
+# BTree as string nodevalue[child1,child2]
+# Example tree 5(4(11(7)(2)))(8(13)(9(1)))
+
+grammar BTreeGrammar {
+ token TOP { <tree> };
+ token tree { <value> ["(" $<left>=<tree> ")"]? ["(" $<right>=<tree> ")"]? };
+ regex value { <-[()]>+ }
+}
+
+role BTree[::T] {
+ has T $.value is required;
+ has BTree[T] $.left;
+ has BTree[T] $.right;
+
+ method Str( ) {
+ $!value ~ ( $!left ?? "({$!left.Str()})" !! "" ) ~ ( $!right ?? "({$!right.Str()})" !! "" );
+ }
+
+ method gist() {
+ self.Str();
+ }
+
+ method traverse() {
+ gather {
+ if $!left {
+ for $!left.traverse -> @t {
+ take ($!value, |@t);
+ }
+ }
+ if $!right {
+ for $!right.traverse -> @t {
+ take ($!value, |@t);
+ }
+ }
+ if ! $!left && ! $!right {
+ take ( $!value, );
+ }
+ }
+ }
+
+ multi method from-Str('') { }
+
+ multi method from-Str( ::?CLASS:U: Str $in ) {
+ my $match = BTreeGrammar.parse( $in );
+ if ( $match ) {
+ self.new(
+ value => $match<tree><value>.Str,
+ left => self.from-Str( $match<tree><left> ?? $match<tree><left>.Str !! '' ),
+ right => self.from-Str( $match<tree><right> ?? $match<tree><right>.Str !! '' )
+ );
+ } else {
+ die "Unable to Parse $in";
+ }
+
+ }
+}
+
+class UBTree does BTree[UInt] {
+ submethod BUILD ( :$value, :$left = UBTree, :$right = UBTree ) {
+ $!value = $value.UInt();
+ $!left = $left;
+ $!right = $right;
+ }
+}
+
+#| Display the example Tree in Str and gist representations
+#| also displays all traversals
+multi sub MAIN ( 'example' ) {
+ my $example = example-tree;
+ say $example;
+ UBTree.from-Str( $example.Str ).say;
+
+ for $example.traverse -> @row {
+ @row.join("->").say
+ }
+}
+
+#| Traverses the example tree and prints any routes that add up to the target.
+multi sub MAIN ( UInt $target, 'example' ) {
+ my $example = example-tree;
+
+ for $example.traverse -> @row {
+ @row.join("->").say if ( [+] @row ) == $target;
+ }
+}
+
+#| Given a target number and a tree string find all the traversals that add up to is
+#| Note the Tree string is in the format "number (left tree) (right tree)" spaces are optional
+multi sub MAIN ( UInt $target, *@rest ) {
+ my $tree = UBTree.from-Str( @rest.join("") );
+
+ for $tree.traverse -> @row {
+ @row.join("->").say if ( [+] @row ) == $target;
+ }
+}
+
+
+sub example-tree() {
+ return UBTree.new(
+ value => 5,
+ left => UBTree.new(
+ value => 4,
+ left => UBTree.new(
+ value => 11,
+ left => UBTree.new(
+ value => 7,
+ ),
+ right => UBTree.new(
+ value => 2,
+ )
+ )
+ ),
+ right => UBTree.new(
+ value => 8,
+ left => UBTree.new(
+ value => 13,
+ ),
+ right => UBTree.new(
+ value => 9,
+ right => UBTree.new(
+ value => 1
+ )
+ )
+ )
+ );
+}