aboutsummaryrefslogtreecommitdiff
path: root/challenge-151/mattneleigh/perl/ch-2.pl
blob: 59a78cbc57cc27dbbc652f46d993e36e6c14179e (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
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/perl

use strict;
use warnings;
use English;

################################################################################
# Begin main execution
################################################################################

# The houses on multiple streets
my @streets = (
    # Given cases
    [ 2, 4, 5 ],
    [ 4, 2, 3, 6, 5, 3 ],

    # Additional test cases
    [ 3, 9 ],
    [ 4 ],
    [ ],

    # This one kind of shows the limitations
    # of the starting condition...
    [ 1, 50, 2, 3, 7, 4 ]
);
my $street;

print("\n");

foreach $street (@streets){
    printf(
        "The street with houses containing valuables: %s\n",
        join(", ", @{$street})
    );
    printf(
        "    will yield a total of %d loot.\n\n",
        calculate_loot_yield_on_street(@{$street})
    );
}

print("DISCLAIMER: Do not actually rob houses- it's not nice!\n\n");

exit(0);
################################################################################
# End main execution; subroutines follow
################################################################################



################################################################################
# Determine the maximum amount of loot that can be gotten by robbing houses on
# a street, given certain parameters and restrictions, including a requirement
# to rob the first house on the street, and not to rob any two adjacent houses
# Takes one argument:
# * A list of the quantities of loot available in each house on the street
# Returns:
# * The maximum amount of loot that can be gotten within the restrictions
#   specified, which will be zero (0) if the supplied list is empty
# Shamelessly adapted from an algorithm seen at:
# https://www.geeksforgeeks.org/find-maximum-possible-stolen-value-houses/
# DISCLAIMER: Do not actually rob houses- it's not nice!
################################################################################
sub calculate_loot_yield_on_street{
    use List::Util qw(max);

    # Empty list, no houses to rob
    return(0)
        unless(@ARG);

    my @loot;
    my $loot_initial;
    my $i;

    # We always start with the first house, as
    # specified (though this seems limiting...)
    $loot_initial = $ARG[0];

    # Strip off the first two houses- we've
    # robbed the first and can't rob the second
    splice(@ARG, 0, 2);

    # Edge cases- zero or one houses left
    return($loot_initial)
        unless(@ARG);
    if(scalar(@ARG) == 1){
        return($loot_initial + $ARG[0]);
    }

    # Proceed as normal(?)
    $loot[0] = $ARG[0];
    $loot[1] = max($ARG[0], $ARG[1]);

    for($i = 2; $i < scalar(@ARG); $i++){
        $loot[$i] = max($ARG[$i] + $loot[$i - 2], $loot[$i - 1]);
    }

    return($loot_initial + $loot[$#loot]);

}