Category talk:Factor-numspec: Difference between revisions

From Rosetta Code
Content added Content deleted
(Add Factor-numspec source code)
 
m (Chunes moved page Talk:Factor-numspec to Category talk:Factor-numspec: to make libheader template work correctly)
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Source code ==
== Source code ==
<lang factor>USING: grouping kernel lexer lists lists.lazy math
<lang factor>USING: ascii assocs kernel lexer lists lists.lazy math
math.functions parser sequences ;
math.functions math.parser namespaces pair-rocket parser
sequences words.constant ;
IN: numspec
IN: numspec

SYMBOL: digits

H{
CHAR: E => L{ 0 2 4 6 8 }
CHAR: e => L{ 2 4 6 8 }
CHAR: f => L{ 2 4 6 }
CHAR: o => L{ 1 3 5 7 9 }
CHAR: s => L{ 1 2 3 4 5 6 7 8 9 }
CHAR: p => L{ 2 3 5 7 }
CHAR: q => L{ 1 3 7 9 }
CHAR: r => L{ 3 5 7 }
CHAR: _ => L{ 0 1 2 3 4 5 6 7 8 9 }
}

digits set-global


<PRIVATE
<PRIVATE


: digits>number ( {5,3,1} -- 531 )
: digits>number ( {5,2,4} -- 524 )
<reversed> 0 [ 10^ * + ] reduce-index ; flushable
<reversed> 0 [ 10^ * + ] reduce-index ;


: (numspec) ( list-of-lists-of-lists -- list )
: parse-digit ( n -- list )
dup digit? [ digit> 1list ] [ digits get at ] if ;
[ lcartesian-product* ] lmap-lazy lconcat
[ digits>number ] lmap-lazy ;


: (parse-digits-spec) ( str -- list-of-lists )
: (extrapolate) ( seq -- newseq ) [ second 1 ] keep insert-nth ;
[ parse-digit ] { } map-as >list ;


: extrapolate ( seq -- list )
: parse-digits-spec ( str -- list-of-lists )
dup length 1 = [ CHAR: 0 prefix ] when (parse-digits-spec) ;
but-last [ but-last >list ] [ last ] bi
[ (extrapolate) ] lfrom-by lappend-lazy ;


: ?extrapolate ( seq -- list )
: (parse-numspec) ( seq -- list-of-lists-of-lists )
dup last "..." = [ extrapolate ] [ >list ] if ;
[ parse-digits-spec ] map >list ;


: expand ( token -- list )
: extrapolate ( list -- list' )
uncons uncons dupd cons cons cons ;
parse-datum dup integer? [ 1list ] [ execute( -- x ) ] if ;


: prep-cartesian ( seq -- list )
: >infinite ( list -- list' ) [ extrapolate ] lfrom-by ;
dup length 1 = [ L{ 0 } prefix ] when >list ;


: <numspec> ( list -- list' )
: infinitize ( seq -- list )
but-last unclip-last [ (parse-numspec) ]
[ 1 group [ expand ] map prep-cartesian ] lmap-lazy ;
[ parse-digits-spec >infinite ] bi* lappend-lazy ;

: parse-numspec ( seq -- list-of-lists-of-lists )
dup last "..." = [ infinitize ] [ (parse-numspec) ] if ;


PRIVATE>
PRIVATE>


: numspec ( seq -- list )
! Some common digit restrictions. Custom ones are easily definable.
parse-numspec [ lcartesian-product* ] lmap-lazy lconcat
CONSTANT: _ L{ 0 1 2 3 4 5 6 7 8 9 } ! any
[ digits>number ] lmap-lazy ;
CONSTANT: S L{ 1 2 3 4 5 6 7 8 9 } ! no zero (for leading digit)
CONSTANT: E L{ 0 2 4 6 8 } ! even
CONSTANT: O L{ 1 3 5 7 9 } ! odd
CONSTANT: P L{ 2 3 5 7 } ! prime
CONSTANT: Q L{ 1 3 7 9 } ! number can be prime if this is last digit


SYNTAX: NUMSPEC:
: numspec ( seq -- list ) ?extrapolate <numspec> (numspec) ;
scan-new-word ";" parse-tokens numspec define-constant ;


SYNTAX: DIGIT:
SYNTAX: NUMSPEC: ";" parse-tokens numspec suffix! ;</lang>
scan-token scan-token
[ first ] [ [ digit> ] { } map-as >list ] bi*
swap digits get set-at ;</lang>

Latest revision as of 22:02, 5 August 2021

Source code

<lang factor>USING: ascii assocs kernel lexer lists lists.lazy math math.functions math.parser namespaces pair-rocket parser sequences words.constant ; IN: numspec

SYMBOL: digits

H{

   CHAR: E => L{ 0 2 4 6 8 }
   CHAR: e => L{ 2 4 6 8 }
   CHAR: f => L{ 2 4 6 }
   CHAR: o => L{ 1 3 5 7 9 }
   CHAR: s => L{ 1 2 3 4 5 6 7 8 9 }
   CHAR: p => L{ 2 3 5 7 }
   CHAR: q => L{ 1 3 7 9 }
   CHAR: r => L{ 3 5 7 }
   CHAR: _ => L{ 0 1 2 3 4 5 6 7 8 9 }

}

digits set-global

<PRIVATE

digits>number ( {5,2,4} -- 524 )
   <reversed> 0 [ 10^ * + ] reduce-index ;
parse-digit ( n -- list )
   dup digit? [ digit> 1list ] [ digits get at ] if ;
(parse-digits-spec) ( str -- list-of-lists )
   [ parse-digit ] { } map-as >list ;
parse-digits-spec ( str -- list-of-lists )
   dup length 1 = [ CHAR: 0 prefix ] when (parse-digits-spec) ;
(parse-numspec) ( seq -- list-of-lists-of-lists )
   [ parse-digits-spec ] map >list ;
extrapolate ( list -- list' )
   uncons uncons dupd cons cons cons ;
>infinite ( list -- list' ) [ extrapolate ] lfrom-by ;
infinitize ( seq -- list )
   but-last unclip-last [ (parse-numspec) ]
   [ parse-digits-spec >infinite ] bi* lappend-lazy ;
parse-numspec ( seq -- list-of-lists-of-lists )
   dup last "..." = [ infinitize ] [ (parse-numspec) ] if ;

PRIVATE>

numspec ( seq -- list )
   parse-numspec [ lcartesian-product* ] lmap-lazy lconcat
   [ digits>number ] lmap-lazy ;

SYNTAX: NUMSPEC:

   scan-new-word ";" parse-tokens numspec define-constant ;

SYNTAX: DIGIT:

   scan-token scan-token
   [ first ] [ [ digit> ] { } map-as >list ] bi*
   swap digits get set-at ;</lang>