]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Sat, 12 Dec 2009 00:31:58 +0000 (19:31 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Sat, 12 Dec 2009 00:31:58 +0000 (19:31 -0500)
19 files changed:
basis/circular/circular-docs.factor
basis/circular/circular-tests.factor
basis/circular/circular.factor
basis/io/files/info/unix/unix-docs.factor
basis/io/files/info/unix/unix.factor
basis/math/combinatorics/combinatorics.factor
basis/math/statistics/statistics-docs.factor
basis/math/statistics/statistics.factor
basis/sequences/parser/parser.factor
basis/sequences/product/product-docs.factor
basis/sequences/product/product.factor
basis/xml/tokenize/tokenize.factor
core/sequences/sequences-docs.factor
extra/lcd/lcd.factor
extra/poker/poker-docs.factor
extra/poker/poker-tests.factor
extra/poker/poker.factor
extra/project-euler/054/054.factor
extra/project-euler/186/186.factor

index 8abadfadd2230f54f41bb8921f50d0fbbe70de96..93d137d626d3b377a5a734652029d14a815264ae 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: help.markup help.syntax io.streams.string sequences
-math kernel ;
+math kernel quotations ;
 IN: circular
 
 HELP: <circular-string>
@@ -33,12 +33,12 @@ HELP: circular
 HELP: growing-circular
 { $description "A circular sequence that is growable." } ;
 
-HELP: push-circular
+HELP: circular-push
 { $values
      { "elt" object } { "circular" circular } }
 { $description "Pushes an element to a " { $link circular } " object." } ;
 
-HELP: push-growing-circular
+HELP: growing-circular-push
 { $values
      { "elt" object } { "circular" circular } }
 { $description "Pushes an element onto a " { $link growing-circular } " object." } ;
@@ -48,6 +48,13 @@ HELP: rotate-circular
     { "circular" circular } }
 { $description "Advances the start index of a circular object by one." } ;
 
+HELP: circular-while
+{ $values
+    { "circular" circular }
+    { "quot" quotation }
+}
+{ $description "Calls " { $snippet "quot" } " on each element of the sequence until each call yields " { $link f } " in succession." } ;
+
 ARTICLE: "circular" "Circular sequences"
 "The " { $vocab-link "circular" } " vocabulary implements the " { $link "sequence-protocol" } " to allow an arbitrary start index and wrap-around indexing." $nl
 "Creating a new circular object:"
@@ -63,8 +70,10 @@ ARTICLE: "circular" "Circular sequences"
 }
 "Pushing new elements:"
 { $subsections
-    push-circular
-    push-growing-circular
-} ;
+    circular-push
+    growing-circular-push
+}
+"Iterating over a circular until a stop condition:"
+{ $subsections circular-while } ;
 
 ABOUT: "circular"
index c3c4860f953a3e51b1f219f811ec4c015f561374..cda26df1d3f54e9e31444a1761b3ce94a6005adb 100644 (file)
@@ -23,7 +23,7 @@ IN: circular.tests
 [ "boo" ] [ "foo" <circular> CHAR: b 3 pick set-nth-unsafe >string ] unit-test
 [ "ornact" ] [ "factor" <circular> 4 over change-circular-start CHAR: n 2 pick set-nth >string ] unit-test
 
-[ "bcd" ] [ 3 <circular-string> "abcd" [ over push-circular ] each >string ] unit-test
+[ "bcd" ] [ 3 <circular-string> "abcd" [ over circular-push ] each >string ] unit-test
 
 [ { 0 0 } ] [ { 0 0 } <circular> -1 over change-circular-start >array ] unit-test
 
@@ -34,11 +34,11 @@ IN: circular.tests
 [ { } ] [ 3 <growing-circular> >array ] unit-test
 [ { 1 2 } ] [
     3 <growing-circular>
-    [ 1 swap push-growing-circular ] keep
-    [ 2 swap push-growing-circular ] keep >array
+    [ 1 swap growing-circular-push ] keep
+    [ 2 swap growing-circular-push ] keep >array
 ] unit-test
 [ { 3 4 5 } ] [
     3 <growing-circular> dup { 1 2 3 4 5 } [
-        swap push-growing-circular
+        swap growing-circular-push
     ] with each >array
 ] unit-test
index 1c0efb1c36c15c104ba8a200e39f8028a3cd3a8d..ccb70c617f534f4af67498ae0c51adf91012ad04 100644 (file)
@@ -1,57 +1,79 @@
 ! Copyright (C) 2005, 2006 Alex Chapman, Daniel Ehrenberg
 ! See http;//factorcode.org/license.txt for BSD license
 USING: kernel sequences math sequences.private strings
-accessors ;
+accessors locals fry ;
 IN: circular
 
