aboutsummaryrefslogtreecommitdiff
path: root/challenge-042/colin-crain/perl/ch-2.pl
blob: 6eea648f11e7439c48cec89aa9947ee68c198157 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#! /opt/local/bin/perl
#
#       balanced_brackets.pl
#
#       PWC 42 - TASK #2
#             Balanced Brackets
#             Write a script to generate a string with random number of ( and )
#             brackets. Then make the script validate the string if it has
#             balanced brackets.
#
#             For example:
#
#             () - OK
#             (()) - OK
#             )( - NOT OK
#             ())() - NOT OK
#
#       method: to make the random string of parens, we take a range of 1 to
#             10 indexes and, mapping through them, assign either a left or right
#             paren and place on a list, joining that list at the end to make a
#             single string. So far so good.
#
#             For validation, we will match pairs of parens and eliminate them
#             from the string until no more can be matched. If our string goes
#             away we were good, if not, then things didn't match up. That said,
#             there are a number of short circuits to this process where it no
#             longer pays to continue.
#
#             • Matched parens come in pairs, by definition, so right out of the
#             gate the length of the random string must be even. So this
#             eliminates one half of the chances. We will check for evenness and
#             exit with a message as required.
#
#             • If the string under consideration starts with a right paren, that
#             paren can no longer be matched and the validation will fail. One way
#             to detect this is to look for the placement of a valid () match; if
#             the match does not take place at index 0, there must be a paren
#             preceeding it and that paren must be a right paren. So we exit with
#             a note.
#
#             • Finally if matching has stopped we check for length, if the string
#             still has chars, it is imbalanced and we exit with a note, showing
#             the unbalanced section. If we have no string lenght remaining,
#             against all odds we have succeded at randomly crafting a balanced
#             string of parens.
#
#             It's obvious this last occurance will in fact rarely happen. The
#             shortest matching sting is 2 chars, (). The odds are .5 any given
#             string is odd-numbered, and .5 the first paren will be right, so our
#             chance of immediately failing is .75
#
#             After this the odds get complicated, but never better, and worse as
#             the length of the random base grows. So for purposes of this
#             experiment the length has been limited to up to 10 chars.

#
#       2020 colin crain
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##



use warnings;
use strict;
use feature ":5.26";

## ## ## ## ## MAIN

my $upper = shift @ARGV // 10;
$upper = int(rand($upper)) + 1;

my $str = make_string($upper);
say $str;
say validate( $str );


## ## ## ## ## SUBS

sub make_string {
    return join '', map { ['(',')']->[int(rand(2))] } (1..$_[0]);
}

sub validate {
    my $str = shift;
    unless (length($str)%2==0) { return "IMBALANCED - odd number of parens"};
    while ( $str =~ s/ \( (.*?) \) /$1/x) {
        if ($-[0] != 0){ return "IMBALANCED - remaining group starts with right paren : $str" }
    }
    return (length $str == 0) ? "BALANCED" : "IMBALANCED - $str remaining";
}