This is my response to the Perl Weekly Challenge #160.
$n < 10
.
Input: $n = 5
Output: Five is four, four is magic.
Example 2:
Input: $n = 7
Output: Seven is five, five is four, four is magic.
Example 3:
Input: $n = 6
Output: Six is three, three is five, five is four, four is magic.
File: four-is-magic
#! /usr/bin/env raku
unit sub MAIN (Int $n is copy where 0 < $n < 10); # [1]
my @names = # [2]
[
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
];
my @result; # [3]
repeat # [4]
{
my $text = @names[$n]; # [5]
my $length = $text.chars; # [6]
@result.push: "$text is @names[$length]"; # [7]
$n = $length; # [8]
} while $n != 4; # [9]
say tc(@result.join(", ")) ~ ", four is magic."; # [10]
[1] A positive integer, actually. Thus in the interval 1..9.
[2] From the numbers to the textual representation. Note the first entry (for zero). It is not needed, so an empty string could also have been used.
[3] The result, as an array (so that we can join them with a comma later on, in [10]).
[4] Repeat the block as long as the condition in [9] is not met.
See
docs.raku.org/syntax/repeat
for more information about repeat
.
[5] Get the text version of the number,
[6] and the length of that text.
[7] Add the partial result to the array.
[8] Set the next number, ready for the end condition check (in [9]) - or a new iteration.
[9] Finish the loop when we have reached the number 4.
[10] Print the result. Note the join on comma to get the requested
output format. tc
(title case) gives us the first letter converted to
uppercase.
See
docs.raku.org/routine/tc
for more information about tc
(title case).
Running it:
$ ./four-is-magic 9
Nine is four, four is magic.
$ ./four-is-magic 8
Eight is five, five is four, four is magic.
$ ./four-is-magic 7
Seven is five, five is four, four is magic.
$ ./four-is-magic 6
Six is three, three is five, five is four, four is magic.
$ ./four-is-magic 5
Five is four, four is magic.
$ ./four-is-magic 4
Four is four, four is magic.
$ ./four-is-magic 3
Three is five, five is four, four is magic.
$ ./four-is-magic 2
Two is three, three is five, five is four, four is magic.
$ ./four-is-magic 1
One is three, three is five, five is four, four is magic.
Looking good.
As a graph, just for fun:
#! /usr/bin/env perl
use strict;
use warnings;
use feature 'say';
my $n = $ARGV[0] || "";
die "Values 1..9 only" unless $n =~ /^[1-9]$/;
my @names =
(
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
);
my @result;
do
{
my $text = $names[$n];
my $length = length($text);
push(@result, "$text is $names[$length]");
$n = $length;
} while $n != 4;
say ucfirst(join(", ", @result)) . ", four is magic.";
Running it gives the same result as the Raku version:
$ ./four-is-magic-perl 9
Nine is four, four is magic.
$ ./four-is-magic-perl 8
Eight is five, five is four, four is magic.
$ ./four-is-magic-perl 7
Seven is five, five is four, four is magic.
$ ./four-is-magic-perl 6
Six is three, three is five, five is four, four is magic.
$ ./four-is-magic-perl 5
Five is four, four is magic.
$ ./four-is-magic-perl 4
Four is four, four is magic.
$ ./four-is-magic-perl 3
Three is five, five is four, four is magic.
$ ./four-is-magic-perl 2
Two is three, three is five, five is four, four is magic.
$ ./four-is-magic-perl 1
One is three, three is five, five is four, four is magic.
@n
.
Equilibrium Index
of the given array, if
found.
Input: @n = (1, 3, 5, 7, 9)
Output: 3
Example 2:
Input: @n = (1, 2, 3, 4, 5)
Output: -1 as no Equilibrium Index found.
Example 3:
Input: @n = (2, 4, 2)
Output: 1
I have decided to accept positive integers only.
File: equilibrium-index
#! /usr/bin/env raku
unit sub MAIN (*@n where @n.elems > 0 && all(@n) ~~ /^\d+$/, # [1]
:v(:$verbose));
my $elems = @n.elems; # [2]
for 1 .. $elems - 2 -> $equilibrium # [3]
{
my @first = @n[0 .. $equilibrium -1]; # [4]
my @second = @n[$equilibrium +1 .. $elems -1]; # [5]
say ": @first[] :: @second[]" if $verbose;
if @first.sum == @second.sum # [6]
{
say $equilibrium; # [6a]
exit; # [6b]
}
}
say -1; # [7]
[1] At least one element, and they (all of them) must satisfy the regex (one or more integers). Note that zero is allowed.
[2] The number of elements.
[3] Iterate over the breaking point (the possible equilibrium), i.e. the index.
[4] Get the left hand part,
[5] and the right hand part. (Note that the equilibrium value itself is not included in either one.)
[6] Are the sums equael? If som, print the index [6a] and exit [6b].
[7] We have not found an equilibrium. Say so.
Running it:
$ ./equilibrium-index 1 3 5 7 9
3
$ ./equilibrium-index 1 2 3 4 5
-1
$ ./equilibrium-index 2 4 2
1
Looking good.
With verbose mode, where «::» is the equilibrium candidate:
$ ./equilibrium-index -v 1 3 5 7 9
: 1 :: 5 7 9
: 1 3 :: 7 9
: 1 3 5 :: 9
3
$ ./equilibrium-index -v 1 2 3 4 5
: 1 :: 3 4 5
: 1 2 :: 4 5
: 1 2 3 :: 5
-1
$ ./equilibrium-index -v 2 4 2
: 2 :: 2
1
#! /usr/bin/env perl
use strict;
use warnings;
use feature 'say';
use List::Util 'sum';
use Getopt::Long;
use Perl6::Junction 'all'; # [1]
my $verbose = 0;
GetOptions("verbose" => \$verbose);
my @n = @ARGV;
die "Positive integers only" unless @n && all(@n) == qr/^\d+$/; # [1a]
my $elems = @n;
for my $equilibrium (1 .. $elems -2)
{
my @first = @n[0 .. $equilibrium -1];
my @second = @n[$equilibrium +1 .. $elems -1];
say ": @first :: @second" if $verbose;
if (sum(@first) == sum(@second))
{
say $equilibrium;
exit;
}
}
say -1;
[1] Note the useage of the Perl6::Junction module to get junction functionality. The actual syntax (at [1a]) is a little cumbersome, but everything is nicely explained in the documentation.
Running it gives the same result as the Raku version:
$ ./equilibrium-index-perl 1 3 5 6 9
3
$ ./equilibrium-index-perl 1 2 3 4 5
-1
$ ./equilibrium-index-perl 2 4 2
1
As does verbose mode:
$ ./equilibrium-index-perl -v 1 3 5 6 9
: 1 :: 5 6 9
: 1 3 :: 6 9
: 1 3 5 :: 9
3
$ ./equilibrium-index-perl -v 1 2 3 4 5
: 1 :: 3 4 5
: 1 2 :: 4 5
: 1 2 3 :: 5
-1
$ ./equilibrium-index-perl -v 2 4 2
: 2 :: 2
1
And that's it.