perl logo Perl logo (Thanks to Olaf Alders)

The weekly challenge 388 - Task 1: Dyck Words

 1 #!/usr/bin/env perl
 2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-388/#TASK1
 3 #
 4 # Task 1: Dyck Words
 5 # ==================
 6 #
 7 # A Dyck Word of order $n is a string of length 2x$n consisting of $n ‘U’ (Up)
 8 # characters and $n ‘D’ (Down) characters such that no initial prefix of the
 9 # string contains more ‘D’s than ‘U’s.
10 #
11 # Write a script to return a list of all valid Dyck words of length 2x$n,
12 # sorted in lexicographical (alphabetical) order.
13 #
14 ## Example 1
15 ##
16 ## Input: $n = 1
17 ## Output: ("UD")
18 #
19 ## Example 2
20 ##
21 ## Input: $n = 2
22 ## Output: ("UDUD","UUDD")
23 #
24 ## Example 3
25 ##
26 ## Input: $n = 3
27 ## Output: ("UDUDUD", "UDUUDD", "UUDDUD", "UUDUDD", "UUUDDD")
28 #
29 ## Example 4
30 ##
31 ## Input: $n = 0
32 ## Output: ("")
33 #
34 ## Example 5
35 ##
36 ## Input: $n = 4
37 ## Output: ("UDUDUDUD", "UDUDUUDD", "UDUUDDUD", "UDUUDUDD", "UDUUUDDD",
38 ##          "UUDDUDUD", "UUDDUUDD", "UUDUDDUD", "UUDUDUDD", "UUDUUDDD",
39 ##          "UUUDDDUD", "UUUDDUDD", "UUUDUDDD", "UUUUDDDD")
40 #
41 ############################################################
42 ##
43 ## discussion
44 ##
45 ############################################################
46 #
47 # We just calculate all options recursively:
48 # - We start with an empty string
49 # - As long as we still have U's or D's available:
50 #   - recursively create all options starting at the current string:
51 #     - if there are more U's, create all new results from the current
52 #       results by adding a "U" and recursively go further with one less U
53 #     - if there are more D's than U's, create all new results from the current
54 #       results by adding a "D" and recursively go further with one less D
55 # When there are no more U's and D's left, return the result.
56 
57 use v5.36;
58 
59 sub dyck_words($n) {
60     say "Input: $n";
61     my @result = find_dyck_words($n, $n, (""));
62     say "Output: (" . join(", ", map { "\"$_\"" } @result) . ")";
63 }
64 
65 sub find_dyck_words($n1, $n2, @current_result) {
66     my @result = ();
67     return @current_result if $n1 == 0 and $n2 == 0;
68     if($n1 > 0) {
69         foreach my $elem (@current_result) {
70             push @result, find_dyck_words($n1-1, $n2, ("${elem}U"));
71         }
72     }
73     if($n2 > $n1) {
74         foreach my $elem (@current_result) {
75             push @result, find_dyck_words($n1, $n2-1, ("${elem}D"));
76         }
77     }
78     return @result;
79 }
80 
81 dyck_words(1);
82 dyck_words(2);
83 dyck_words(3);
84 dyck_words(0);
85 dyck_words(4);