Richard Hainsworth wrote:
The following arose out of a discussion on #perl6. Junctions are new and different from anything I have encountered, but I cant get rid of the feeling that there needs to be some more flexibility in their use to make them a common programming tool.

Background: Imagine a hand of cards. Cards may be Ace, Two, Three. Ace having either the values 1 or 11, depending on context, the other cards their face value. Sums of a hand over 21 are invalid.
Hands with multiple junctions become interesting, eg.,
p: Ace, Two, Ace
d: Ace, Three, Ace

Given that Ace has a value of 1 or 11 depending on context, it would seem natural to use a junction. Hence the two hands can be expressed as:
@p = 1|11, 2, 1|11;
@d = 1|11, 3, 1|11;

If we use [+] to add these, we get
$p = [+] @p; say $p.perl; # any(any(4,14),any(14,24))
$d = [+] @d; say $d.perl; #any(any(5,15),any(15,25))

Since the values of 24 & 25 are greater than 21, they must be eliminated from consideration.
What we want is for hand @d to beat hand @p because 15 > 14

On #perl6, rouso, masak and moritz_ explained that I am incorrectly thinking about junctions as sets and that for this task I should be using another perl idiom, namely lists. Something like:
moritz_ rakudo: ([1,11], 3, [1,11]).reduce({@($^a) X+ @($^b)})
p6eval  rakudo bb22e0: RESULT«[5, 15, 15, 25]»

Then the out-of-limit values (in the above case 25) can be stripped off using grep, viz.,
# here we have ([1,11],3,[1,11]) instead of (1|11, 3, 1|11)
my @dlist = grep { $_ < 21 } ([1,11], 3, [1,11]).reduce({@($^a) X+ @($^b)});

Then the two lists (do the same for @p) can be compared by a junction comparison of the form
if any(@plist) > all(@dlist) { say 'p wins' };

The problem is not just that [+] @p produces a junction with undesired (>21) eigenstates, but that the [+] @d produces a junction of the form
any(any(5,15),any(15,25)) which should collapse to any(5,15,25)
whereas we want a junction of the form
all(5,15,25)

After the #perl6 conversation, I thought some more. A junction is a neat way of expressing the hand, but the junction needs to be converted to a list to do some processing, and then the lists are compared using junctions.

I think (I might be wrong) that the conversion from a junction to a list is specified by the .eigenstates method, but it doesn't seem to completely flatten a junction yet - it produces the any(any(4,14),any(14,24)) output shown above.

So my questions to the language list are:

a) Am I trying to fit a square peg in a round hole by applying junctions to this sort of problem? If so, would it be possible to explain what the limits are to the junction approach, or another way of expressing this question: what sort of problems should junctions be applied to?

b) Why would it be "wrong" to have a method for eliminating eigenstates from a junction? (The answer to this might naturally arise out of the answer to a). However, ...

In a wider context, I would conjecture that some algorithms to which junctions could be applied would be optimised if some states could be eliminated, a bit like tree-pruning optimisations that eliminate paths which can never produce a correct answer. Consequently, providing a filtering method would increase the usefulness of the junction as a programming tool. Perhaps

$new-junction = $old-junction.grep({ $_ <= 21 }); # not sure if the parens are needed here

c) On junction algebra, am I wrong or is always true that a junction of the form any('x','y','z', any('foo','bar'), 1, 2, 3) should collapse to any('x','y','z','foo','bar',1,2,3)

In other words, if an 'any' junction is contained in an outer 'any', the inner 'any' can be factored out?
This would eliminate the nested junctions produced by .eigenstates

d) Am I right in thinking this is also true for nested 'all' junctions? viz.
all(1,2,3,all('foo', 'bar')) collapses to all(1,2,3,'foo','bar')

e) Conjecture: This true of all junction types, eg.,
junc(..., junc(...)) == junc(..., ...)

f) Would it be possible to have a means to coerce an 'any' junction into an 'all' junction or vice versa? eg. my $old-junction = 1|2|3; my $new-junction = all{$old-junction}; say $old-junction.perl
# all(1,2,3)
Using () creates a new junction all(any(1,2,3))
{} are undefined for junctions.

If my suggestions prove acceptable, then for my problem I would have:
# @p & @d get defined as arrays of junctions, eg.

my @p=1|11,2,1|11;
my @d=1|11,3,1|11;

#later
my $p = ([+] @p).grep { $_ < 21 };
my $d = ([+] @d).grep { $_ < 21 };
if $p > all{$d} { say 'p wins' } else { say 'd wins' };

I believe that there are hands where $p = 15|26 which would not beat a hand where $d = 17.

I believe that the correct way to calculate the "value of the hand" is:

   my $p = ([+] @p).map{.eigenstates}.grep{$_ < 21}.max;

which is exactly how I do it when I am playing Blackjack.

Put another way, the value of a blackjack hand is deterministic and "sane", and you must get rid of the "schizophrenic" junctions when calculating the value.

Henry

ps. I am not sure that I am using valid perl6 syntax. In pseudo-perl5 I would do it as:

   my $p = max grep {$_ < 21} map {$_.eigenstates} [+] @p;

HB

Richard (finanalyst)


--
Henry Baragar
Principal
Instantiated Software Inc.
416-907-8454 ext 42

Reply via email to