Merge branch 'master' of git://factorcode.org/git/factor

db4
Doug Coleman 2008-12-04 06:29:14 -06:00
commit ed248ebad4
29 changed files with 194 additions and 39 deletions

View File

@ -1,4 +1,22 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: tools.test interpolate ;
USING: interpolate io.streams.string namespaces tools.test locals ;
IN: interpolate.tests
[ "Hello, Jane." ] [
"Jane" "name" set
[ "Hello, ${name}." interpolate ] with-string-writer
] unit-test
[ "Sup Dawg, we heard you liked rims, so we put rims on your rims so you can roll while you roll." ] [
"Dawg" "name" set
"rims" "noun" set
"roll" "verb" set
[ "Sup ${name}, we heard you liked ${noun}, so we put ${noun} on your ${noun} so you can ${verb} while you ${verb}." interpolate ] with-string-writer
] unit-test
[ "Oops, I accidentally the whole economy..." ] [
[let | noun [ "economy" ] |
[ I[ Oops, I accidentally the whole ${noun}...]I ] with-string-writer
]
] unit-test

View File

@ -1,21 +1,40 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: io kernel macros make multiline namespaces parser
peg.ebnf present sequences strings ;
present sequences strings splitting fry accessors ;
IN: interpolate
MACRO: interpolate ( string -- )
[EBNF
var = "${" [^}]+ "}" => [[ second >string [ get present write ] curry ]]
text = [^$]+ => [[ >string [ write ] curry ]]
interpolate = (var|text)* => [[ [ ] join ]]
EBNF] ;
TUPLE: interpolate-var name ;
EBNF: interpolate-locals
var = "${" [^}]+ "}" => [[ [ second >string search , [ present write ] % ] [ ] make ]]
text = [^$]+ => [[ [ >string , [ write ] % ] [ ] make ]]
interpolate = (var|text)* => [[ [ ] join ]]
;EBNF
: (parse-interpolate) ( string -- )
[
"${" split1-slice [ >string , ] [
[
"}" split1-slice
[ >string interpolate-var boa , ]
[ (parse-interpolate) ] bi*
] when*
] bi*
] unless-empty ;
: parse-interpolate ( string -- seq )
[ (parse-interpolate) ] { } make ;
MACRO: interpolate ( string -- )
parse-interpolate [
dup interpolate-var?
[ name>> '[ _ get present write ] ]
[ '[ _ write ] ]
if
] map [ ] join ;
: interpolate-locals ( string -- quot )
parse-interpolate [
dup interpolate-var?
[ name>> search '[ _ present write ] ]
[ '[ _ write ] ]
if
] map [ ] join ;
: I[ "]I" parse-multiline-string
interpolate-locals parsed \ call parsed ; parsing

View File

@ -3,13 +3,14 @@ IN: math.statistics
HELP: geometric-mean
{ $values { "seq" "a sequence of numbers" } { "n" "a non-negative real number"} }
{ $description "Computes the geometric mean of all elements in " { $snippet "seq" } ". The geometric mean measures the central tendency of a data set that minimizes the effects of extreme values." }
{ $description "Computes the geometric mean of all elements in " { $snippet "seq" } ". The geometric mean measures the central tendency of a data set that minimizes the effects of extreme values." }
{ $examples { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } geometric-mean ." "1.81712059283214" } }
{ $errors "Throws a " { $link signal-error. } " (square-root of 0) if the sequence is empty." } ;
HELP: harmonic-mean
{ $values { "seq" "a sequence of numbers" } { "n" "a non-negative real number"} }
{ $description "Computes the harmonic mean of the elements in " { $snippet "seq" } ". The harmonic mean is appropriate when the average of rates is desired." }
{ $description "Computes the harmonic mean of the elements in " { $snippet "seq" } ". The harmonic mean is appropriate when the average of rates is desired." }
{ $notes "Positive reals only." }
{ $examples { $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } harmonic-mean ." "6/11" } }
{ $errors "Throws a " { $link signal-error. } " (divide by zero) if the sequence is empty." } ;
@ -36,21 +37,21 @@ HELP: range
HELP: std
{ $values { "seq" "a sequence of numbers" } { "x" "a non-negative real number"} }
{ $description "Computes the standard deviation of " { $snippet "seq" } " by squaring the variance of the sequence. It measures how widely spread the values in a sequence are about the mean." }
{ $description "Computes the standard deviation of " { $snippet "seq" } ", which is the square root of the variance. It measures how widely spread the values in a sequence are about the mean." }
{ $examples
{ $example "USING: math.statistics prettyprint ;" "{ 1 2 3 } std ." "1.0" }
{ $example "USING: math.statistics prettyprint ;" "{ 1 2 3 4 } std ." "1.290994448735806" } } ;
HELP: ste
{ $values { "seq" "a sequence of numbers" } { "x" "a non-negative real number"} }
{ $description "Computes the standard error of the mean for " { $snippet "seq" } ". It's defined as the standard deviation divided by the square root of the length of the sequence, and measures uncertainty associated with the estimate of the mean." }
{ $description "Computes the standard error of the mean for " { $snippet "seq" } ". It's defined as the standard deviation divided by the square root of the length of the sequence, and measures uncertainty associated with the estimate of the mean." }
{ $examples
{ $example "USING: math.statistics prettyprint ;" "{ -2 2 } ste ." "2.0" }
{ $example "USING: math.statistics prettyprint ;" "{ -2 2 2 } ste ." "1.333333333333333" } } ;
HELP: var
{ $values { "seq" "a sequence of numbers" } { "x" "a non-negative real number"} }
{ $description "Computes the variance of " { $snippet "seq" } ". It's a measurement of the spread of values in a sequence. The larger the variance, the larger the distance of values from the mean." }
{ $description "Computes the variance of " { $snippet "seq" } ". It's a measurement of the spread of values in a sequence. The larger the variance, the larger the distance of values from the mean." }
{ $notes "If the number of elements in " { $snippet "seq" } " is 1 or less, it outputs 0." }
{ $examples
{ $example "USING: math.statistics prettyprint ;" "{ 1 } var ." "0" }

View File

@ -5,20 +5,15 @@ USING: arrays combinators kernel math math.analysis math.functions sequences
IN: math.statistics
: mean ( seq -- n )
#! arithmetic mean, sum divided by length
[ sum ] [ length ] bi / ;
: geometric-mean ( seq -- n )
#! geometric mean, nth root of product
[ length ] [ product ] bi nth-root ;
: harmonic-mean ( seq -- n )
#! harmonic mean, reciprocal of sum of reciprocals.
#! positive reals only
[ recip ] sigma recip ;
: median ( seq -- n )
#! middle number if odd, avg of two middle numbers if even
natural-sort dup length even? [
[ midpoint@ dup 1- 2array ] keep nths mean
] [
@ -26,11 +21,10 @@ IN: math.statistics
] if ;
: range ( seq -- n )
#! max - min
minmax swap - ;
: var ( seq -- x )
#! variance, normalize by N-1
#! normalize by N-1
dup length 1 <= [
drop 0
] [
@ -39,11 +33,9 @@ IN: math.statistics
] if ;
: std ( seq -- x )
#! standard deviation, sqrt of variance
var sqrt ;
: ste ( seq -- x )
#! standard error, standard deviation / sqrt ( length of sequence )
[ std ] [ length ] bi sqrt / ;
: ((r)) ( mean(x) mean(y) {x} {y} -- (r) )

View File

@ -758,12 +758,10 @@ $nl
"Technically, the spread combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on three related values can be written in one of two ways:"
{ $code
"! First alternative; uses dip"
"[ [ 1 + ] dip 1 - dip ] 2 *"
"[ [ 1 + ] dip 1 - ] dip 2 *"
"! Second alternative: uses tri*"
"[ 1 + ] [ 1 - ] [ 2 * ] tri*"
}
$nl
"A generalization of the above combinators to any number of quotations can be found in " { $link "combinators" } "."
{ $subsection "spread-shuffle-equivalence" } ;

View File

@ -6,7 +6,7 @@ ARTICLE: "floats" "Floats"
"Rational numbers represent " { $emphasis "exact" } " quantities. On the other hand, a floating point number is an " { $emphasis "approximation" } ". While rationals can grow to any required precision, floating point numbers are fixed-width, and manipulating them is usually faster than manipulating ratios or bignums (but slower than manipulating fixnums). Floating point numbers are often used to represent irrational numbers, which have no exact representation as a ratio of two integers."
$nl
"Introducing a floating point number in a computation forces the result to be expressed in floating point."
{ $example "5/4 1/2 + ." "7/4" }
{ $example "5/4 1/2 + ." "1+3/4" }
{ $example "5/4 0.5 + ." "1.75" }
"Integers and rationals can be converted to floats:"
{ $subsection >float }

View File

@ -3,3 +3,4 @@ IN: project-euler.002.tests
[ 4613732 ] [ euler002 ] unit-test
[ 4613732 ] [ euler002a ] unit-test
[ 4613732 ] [ euler002b ] unit-test

View File

@ -1,4 +1,4 @@
! Copyright (c) 2007 Aaron Schaefer, Alexander Solovyov.
! Copyright (c) 2007, 2008 Aaron Schaefer, Alexander Solovyov, Vishal Talwar.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel math sequences shuffle ;
IN: project-euler.002
@ -50,4 +50,31 @@ PRIVATE>
! [ euler002a ] 100 ave-time
! 0 ms ave run time - 0.2 SD (100 trials)
MAIN: euler002a
<PRIVATE
: next-fibs ( x y -- y x+y )
tuck + ;
: ?retotal ( total fib- fib+ -- retotal fib- fib+ )
dup even? [ [ nip + ] 2keep ] when ;
: (sum-even-fibs-below) ( partial fib- fib+ max -- total )
2dup > [
3drop
] [
[ ?retotal next-fibs ] dip (sum-even-fibs-below)
] if ;
PRIVATE>
: sum-even-fibs-below ( max -- sum )
[ 0 0 1 ] dip (sum-even-fibs-below) ;
: euler002b ( -- answer )
4000000 sum-even-fibs-below ;
! [ euler002b ] 100 ave-time
! 0 ms ave run time - 0.0 SD (100 trials)
MAIN: euler002b

View File

@ -0,0 +1,6 @@
USING: project-euler.050 project-euler.050.private tools.test ;
IN: project-euler.050.tests
[ 41 ] [ 100 solve ] unit-test
[ 953 ] [ 1000 solve ] unit-test
[ 997651 ] [ euler050 ] unit-test

View File

@ -0,0 +1,90 @@
! Copyright (c) 2008 Aaron Schaefer.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays kernel locals math math.primes sequences ;
IN: project-euler.050
! http://projecteuler.net/index.php?section=problems&id=50
! DESCRIPTION
! -----------
! The prime 41, can be written as the sum of six consecutive primes:
! 41 = 2 + 3 + 5 + 7 + 11 + 13
! This is the longest sum of consecutive primes that adds to a prime below
! one-hundred.
! The longest sum of consecutive primes below one-thousand that adds to a
! prime, contains 21 terms, and is equal to 953.
! Which prime, below one-million, can be written as the sum of the most
! consecutive primes?
! SOLUTION
! --------
! 1) Create an sequence of all primes under 1000000.
! 2) Start summing elements in the sequence until the next number would put you
! over 1000000.
! 3) Check if that sum is prime, if not, subtract the last number added.
! 4) Repeat step 3 until you get a prime number, and store it along with the
! how many consecutive numbers from the original sequence it took to get there.
! 5) Drop the first number from the sequence of primes, and do steps 2-4 again
! 6) Compare the longest chain from the first run with the second run, and store
! the longer of the two.
! 7) If the sequence of primes is still longer than the longest chain, then
! repeat steps 5-7...otherwise, you've found the longest sum of consecutive
! primes!
<PRIVATE
:: sum-upto ( seq limit -- length sum )
0 seq [ + dup limit > ] find
[ swapd - ] [ drop seq length swap ] if* ;
: pop-until-prime ( seq sum -- seq prime )
over length 0 > [
[ unclip-last-slice ] dip swap -
dup prime? [ pop-until-prime ] unless
] [
2drop { } 0
] if ;
! a pair is { length of chain, prime the chain sums to }
: longest-prime ( seq limit -- pair )
dupd sum-upto dup prime? [
2array nip
] [
[ head-slice ] dip pop-until-prime
[ length ] dip 2array
] if ;
: longest ( pair pair -- longest )
2dup [ first ] bi@ > [ drop ] [ nip ] if ;
: continue? ( pair seq -- ? )
[ first ] [ length 1- ] bi* < ;
: (find-longest) ( best seq limit -- best )
[ longest-prime longest ] 2keep 2over continue? [
[ rest-slice ] dip (find-longest)
] [ 2drop ] if ;
: find-longest ( seq limit -- best )
{ 1 2 } -rot (find-longest) ;
: solve ( n -- answer )
[ primes-upto ] keep find-longest second ;
PRIVATE>
: euler050 ( -- answer )
1000000 solve ;
! [ euler050 ] 100 ave-time
! 291 ms run / 20.6 ms GC ave time - 100 trials
MAIN: euler050

View File

@ -1,21 +1,24 @@
! Copyright (c) 2007 Aaron Schaefer.
! Copyright (c) 2007, 2008 Aaron Schaefer.
! See http://factorcode.org/license.txt for BSD license.
USING: continuations fry io kernel make math math.functions math.parser
math.statistics memory tools.time ;
IN: project-euler.ave-time
: nth-place ( x n -- y )
10 swap ^ [ * round >integer ] keep /f ;
: collect-benchmarks ( quot n -- seq )
[
[ datastack ]
[ '[ _ gc benchmark , ] tuck '[ _ _ with-datastack drop ] ]
[
'[ _ gc benchmark 1000 / , ] tuck
'[ _ _ with-datastack drop ]
]
[ 1- ] tri* swap times call
] { } make ; inline
: nth-place ( x n -- y )
10 swap ^ [ * round ] keep / ;
: ave-time ( quot n -- )
[ collect-benchmarks ] keep swap
[ std 2 nth-place ] [ mean round ] bi [
[ std 2 nth-place ] [ mean round >integer ] bi [
# " ms ave run time - " % # " SD (" % # " trials)" %
] "" make print flush ; inline