perlmeditation
Daruma
Greetings Monks!<br><br>
Yesterday I was given a riddle over an instant messenger connection. "What 5 digit number am I thinking of?" It was a simple mathematical puzzle. Here are the conditions of the query...<br><br>
<h4>What 5 digit number am I thinking of?</h4>
<ul>
<li>It has 2 prime digits.</li>
<li>Digit 3 is the highest number.</li>
<li>Digit 2 is lowest.</li>
<li>Digit 5 is between digit 2 and digit 1 and is half of digit 4.</li>
<li>There are no duplicates.</li>
<li>Digit 1 is 1 less than digit 3.</li>
<li>Digit 1 is higher than the sum of digits 4 and 5.</li>
</ul><br>
Well... I twiddled around with it a bit and found one answer using a good bit of guesswork. Then my IM prompter said she had two answers. At this point, I was hooked. I not only had to find three answers... I had to find all possible answers, and fast!<br><br>
I whipped together a quick bit of code...<br>
<readmore>
<code>
#!c:\perl\bin\perl.exe
#
# FILE: autoprime.pl
#
# Daruma
# 09-MAY-2003
#
# puzzle: What 5 digit number am I thinking of?
# It has 2 prime digits.
# Digit 3 is the highest number.
# Digit 2 is lowest.
# Digit 5 is between digit 2 and digit 1 and is half of digit 4.
# There are no duplicates.
# Digit 1 is 1 less than digit 3.
# Digit 1 is higher than the sum of digits 4 and 5.
use warnings;
use strict;
my $candidate;
my @digits;
my $flag;
for ($candidate = 12345;
$candidate <= 98765;
$candidate++) {
$flag = 0;
check_prime($candidate);
check_digit_3($candidate);
check_digit_2($candidate);
check_digit_5($candidate);
#check_duplicates($candidate); # problem?
check_digit_1($candidate);
if ($flag < 1) {
print "$candidate\n";
}
}
# subroutines
sub check_prime {
# The candidate number must have 2 prime digits
my $candidate = shift;
my @digits = split //,$candidate;
my $prime_count = 0;
foreach my $digit (@digits) {
if ($digit =~ /(2|3|5|7)/) { $prime_count++ }
}
if ($prime_count != 2) { $flag++ }
}
sub check_digit_3 {
# Digit 3 is the highest number.
my $candidate = shift;
my @digits = split //,$candidate;
my $digit_3 = splice @digits,2,1;
foreach my $digit (@digits) {
if ($digit_3 < $digit) { $flag++ }
}
}
sub check_digit_2 {
# Digit 2 is lowest.
my $candidate = shift;
my @digits = split //,$candidate;
my $digit_2 = splice @digits,1,1;
foreach my $digit (@digits) {
if ($digit_2 > $digit) { $flag++ }
}
}
sub check_digit_5 {
# Digit 5 is between digit 2 and digit 1
# and is half of digit 4.
my $candidate = shift;
my @digits = split //,$candidate;
my $digit_5 = pop(@digits);
my $digit_1 = shift(@digits);
my $digit_2 = shift(@digits);
my $digit_4 = pop(@digits);
if ($digit_5 > $digit_1 and $digit_5 < $digit_2) {} # good
elsif ($digit_5 < $digit_1 and $digit_5 > $digit_2) {} # also good
else { $flag++ }
if ($digit_5 != $digit_4 / 2) { $flag++ }
}
sub check_duplicates {
# There are no duplicates.
# Problems with this sub...
my $candidate = shift;
my @digits = split //,$candidate;
foreach my $digit (@digits) {
#shift(@digits);
foreach my $check_digit (@digits) {
if ($digit == $check_digit) { $flag++ }
}
}
}
sub check_digit_1 {
# Digit 1 is 1 less than digit 3.
# Digit 1 is higher than the sum of digits 4 and 5.
my $candidate = shift;
my @digits = split //,$candidate;
my $sum_4_5 = $digits[3] + $digits[4];
if ($digits[0] != $digits[2] - 1 or $digits[0] <= $sum_4_5) { $flag++ }
}
</code>
</readmore>
<br>
I am quite sure there is a MUCH more efficient way to handle the problem, but this was a quick hack. Any suggestions, concerns, criticisms or witticisms are welcome, as always... <br><br>
[Daruma]