 : penultimate ( seq -- elt )
     dup length 2 - swap nth ;
 
+<PRIVATE
+
+! Propagate one row into the upper one
+: propagate ( bottom top -- newtop )
+    [ over rest rot first2 max rot + ] map nip ;
+
+PRIVATE>
+
 ! Not strictly needed, but it is nice to be able to dump the
 ! triangle after the propagation
 : propagate-all ( triangle -- new-triangle )

: perfect-square? ( n -- ? )
    dup sqrt mod zero? ;

<PRIVATE

: count-digits ( n -- byte-array )
    10 <byte-array> [
        '[ 10 /mod _ [ 1 + ] change-nth dup 0 > ] loop drop
    ] keep ;

HINTS: count-digits fixnum ;

: max-children ( seq -- seq )
    [ dup length 1 - <iota> [ nth-pair max , ] with each ] { } make ;

! Propagate one row into the upper one
: propagate ( bottom top -- newtop )
    [ over rest rot first2 max rot + ] map nip ;

: (sum-divisors) ( n -- sum )
    dup sqrt >integer [1,b] [
        [ 2dup divisor? [ 2dup / + , ] [ drop ] if ] each
        dup perfect-square? [ sqrt >fixnum neg , ] [ drop ] if
    ] { } make sum ;

: transform ( triple matrix -- new-triple )
    [ 1array ] dip m. first ;

PRIVATE>

: alpha-value ( str -- n )
    >lower [ CHAR: a - 1 + ] map-sum ;

: mediant ( a/c b/d -- (a+b)/(c+d) )
    2>fraction [ + ] 2bi@ / ;

: max-path ( triangle -- n )
    dup length 1 > [

        dupd divisor? [ [ 2 + ] dip ] when
    ] each drop * ;

<PRIVATE

: transform ( triple matrix -- new-triple )
    [ 1array ] dip m. first ;

PRIVATE>

! These transforms are for generating primitive Pythagorean triples
: u-transform ( triple -- new-triple )
    { { 1 2 2 } { -2 -1 -2 } { 2 2 3 } } transform ;
