develooper Front page | perl.perl6.language | Postings from March 2009

On Junctions

Thread Next
From:
Richard Hainsworth
Date:
March 27, 2009 03:37
Subject:
On Junctions
Message ID:
49CCAC47.8060205@rusrating.ru
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' };

Richard (finanalyst)


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About