xsl-list
[Top] [All Lists]

Re: [xsl] FizzBuzz in XSLT 1.0. Help with a 2.0/FXSL solution?

2007-03-17 19:48:46
On 3/14/07, M. David Peterson <m(_dot_)david(_at_)mdptws(_dot_)com> wrote:
Hey All,

Building upon the theme provided by Dr. Kay a while back[1], I recently wrote a 
post
that showcased how one could not only use XSLT to solve the problem, but do so 
in a
way that provides for dynamic data evaluation in regards to the variables used, 
and
what those variables should print out when the test evaluates to true.

http://dev.aol.com/blog/mdavidpeterson/2007/03/14/fizz-buzz-in-xslt-1.0

My question to you all is this: Using this same premise, how would one solve 
this in
XSLT 2.0, and in particular, given that this touches smack-dab center on the 
benefits
that FXSL provides the XSLT developer, how one could use FXSL to solve this same
problem?

I have been quite busy these days, so here's an answer coming somewhat late.

The other reason for the delay is that the FXSL infrastructure was not
complete for solving a problem of this kind. I had to implement a
number of new functions (especially the f:lift<N>() family of
functions), which I had planned to do long ago.

Right now, FXSL produces the desired result with the following
one-liner (err... it is a single expression, to be more precise):


   "f:multiMap($vDelimElem,
               (f:compose(f:choice('fizz', '', 0), f:flip(f:mod(),3)),
                f:compose(f:choice('buzz', '', 0), f:flip(f:mod(),5)),
                f:lift4(f:choice(),
                        f:const(''),
                        f:id(),
                        f:const((0,3,5,6,9,10,12)),
                        f:flip(f:mod(),15)
                        )
               ),
               1  to 100)"


Here f:multiMap()  maps a list of functions on every element of a list
(of data items). The produced list of results are delimited by an
element-delimiter, because the XPath 2.0 data model only supports flat
sequences.

f:choice(pChoice1, pChoice2, pChoice1Val, pActualVal)

evaluates to
         pChoice1

if
  pActualVal = pChoice1Val

and evaluates to

        pChoice2

otherwise.

f:id(x) = x

f:const(x,y) = x


So, the above expression evaluates a multiMap of three functions, each
on the numbers 1 to 100.

The first two functions produce "fizz" or (respectively) "buzz"
whenever their argument is divisible by 3 or (respectively) 5. Both
functions produce Nothing (the empty string) otherwise.

The third function specified for f:multiMap() is a little bit more
involved. It is a "lift" of the function f:choice(), which allows its
arguments to be functions, that provide the arguments to f:choice().
This is necessary, because when the number is neither divisible by 3
or 5 we are required to produce not a fixed result, but this number
itself, which is done by the function f:id().


Let me thank M.David Peterson for this excellent and challenging problem.

Here is the complete transformation. To run it one needs to sync from
the FXSL CVS for the latest changes:


<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xs="http://www.w3.org/2001/XMLSchema";
xmlns:f="http://fxsl.sf.net/";
exclude-result-prefixes="f xs"
>
 <xsl:import href="../f/func-multiMap.xsl"/>
 <xsl:import href="../f/func-Operators.xsl"/>
 <xsl:import href="../f/func-id.xsl"/>
 <xsl:import href="../f/func-const.xsl"/>
 <xsl:import href="../f/func-choice.xsl"/>
 <xsl:import href="../f/func-lift.xsl"/>
 <xsl:import href="../f/func-compose.xsl"/>

 <xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
  <xsl:variable name="vDelimElem" as="element()">
    <map/>
  </xsl:variable>

  <multiMap>
  <xsl:sequence select=
   "f:multiMap($vDelimElem,
               (f:compose(f:choice('fizz', '', 0), f:flip(f:mod(),3)),
                f:compose(f:choice('buzz', '', 0), f:flip(f:mod(),5)),
                f:lift4(f:choice(),
                        f:const(''),
                        f:id(),
                        f:const((0,3,5,6,9,10,12)),
                        f:flip(f:mod(),15)
                        )
               ),
               1  to 100)"
 />
 </multiMap>
</xsl:template>
</xsl:stylesheet>


And the result:

<multiMap>
        <map/>1
        <map/>2
        <map/>fizz
        <map/>4
        <map/>buzz
        <map/>fizz
        <map/>7
        <map/>8
        <map/>fizz
        <map/>buzz
        <map/>11
        <map/>fizz
        <map/>13
        <map/>14
        <map/>fizz buzz
        <map/>16
        <map/>17
        <map/>fizz
        <map/>19
        <map/>buzz
        <map/>fizz
        <map/>22
        <map/>23
        <map/>fizz
        <map/>buzz
        <map/>26
        <map/>fizz
        <map/>28
        <map/>29
        <map/>fizz buzz
        <map/>31
        <map/>32
        <map/>fizz
        <map/>34
        <map/>buzz
        <map/>fizz
        <map/>37
        <map/>38
        <map/>fizz
        <map/>buzz
        <map/>41
        <map/>fizz
        <map/>43
        <map/>44
        <map/>fizz buzz
        <map/>46
        <map/>47
        <map/>fizz
        <map/>49
        <map/>buzz
        <map/>fizz
        <map/>52
        <map/>53
        <map/>fizz
        <map/>buzz
        <map/>56
        <map/>fizz
        <map/>58
        <map/>59
        <map/>fizz buzz
        <map/>61
        <map/>62
        <map/>fizz
        <map/>64
        <map/>buzz
        <map/>fizz
        <map/>67
        <map/>68
        <map/>fizz
        <map/>buzz
        <map/>71
        <map/>fizz
        <map/>73
        <map/>74
        <map/>fizz buzz
        <map/>76
        <map/>77
        <map/>fizz
        <map/>79
        <map/>buzz
        <map/>fizz
        <map/>82
        <map/>83
        <map/>fizz
        <map/>buzz
        <map/>86
        <map/>fizz
        <map/>88
        <map/>89
        <map/>fizz buzz
        <map/>91
        <map/>92
        <map/>fizz
        <map/>94
        <map/>buzz
        <map/>fizz
        <map/>97
        <map/>98
        <map/>fizz
        <map/>buzz
        <map/>
</multiMap>


--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--