-! a circular sequence wraps another sequence, but begins at an
-! arbitrary element in the underlying sequence.
-TUPLE: circular seq start ;
+TUPLE: circular { seq read-only } { start integer } ;
 
 : <circular> ( seq -- circular )
-    0 circular boa ;
+    0 circular boa ; inline
 
 <PRIVATE
+
 : circular-wrap ( n circular -- n circular )
     [ start>> + ] keep
     [ seq>> length rem ] keep ; inline
+
 PRIVATE>
 
-M: circular length seq>> length ;
+M: circular length seq>> length ; inline
 
-M: circular virtual@ circular-wrap seq>> ;
+M: circular virtual@ circular-wrap seq>> ; inline
 
-M: circular virtual-exemplar seq>> ;
+M: circular virtual-exemplar seq>> ; inline
 
 : change-circular-start ( n circular -- )
     #! change start to (start + n) mod length
-    circular-wrap (>>start) ;
+    circular-wrap (>>start) ; inline
 
 : rotate-circular ( circular -- )
-    [ 1 ] dip change-circular-start ;
+    [ 1 ] dip change-circular-start ; inline
 
-: push-circular ( elt circular -- )
+: circular-push ( elt circular -- )
     [ set-first ] [ rotate-circular ] bi ;
 
 : <circular-string> ( n -- circular )
-    0 <string> <circular> ;
+    0 <string> <circular> ; inline
 
 INSTANCE: circular virtual-sequence
 
-TUPLE: growing-circular < circular length ;
+TUPLE: growing-circular < circular { length integer } ;
 
-M: growing-circular length length>> ;
+M: growing-circular length length>> ; inline
 
 <PRIVATE
 
 : full? ( circular -- ? )
-    [ length ] [ seq>> length ] bi = ;
+    [ length ] [ seq>> length ] bi = ; inline
 
 PRIVATE>
 
-: push-growing-circular ( elt circular -- )
-    dup full? [ push-circular ]
+: growing-circular-push ( elt circular -- )
+    dup full? [ circular-push ]
     [ [ 1 + ] change-length set-last ] if ;
 
 : <growing-circular> ( capacity -- growing-circular )
-    { } new-sequence 0 0 growing-circular boa ;
+    { } new-sequence 0 0 growing-circular boa ; inline
+
+TUPLE: circular-iterator
+    { circular read-only } { n integer } { last-start integer } ;
+
+: <circular-iterator> ( circular -- obj )
+    0 0 circular-iterator boa ; inline
+
+<PRIVATE
+
+: (circular-while) ( iterator quot: ( obj -- ? ) -- )
+    [ [ [ n>> ] [ circular>> ] bi nth ] dip call ] 2keep
+    rot [ [ dup n>> >>last-start ] dip ] when
+    over [ n>> ] [ [ last-start>> ] [ circular>> length ] bi + 1 - ] bi = [
+        2drop
+    ] [
+        [ [ 1 + ] change-n ] dip (circular-while)
+    ] if ; inline recursive
+
+PRIVATE>
+
+: circular-while ( circular quot: ( obj -- ? ) -- )
+    [ clone ] dip [ <circular-iterator> ] dip (circular-while) ; inline
index 62837dae7e411cc75d30eec00e33ef1ec7ec765e..7b98788226bb53dc5dd7550d5f021425a2e2e448 100644 (file)
@@ -4,6 +4,18 @@ USING: classes help.markup help.syntax io.streams.string
 strings math calendar io.files.info io.files.info.unix ;
 IN: io.files.unix
 
+HELP: add-file-permissions
+{ $values
+     { "path" "a pathname string" }
+     { "n" integer } }
+{ $description "Ensures that the bits from " { $snippet "n" } " are set in the Unix file permissions for a given file." } ;
+
+HELP: remove-file-permissions
+{ $values
+     { "path" "a pathname string" }
+     { "n" integer } }
+{ $description "Ensures that the bits from " { $snippet "n" } " are cleared in the Unix file permissions for a given file." } ;
+
 HELP: file-group-id
 { $values
      { "path" "a pathname string" }
@@ -231,8 +243,12 @@ ARTICLE: "unix-file-permissions" "Unix file permissions"
     other-write?
     other-execute?
 }
