aboutsummaryrefslogtreecommitdiff
path: root/challenge-038/javier-luque/perl5/ch-2.pl
blob: a200eba363b8961f72a08ebb81db8f2ffa9191a8 (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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/perl
# Test: ./ch-2.pl
use strict;
use warnings;
use feature qw /say/;
use Algorithm::Combinatorics qw(variations);
use List::Util qw(shuffle);

# Store valid words
our %valid_words;

# Tiles metadata
our %tiles_metadata =  (
    A => { points => 1,  amount => 8 },
    B => { points => 4,  amount => 5 },
    C => { points => 5,  amount => 4 },
    D => { points => 3,  amount => 3 },
    E => { points => 2,  amount => 9 },
    F => { points => 3,  amount => 3 },
    G => { points => 1,  amount => 3 },
    H => { points => 5,  amount => 3 },
    I => { points => 1,  amount => 5 },
    J => { points => 2,  amount => 3 },
    K => { points => 10, amount => 2 },
    L => { points => 2,  amount => 3 },
    M => { points => 5,  amount => 4 },
    N => { points => 4,  amount => 4 },
    O => { points => 5,  amount => 3 },
    P => { points => 3,  amount => 5 },
    Q => { points => 10, amount => 2 },
    R => { points => 2,  amount => 3 },
    S => { points => 1,  amount => 7 },
    T => { points => 5,  amount => 5 },
    U => { points => 1, amount  => 5 },
    V => { points => 2,  amount => 3 },
    W => { points => 3,  amount => 5 },
    X => { points => 1,  amount => 2 },
    Y => { points => 2,  amount => 5 },
    Z => { points => 1,  amount => 5 },
);

# Load the dictionary
load_words('/usr/share/dict/words');

# Grab 7 times
my @tiles = get_tiles(7);
say 'Picked tiles: ' . join ', ', @tiles;

# Find the word with the most points
my ($word, $score) = find_best_word(\@tiles);
say 'Best word: ' . $word .
    ' with score: ' . $score;

# Load the dictionary into memory
sub load_words {
    my $filename = shift;

    open(my $fh, '<:encoding(UTF-8)', $filename) || die "$@";
    while (my $row = <$fh>) {
        chomp $row;
        $valid_words{uc($row)} = 1;
    }
}

# Get tiles
sub get_tiles {
    my $no_tiles = shift;

    # Generate the set of tiles
    my @tileset;
    for my $key (keys %tiles_metadata) {
        for my $i (1 .. $tiles_metadata{$key}->{amount}) {
            push @tileset, $key;
        }
    }

    # Get Seven tiles
    my @shuffled_indexes = shuffle(0..$#tileset);
    my @my_tiles =
        @tileset[
            @shuffled_indexes[ 0 .. $no_tiles -1 ]
        ];
    return @my_tiles;
}

# Find the best word
sub find_best_word {
    my $tiles_ref = shift;
    my $top_score = 0;
    my $top_word;

    # Generate the possible combinations
    for my $i (1..7) {
        my $iter = variations($tiles_ref,$i);

        # Loop through each variation
        while (my $v = $iter->next) {
            my $word = join '', @{$v};
            if ($valid_words{$word}) {
                my $score = calculate_score($v);

                # If this is the best word store it
                if ($score > $top_score) {
                    $top_score = $score;
                    $top_word  = $word;
                }
            }
        }
    }

    return $top_word, $top_score;
}

# Calculate score
sub calculate_score {
    my $word_ref = shift;
    my $score = 0;

    for my $letter (@${word_ref}) {
        $score += $tiles_metadata{$letter}->{points};
    }

    return $score;
}