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
125
126
127
128
129
130
131
132
|
package Task089_2;
use strict;
use warnings;
=head1 NAME
Task089_2 - TASK 089 #2: Magical Matrix
=head1 SYNOPSIS
Display matrix as below with numbers 1 - 9. Make sure numbers are used once.
[ a b c ]
[ d e f ]
[ g h i ]
a + b + c = 15
d + e + f = 15
g + h + i = 15
a + d + g = 15
b + e + h = 15
c + f + i = 15
a + e + i = 15
c + e + g = 15
=cut
# Test the magic rules. A hash ref with a-i keys is required. Returns:
# 0: a rule failed
# 1: all rules are ok
sub _check_magic_rules_ {
my $matrix = shift;
return 0 if $matrix->{a} + $matrix->{b} + $matrix->{c} != 15;
return 0 if $matrix->{d} + $matrix->{e} + $matrix->{f} != 15;
return 0 if $matrix->{g} + $matrix->{h} + $matrix->{i} != 15;
return 0 if $matrix->{a} + $matrix->{d} + $matrix->{g} != 15;
return 0 if $matrix->{b} + $matrix->{e} + $matrix->{h} != 15;
return 0 if $matrix->{c} + $matrix->{f} + $matrix->{i} != 15;
return 0 if $matrix->{a} + $matrix->{e} + $matrix->{i} != 15;
return 0 if $matrix->{c} + $matrix->{e} + $matrix->{g} != 15;
return 1;
}
# Check if two array refs have at least one equal element (1) or not (0)
sub _match_arrays_ {
my $arr_1 = shift;
my $arr_2 = shift;
for my $i( $arr_1->@* ) {
for my $j( $arr_2->@* ) {
return 1 if $i == $j;
}
}
return 0;
}
sub _set_magic_matrix_values_ {
my $mag_mat = shift;
my $keys = shift;
my $values = shift;
for (my $i=0; $i<@$keys; $i++) {
$mag_mat->{$keys->[$i]} = $values->[$i];
}
}
=head2 magical_matrix
Return an array with valid solutions of magical matrix 3x3
=cut
sub magical_matrix {
my @solutions = ();
my $mag_mat = {};
# 1. fill @valid with 3-tuples that sum 15
my $valid = [];
my @digits = (1..9);
for my $i (@digits) {
for my $j (grep { !/$i/ } @digits ) {
for my $k (grep { !/$i|$j/ } @digits ) {
push $valid->@*, [$i, $j, $k] if $i+$j+$k == 15;
}
}
}
# Try valid 3-tuples for row 1
for my $current_1 ($valid->@*) {
_set_magic_matrix_values_ ( $mag_mat, [qw/a b c/], $current_1 );
# Filter the tuples candidates for 2nd row
my @valid_2 = grep { ! _match_arrays_ ($_, $current_1) } $valid->@*;
# Try valid 3-tuples for row 2
for my $current_2 (@valid_2) {
_set_magic_matrix_values_ ( $mag_mat, [qw/d e f/], $current_2 );
# Filter the tuples candidates for 3nd row
my @valid_3 = grep { ! _match_arrays_ ($_, $current_2) } @valid_2;
# Try valid 3-tuples for row 3
for my $current_3 ( @valid_3 ) {
_set_magic_matrix_values_( $mag_mat, [qw/g h i/], $current_3 );
# Check the magic rules, and if ok, add the current setup to
# the final solutions
_check_magic_rules_ ($mag_mat)
&& push @solutions, [$current_1, $current_2, $current_3];
}
}
}
return @solutions;
}
#----
1970;
|