-"Writing all file permissions:"
-{ $subsections set-file-permissions }
+"Changing file permissions:"
+{ $subsections
+    add-file-permissions
+    remove-file-permissions
+    set-file-permissions
+}
 "Writing individual file permissions:"
 { $subsections
     set-uid
index 0b52237a6d077eb3b7bbfb507a8d7a43c51d663b..eedf8de47ae35e93ef859a46bd6e359fd83902b2 100644 (file)
@@ -5,7 +5,7 @@ sequences combinators combinators.short-circuit alien.c-types
 vocabs.loader calendar calendar.unix io.files.info
 io.files.types io.backend io.directories unix unix.stat
 unix.time unix.users unix.groups classes.struct
-specialized-arrays ;
+specialized-arrays literals ;
 SPECIALIZED-ARRAY: timeval
 IN: io.files.info.unix
 
@@ -134,6 +134,9 @@ CONSTANT: OTHER-ALL     OCT: 0000007
 CONSTANT: OTHER-READ    OCT: 0000004
 CONSTANT: OTHER-WRITE   OCT: 0000002
 CONSTANT: OTHER-EXECUTE OCT: 0000001
+CONSTANT: ALL-READ      OCT: 0000444
+CONSTANT: ALL-WRITE     OCT: 0000222
+CONSTANT: ALL-EXECUTE   OCT: 0000111
 
 : uid? ( obj -- ? ) UID file-mode? ;
 : gid? ( obj -- ? ) GID file-mode? ;
@@ -176,6 +179,12 @@ CONSTANT: OTHER-EXECUTE OCT: 0000001
 : file-permissions ( path -- n )
     normalize-path file-info permissions>> ;
 
+: add-file-permissions ( path n -- )
+    over file-permissions bitor set-file-permissions ;
+
+: remove-file-permissions ( path n -- )
+    over file-permissions [ bitnot ] dip bitand set-file-permissions ;
+
 M: unix copy-file-and-info ( from to -- )
     [ copy-file ] [ swap file-permissions set-file-permissions ] 2bi ;
 
index 6971d88792b93f1a46451a700807043853a5162c..36b62ddcc06d0cbe53417a81d50a8a5714433af3 100644 (file)
@@ -103,23 +103,26 @@ C: <combo> combo
 : apply-combination ( m combo -- seq )
     [ combination-indices ] keep seq>> nths ;
 
+: combinations-quot ( seq k quot -- seq quot )
+    [ <combo> [ choose [0,b) ] keep ] dip
+    '[ _ apply-combination @ ] ; inline
+
 PRIVATE>
 
+: each-combination ( seq k quot -- )
+    combinations-quot each ; inline
+
+: map-combinations ( seq k quot -- )
+    combinations-quot map ; inline
+
+: map>assoc-combinations ( seq k quot exemplar -- )
+    [ combinations-quot ] dip map>assoc ; inline
+
 : combination ( m seq k -- seq )
     <combo> apply-combination ;
 
 : all-combinations ( seq k -- seq )
-    <combo> [ choose [0,b) ] keep
-    '[ _ apply-combination ] map ;
-
-: each-combination ( seq k quot -- )
-    [ <combo> [ choose [0,b) ] keep ] dip
-    '[ _ apply-combination @ ] each ; inline
-
-: map-combinations ( seq k quot -- )
-    [ <combo> [ choose [0,b) ] keep ] dip
-    '[ _ apply-combination @ ] map ; inline
+    [ ] combinations-quot map ;
 
 : reduce-combinations ( seq k identity quot -- result )
     [ -rot ] dip each-combination ; inline
-
index 9834f44add4167491d2d154b7b26e4bcf81b5d4b..bbfc787c0ffa4078335fd5f4a725b843abb54301 100644 (file)
@@ -38,7 +38,7 @@ HELP: range
 
 HELP: minmax
 { $values { "seq" sequence } { "min" real } { "max" real } }
-{ $description "Finds the minimum and maximum elements of " { $snippet "seq" } " in one pass." }
+{ $description "Finds the minimum and maximum elements of " { $snippet "seq" } " in one pass. Throws an error on an empty sequence." }
 { $examples
     { $example "USING: arrays math.statistics prettyprint ;"
         "{ 1 2 3 } minmax 2array ."
index 73a87ffb72fe95f922d4f97fafaebc65ffe4e0af..c6a600a303555dcb30a5966623fcbc0dfde7d44f 100644 (file)
@@ -89,9 +89,14 @@ PRIVATE>
     histogram >alist
     [ ] [ [ [ second ] bi@ > ] 2keep ? ] map-reduce first ;
 
+ERROR: empty-sequence ;
+
 : minmax ( seq -- min max )
-    #! find the min and max of a seq in one pass
-    [ 1/0. -1/0. ] dip [ [ min ] [ max ] bi-curry bi* ] each ;
+    [
+        empty-sequence
+    ] [
+        [ first dup ] keep [ [ min ] [ max ] bi-curry bi* ] each
+    ] if-empty ;
 
 : range ( seq -- x )
     minmax swap - ;
index 93bbbdf53d52ef480ae96ec522b4111154787b63..44fa75239cfa08acbd9e60c48f4730f3fb211641 100644 (file)
@@ -83,7 +83,7 @@ TUPLE: sequence-parser sequence n ;
     sequence length <growing-circular> :> growing
     sequence-parser
     [
-        current growing push-growing-circular
+        current growing growing-circular-push
         sequence growing sequence=
     ] take-until :> found
     growing sequence sequence= [
index 0b6805eb71526f9a3d17049c44def9acfc63502d..06c99ab806f7299b3123ee541d489193877210f2 100644 (file)
@@ -1,5 +1,5 @@
 ! (c)2009 Joe Groff bsd license
-USING: help.markup help.syntax quotations sequences ;
+USING: assocs help.markup help.syntax quotations sequences ;
 IN: sequences.product
 
 HELP: product-sequence
@@ -44,6 +44,14 @@ HELP: product-map
 { $description "Calls " { $snippet "quot" } " for every element of the cartesian product of " { $snippet "sequences" } " and collects the results from " { $snippet "quot" } " into an output sequence." }
 { $notes { $snippet "[ ... ] product-map" } " is equivalent to, but more efficient than, " { $snippet "<product-sequence> [ ... ] map" } "." } ;
 
+HELP: product-map-as
+{ $values { "sequences" sequence } { "quot" { $quotation "( sequence -- value )" } } { "exemplar" sequence } { "sequence" sequence } }
+{ $description "Calls " { $snippet "quot" } " for every element of the cartesian product of " { $snippet "sequences" } " and collects the results from " { $snippet "quot" } " into an output sequence the same type as the " { $snippet "exemplar" } " sequence." } ;
+
+HELP: product-map>assoc
+{ $values { "sequences" sequence } { "quot" { $quotation "( sequence -- key value )" } } { "exemplar" assoc } { "assoc" assoc } }
+{ $description "Calls " { $snippet "quot" } " for every element of the cartesian product of " { $snippet "sequences" } " and collects the results from " { $snippet "quot" } " into an output assoc." } ;
+
 HELP: product-each
 { $values { "sequences" sequence } { "quot" { $quotation "( sequence -- )" } } }
 { $description "Calls " { $snippet "quot" } " for every element of the cartesian product of " { $snippet "sequences" } "." }
@@ -57,6 +65,8 @@ ARTICLE: "sequences.product" "Product sequences"
     product-sequence
     <product-sequence>
     product-map
+    product-map-as
+    product-map>assoc
     product-each
 } ;
 
index f783fad31204a3744ff21b8499aee057f787b5fc..42900854821f1a73b708776108b9f46ec346c61f 100644 (file)
@@ -1,5 +1,5 @@
 ! (c)2009 Joe Groff bsd license
-USING: accessors arrays kernel locals math sequences ;
+USING: accessors arrays assocs kernel locals math sequences ;
 IN: sequences.product
 
 TUPLE: product-sequence { sequences array read-only } { lengths array read-only } ;
@@ -55,11 +55,21 @@ M: product-sequence nth
         [ ns sequences nths quot call ns lengths product-iter ] until
     ] unless ; inline
 
-:: product-map ( sequences quot -- sequence )
+:: product-map-as ( sequences quot exemplar -- sequence )
     0 :> i!
-    sequences [ length ] [ * ] map-reduce sequences
+    sequences [ length ] [ * ] map-reduce exemplar
     [| result |
         sequences [ quot call i result set-nth i 1 + i! ] product-each
         result
     ] new-like ; inline
 
+: product-map ( sequences quot -- sequence )
+    over product-map-as ; inline
+
+:: product-map>assoc ( sequences quot exemplar -- assoc )
+    0 :> i!
+    sequences [ length ] [ * ] map-reduce { }
+    [| result |
+        sequences [ quot call 2array i result set-nth i 1 + i! ] product-each
+        result
+    ] new-like exemplar assoc-like ; inline
index b0dbdf22ac83036076b8271eb0dfc3322a9c2fee..beb5983b5a61ce1f1158736e3bd0212b6de9f60d 100644 (file)
@@ -86,7 +86,7 @@ HINTS: next* { spot } ;
     spot get '[ _ char>> blank? not ] skip-until ;
 
 : string-matches? ( string circular spot -- ? )
-    char>> over push-circular sequence= ;
+    char>> over circular-push sequence= ;
 
 : take-string ( match -- string )
     dup length <circular-string>
@@ -147,7 +147,7 @@ HINTS: next* { spot } ;
 :: parse-text ( -- string )
     3 f <array> <circular> :> circ
     depth get zero? :> no-text [| char |
-        char circ push-circular
+        char circ circular-push
         circ assure-no-]]>
         no-text [ char blank? char CHAR: < = or [
             char 1string t pre/post-content
index 6d7ff241eff198c5c55541f374745741804d7203..1e966c143d3901406b2dac40cba4f3c389876da8 100644 (file)
@@ -1002,7 +1002,7 @@ HELP: pusher
            "10 [ even? ] pusher [ each ] dip ."
            "V{ 0 2 4 6 8 }"
 }
-{ $notes "Used to implement the " { $link filter } " word." } ;
+{ $notes "Used to implement the " { $link filter } " word. Compare this word with " { $link accumulator } ", which is an unfiltering version." } ;
 
 HELP: trim-head
 { $values
@@ -1671,6 +1671,19 @@ ARTICLE: "sequences-comparing" "Comparing sequences"
 ARTICLE: "sequences-f" "The f object as a sequence"
 "The " { $link f } " object supports the sequence protocol in a trivial way. It responds with a length of zero and throws an out of bounds error when an attempt is made to access elements." ;
 
+ARTICLE: "sequences-combinator-implementation" "Implementing sequence combinators"
+"Creating a new sequence unconditionally:"
+{ $subsections
+    accumulator
+    accumulator-for
+}
+"Creating a new sequence conditionally:"
+{ $subsections
+    pusher
+    pusher-for
+    2pusher
+} ;
+
 ARTICLE: "sequences" "Sequence operations"
 "A " { $emphasis "sequence" } " is a finite, linearly-ordered collection of elements. Words for working with sequences are in the " { $vocab-link "sequences" } " vocabulary."
 $nl
@@ -1708,6 +1721,8 @@ $nl
 "Using sequences for control flow:"
 { $subsections "sequences-if" }
 "For inner loops:"
-{ $subsections "sequences-unsafe" } ;
+{ $subsections "sequences-unsafe" }
+"Implemeting sequence combinators:"
+{ $subsections "sequences-combinator-implementation" } ;
 
 ABOUT: "sequences"
index 1801ee2170345d76c65e03625d33e1c46bd276dc..56aa3373e5caee610e50705199b9de8805086a34 100644 (file)
@@ -1,30 +1,26 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors sequences kernel math io calendar grouping
-calendar.format calendar.model fonts arrays models models.arrow
-namespaces ui.gadgets ui.gadgets.labels ui ;
+USING: accessors calendar.format calendar.model fonts fry
+grouping kernel math models.arrow namespaces sequences ui
+ui.gadgets.labels ;
 IN: lcd
 
-: lcd-digit ( row digit -- str )
-    dup CHAR: : = [ drop 10 ] [ CHAR: 0 - ] if swap {
+: lcd-digit ( digit row -- str )
+    [ dup CHAR: : = [ drop 10 ] [ CHAR: 0 - ] if ] dip {
         "  _       _  _       _   _   _   _   _      "
         " | |  |   _| _| |_| |_  |_    | |_| |_|  *  "
         " |_|  |  |_  _|   |  _| |_|   | |_|   |  *  "
         "                                            "
     } nth 4 <groups> nth ;
 
-: lcd-row ( num row -- string )
-    [ swap lcd-digit ] curry { } map-as concat ;
+: lcd-row ( row digit -- string )
+    '[ _ lcd-digit ] { } map-as concat ;
 
 : lcd ( digit-str -- string )
-    4 [ lcd-row ] with map "\n" join ;
+    4 iota [ lcd-row ] with map "\n" join ;
 
-: hh:mm:ss ( timestamp -- string )
-    [ hour>> ] [ minute>> ] [ second>> >fixnum ] tri
-    3array [ pad-00 ] map ":" join ;
-
-: <time-display> ( timestamp -- gadget )
-    [ hh:mm:ss lcd ] <arrow> <label-control>
+: <time-display> ( model -- gadget )
+    [ timestamp>hms lcd ] <arrow> <label-control>
     "99:99:99" lcd >>string
     monospace-font >>font ;
 
index fef47b859c212d40a21c8e33fb88b84499e6fd45..ecdcf3f59108e6142fc52c68afc1e255465c0866 100644 (file)
@@ -1,46 +1,16 @@
-USING: help.markup help.syntax strings ;
+USING: help.markup help.syntax math sequences strings ;
 IN: poker
 
-HELP: <hand>
-{ $values { "str" string } { "hand" "a new " { $link hand } } }
-{ $description "Creates a new poker hand containing the cards specified in " { $snippet "str" } "." }
+HELP: best-holdem-hand
+{ $values { "hand" sequence } { "n" integer } { "cards" sequence } }
+{ $description "Creates a new poker hand containing the best possible combination of the cards specified in " { $snippet "seq" } "." }
 { $examples
-    { $example "USING: kernel math.order poker prettyprint ;"
-        "\"AC KC QC JC TC\" \"7C 6D 5H 4S 2C\" [ <hand> ] bi@ <=> ." "+lt+" }
     { $example "USING: kernel poker prettyprint ;"
-        "\"TC 9C 8C 7C 6C\" \"TH 9H 8H 7H 6H\" [ <hand> ] bi@ = ." "t" }
-}
-{ $notes "Cards may be specified in any order. Hands are directly comparable to each other on the basis of their computed value. Two hands are considered equal when they would tie in a game (despite being composed of different cards)." } ;
-
-HELP: best-hand
-{ $values { "str" string } { "hand" "a new " { $link hand } } }
-{ $description "Creates a new poker hand containing the best possible combination of the cards specified in " { $snippet "str" } "." }
-{ $examples
-    { $example "USING: kernel poker prettyprint ;"
-        "\"AS KD JC KH 2D 2S KC\" best-hand >value ." "\"Full House\"" }
+        "HAND{ AS KD JC KH 2D 2S KC } best-holdem-hand drop value>hand-name ."
+        """"Full House""""
+    }
 } ;
 
-HELP: >cards
-{ $values { "hand" hand } { "str" string } }
-{ $description "Outputs a string representation of a hand's cards." }
-{ $examples
-    { $example "USING: poker prettyprint ;"
-        "\"AC KC QC JC TC\" <hand> >cards ." "\"AC KC QC JC TC\"" }
-} ;
-
-HELP: >value
-{ $values { "hand" hand } { "str" string } }
-{ $description "Outputs a string representation of a hand's value." }
-{ $examples
-    { $example "USING: poker prettyprint ;"
-        "\"AC KC QC JC TC\" <hand> >value ." "\"Straight Flush\"" }
-}
-{ $notes "This should not be used as a basis for hand comparison." } ;
-
 HELP: <deck>
-{ $values { "deck" "a new " { $link deck } } }
-{ $description "Creates a standard deck of 52 cards." } ;
-
-HELP: shuffle
-{ $values { "deck" deck } { "deck" "a shuffled " { $link deck } } }
-{ $description "Shuffles the cards in " { $snippet "deck" } ", in-place, using the Fisher-Yates algorithm." } ;
+{ $values { "deck" sequence } }
+{ $description "Returns a vector containing a standard, shuffled deck of 52 cards." } ;
index 6b05178462bfc4ffddb13fa2cb815ecb720471d3..fc10a136595e82d76dd4ed11f88fe78c455efaf2 100644 (file)
@@ -1,30 +1,28 @@
-USING: accessors kernel math.order poker poker.private tools.test ;
+USING: accessors kernel math math.order poker poker.private
+tools.test ;
 IN: poker.tests
 
 [ 134236965 ] [ "KD" >ckf ] unit-test
 [ 529159 ] [ "5s" >ckf ] unit-test
 [ 33589533 ] [ "jc" >ckf ] unit-test
 
-[ 7462 ] [ "7C 5D 4H 3S 2C" <hand> value>> ] unit-test
-[ 1601 ] [ "KD QS JC TH 9S" <hand> value>> ] unit-test
-[ 11 ] [ "AC AD AH AS KC" <hand> value>> ] unit-test
-[ 9 ] [ "6C 5C 4C 3C 2C" <hand> value>> ] unit-test
-[ 1 ] [ "AC KC QC JC TC" <hand> value>> ] unit-test
+[ 7462 ] [ "7C 5D 4H 3S 2C" string>value ] unit-test
+[ 1601 ] [ "KD QS JC TH 9S" string>value ] unit-test
+[ 11 ] [ "AC AD AH AS KC" string>value ] unit-test
+[ 9 ] [ "6C 5C 4C 3C 2C" string>value ] unit-test
+[ 1 ] [ "AC KC QC JC TC" string>value ] unit-test
 
-[ "High Card" ] [ "7C 5D 4H 3S 2C" <hand> >value ] unit-test
-[ "Straight" ] [ "KD QS JC TH 9S" <hand> >value ] unit-test
-[ "Four of a Kind" ] [ "AC AD AH AS KC" <hand> >value ] unit-test
-[ "Straight Flush" ] [ "6C 5C 4C 3C 2C" <hand> >value ] unit-test
+[ "High Card" ] [ "7C 5D 4H 3S 2C" string>hand-name ] unit-test
+[ "Straight" ] [ "KD QS JC TH 9S" string>hand-name ] unit-test
+[ "Four of a Kind" ] [ "AC AD AH AS KC" string>hand-name ] unit-test
+[ "Straight Flush" ] [ "6C 5C 4C 3C 2C" string>hand-name ] unit-test
 
-[ "6C 5C 4C 3C 2C" ] [ "6C 5C 4C 3C 2C" <hand> >cards ] unit-test
+[ t ] [ "7C 5D 4H 3S 2C" "KD QS JC TH 9S" [ string>value ] bi@ > ] unit-test
+[ t ] [ "AC AD AH AS KC" "KD QS JC TH 9S" [ string>value ] bi@ < ] unit-test
+[ t ] [ "7C 5D 4H 3S 2C" "7D 5D 4D 3C 2S" [ string>value ] bi@ = ] unit-test
 
-[ +gt+ ] [ "7C 5D 4H 3S 2C" "KD QS JC TH 9S" [ <hand> ] bi@ <=> ] unit-test
-[ +lt+ ] [ "AC AD AH AS KC" "KD QS JC TH 9S" [ <hand> ] bi@ <=> ] unit-test
-[ +eq+ ] [ "7C 5D 4H 3S 2C" "7D 5D 4D 3C 2S" [ <hand> ] bi@ <=> ] unit-test
+[ t ] [ "7C 5D 4H 3S 2C" "2C 3S 4H 5D 7C" [ string>value ] bi@ = ] unit-test
 
-[ t ] [ "7C 5D 4H 3S 2C" "2C 3S 4H 5D 7C" [ <hand> ] bi@ = ] unit-test
+[ t ] [ "7C 5D 4H 3S 2C" "7D 5D 4D 3C 2S" [ string>value ] bi@ = ] unit-test
 
-[ t ] [ "7C 5D 4H 3S 2C" "7D 5D 4D 3C 2S" [ <hand> ] bi@ = ] unit-test
-[ f ] [ "7C 5D 4H 3S 2C" "7D 5D 4D 3C 2S" [ <hand> ] bi@ eq? ] unit-test
-
-[ 190 ] [ "AS KD JC KH 2D 2S KC" best-hand value>> ] unit-test
+[ 190 ] [ "AS KD JC KH 2D 2S KC" string>value ] unit-test
index a5a5a936284f4cfa2d6d31e0e4e6c38d76a4a4aa..59f50509e4513bf7c6a106cf98253a0426df7816 100644 (file)
@@ -1,9 +1,11 @@
 ! Copyright (c) 2009 Aaron Schaefer. All rights reserved.
+! Copyright (c) 2009 Doug Coleman.
 ! The contents of this file are licensed under the Simplified BSD License
 ! A copy of the license is available at http://factorcode.org/license.txt
-USING: accessors arrays ascii binary-search combinators kernel locals math
-    math.bitwise math.combinatorics math.order poker.arrays random sequences
-    sequences.product splitting ;
+USING: accessors arrays ascii assocs binary-search combinators
+fry kernel locals math math.bitwise math.combinatorics
+math.order math.statistics poker.arrays random sequences
+sequences.product splitting grouping lexer strings ;
 IN: poker
 
 ! The algorithm used is based on Cactus Kev's Poker Hand Evaluator with
@@ -108,11 +110,13 @@ CONSTANT: VALUE_STR { "Straight Flush" "Four of a Kind" "Full House" "Flush"
 :: (>ckf) ( rank suit -- n )
     rank rank suit rank card-bitfield ;
 
-: >ckf ( str -- n )
-    #! Cactus Kev Format
-    >upper 1 cut (>ckf) ;
+#! Cactus Kev Format
+GENERIC: >ckf ( string -- n )
 
-: parse-cards ( str -- seq )
+M: string >ckf >upper 1 cut (>ckf) ;
+M: integer >ckf ;
+
+: parse-cards ( string -- seq )
     " " split [ >ckf ] map ;
 
 : flush? ( cards -- ? )
@@ -148,10 +152,10 @@ CONSTANT: VALUE_STR { "Straight Flush" "Four of a Kind" "Full House" "Flush"
         ] if
     ] if ;
 
-: >card-rank ( card -- str )
+: >card-rank ( card -- string )
     -8 shift HEX: F bitand RANK_STR nth ;
 
-: >card-suit ( card -- str )
+: >card-suit ( card -- string )
     {
         { [ dup 15 bit? ] [ drop "C" ] }
         { [ dup 14 bit? ] [ drop "D" ] }
@@ -159,7 +163,7 @@ CONSTANT: VALUE_STR { "Straight Flush" "Four of a Kind" "Full House" "Flush"
         [ drop "S" ]
     } cond ;
 
-: hand-rank ( value -- rank )
+: value>rank ( value -- rank )
     {
         { [ dup 6185 > ] [ drop HIGH_CARD ] }        ! 1277 high card
         { [ dup 3325 > ] [ drop ONE_PAIR ] }         ! 2860 one pair
@@ -172,38 +176,92 @@ CONSTANT: VALUE_STR { "Straight Flush" "Four of a Kind" "Full House" "Flush"
         [ drop STRAIGHT_FLUSH ]                      !   10 straight-flushes
     } cond ;
 
-: card>string ( card -- str )
+: card>string ( n -- string )
     [ >card-rank ] [ >card-suit ] bi append ;
 
 PRIVATE>
 
-TUPLE: hand
-    { cards sequence }
-    { value integer initial: 9999 } ;
-
-M: hand <=> [ value>> ] compare ;
-M: hand equal?
-    over hand? [ [ value>> ] bi@ = ] [ 2drop f ] if ;
-
-: <hand> ( str -- hand )
-    parse-cards dup hand-value hand boa ;
-
-: best-hand ( str -- hand )
-    parse-cards 5 hand new
-    [ dup hand-value hand boa min ] reduce-combinations ;
-
-: >cards ( hand -- str )
-    cards>> [ card>string ] map " " join ;
-
-: >value ( hand -- str )
-    value>> hand-rank VALUE_STR nth ;
-
-TUPLE: deck
-    { cards sequence } ;
-
 : <deck> ( -- deck )
-    RANK_STR SUIT_STR 2array [ concat >ckf ] product-map deck boa ;
-
-: shuffle ( deck -- deck )
-    [ randomize ] change-cards ;
-
+    RANK_STR SUIT_STR 2array
+    [ concat >ckf ] V{ } product-map-as randomize ;
+
+: best-holdem-hand ( hand -- n cards )
+    5 [ [ hand-value ] [ ] bi ] { } map>assoc-combinations
+    infimum first2 ;
+
+: value>string ( n -- string )
+    value>rank VALUE_STR nth ;
+
+: hand>card-names ( hand -- string )
+    [ card>string ] map ;
+
+: string>value ( string -- value )
+    parse-cards best-holdem-hand drop ;
+
+ERROR: no-card card deck ;
+
+: draw-specific-card ( card deck -- card )
+    [ >ckf ] dip
+    2dup index [ swap remove-nth! drop ] [ no-card ] if* ;
+
+: start-hands ( seq -- seq' deck )
+    <deck> [ '[ [ _ draw-specific-card ] map ] map ] keep ;
+
+:: holdem-hand% ( hole1 deck community n -- x )
+    community length 5 swap - 2 + :> #samples
+    n [
+        drop
+        deck #samples sample :> sampled
+        sampled 2 cut :> ( hole2 community2 )
+        hole1 community community2 3append :> hand1
+        hole2 community community2 3append :> hand2
+        hand1 hand2 [ best-holdem-hand 2array ] bi@ <=> +lt+ =
+    ] count ;
+
+:: compare-holdem-hands ( holes deck n -- seq )
+    n [
+        holes deck 5 sample '[
+            [ _ append best-holdem-hand drop ] keep
+        ] { } map>assoc infimum second
+    ] replicate histogram ;
+
+: (best-omaha-hand) ( seq -- pair )
+    4 cut
+    [ 2 all-combinations ] [ 3 all-combinations ] bi*
+    2array [ concat [ best-holdem-hand drop ] keep ] { } product-map>assoc ;
+
+: best-omaha-hand ( seq -- n cards ) (best-omaha-hand) infimum first2 ;
+
+:: compare-omaha-hands ( holes deck n -- seq )
+    n [
+        holes deck 5 sample '[
+            [ _ append best-omaha-hand drop ] keep
+        ] { } map>assoc infimum second
+    ] replicate histogram ;
+
+ERROR: bad-suit-symbol ch ;
+
+: symbol>suit ( ch -- ch' )
+    ch>upper
+    H{
+        { CHAR: ♠ CHAR: S }
+        { CHAR: ♦ CHAR: D }
+        { CHAR: ♥ CHAR: H }
+        { CHAR: ♣ CHAR: C }
+        { CHAR: S CHAR: S }
+        { CHAR: D CHAR: D }
+        { CHAR: H CHAR: H }
+        { CHAR: C CHAR: C }
+    } ?at [ bad-suit-symbol ] unless ;
+
+: card> ( string -- card )
+    1 over [ symbol>suit ] change-nth >ckf ;
+
+: value>hand-name ( value -- string )
+    value>rank VALUE_STR nth ;
+
+: string>hand-name ( string -- string' )
+    string>value value>hand-name ;
+
+SYNTAX: HAND{
+    "}" parse-tokens [ card> ] { } map-as suffix! ;
index 5cf42737fb1237258905e4207c3eb0285b6131da..dedd769059dcb2e6f20a0dc432477e85f888be29 100644 (file)
@@ -76,7 +76,7 @@ IN: project-euler.054
 PRIVATE>
 
 : euler054 ( -- answer )
-    source-054 [ [ <hand> ] map first2 before? ] count ;
+    source-054 [ [ string>value ] map first2 before? ] count ;
 
 ! [ euler054 ] 100 ave-time
 ! 34 ms ave run time - 2.65 SD (100 trials)
index ed4f03dda1aabc8a3a13e5004234bc20260b1b77..922a28cb22c51f21a0212937bc635b545f0a3129 100644 (file)
@@ -45,7 +45,7 @@ IN: project-euler.186
     55 [1,b] [ (generator) ] map <circular> ;
 
 : advance ( lag -- )
-    [ { 0 31 } swap nths sum 1000000 rem ] keep push-circular ;
+    [ { 0 31 } swap nths sum 1000000 rem ] keep circular-push ;
 
 : next ( lag -- n )
     [ first ] [ advance ] bi ;