diff --git a/extra/rosetta-code/100-doors/100-doors.factor b/extra/rosetta-code/100-doors/100-doors.factor new file mode 100644 index 0000000000..0a9fd69d03 --- /dev/null +++ b/extra/rosetta-code/100-doors/100-doors.factor @@ -0,0 +1,43 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: bit-arrays formatting fry kernel math math.ranges +sequences ; +IN: rosetta-code.100-doors + +! http://rosettacode.org/wiki/100_doors + +! Problem: You have 100 doors in a row that are all initially +! closed. You make 100 passes by the doors. The first time +! through, you visit every door and toggle the door (if the door +! is closed, you open it; if it is open, you close it). The second +! time you only visit every 2nd door (door #2, #4, #6, ...). The +! third time, every 3rd door (door #3, #6, #9, ...), etc, until +! you only visit the 100th door. + +! Question: What state are the doors in after the last pass? +! Which are open, which are closed? [1] + +! Alternate: As noted in this page's discussion page, the only +! doors that remain open are whose numbers are perfect squares of +! integers. Opening only those doors is an optimization that may +! also be expressed. + +CONSTANT: number-of-doors 100 + +: multiples ( n -- range ) + 0 number-of-doors rot ; + +: toggle-multiples ( n doors -- ) + [ multiples ] dip '[ _ [ not ] change-nth ] each ; + +: toggle-all-multiples ( doors -- ) + [ number-of-doors [1,b] ] dip '[ _ toggle-multiples ] each ; + +: print-doors ( doors -- ) + [ + swap "open" "closed" ? "Door %d is %s\n" printf + ] each-index ; + +: doors-main ( -- ) + number-of-doors 1 + + [ toggle-all-multiples ] [ print-doors ] bi ; diff --git a/extra/rosetta-code/ackermann/ackermann.factor b/extra/rosetta-code/ackermann/ackermann.factor new file mode 100644 index 0000000000..512517b080 --- /dev/null +++ b/extra/rosetta-code/ackermann/ackermann.factor @@ -0,0 +1,29 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: combinators locals kernel math ; +IN: rosetta-code.ackermann + +! http://rosettacode.org/wiki/Ackermann_function + +! The Ackermann function is a classic recursive example in +! computer science. It is a function that grows very quickly (in +! its value and in the size of its call tree). It is defined as +! follows: + +! A(m,n) = { +! n + 1 if m = 0 +! A(m-1, 1) if m > 0 and n = 0 +! A(m-1, A(m, n-1)) if m > 0 and n > 0 +! } + +! Its arguments are never negative and it always terminates. +! Write a function which returns the value of A(m,n). Arbitrary +! precision is preferred (since the function grows so quickly), +! but not required. + +:: ackermann ( m n -- u ) + { + { [ m 0 = ] [ n 1 + ] } + { [ n 0 = ] [ m 1 - 1 ackermann ] } + [ m 1 - m n 1 - ackermann ackermann ] + } cond ; diff --git a/extra/rosetta-code/active-object/active-object.factor b/extra/rosetta-code/active-object/active-object.factor new file mode 100644 index 0000000000..ccda709ccc --- /dev/null +++ b/extra/rosetta-code/active-object/active-object.factor @@ -0,0 +1,85 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors calendar combinators kernel locals math +math.constants math.functions prettyprint system threads timers ; +IN: rosetta-code.active-object + +! http://rosettacode.org/wiki/Active_object + +! In object-oriented programming an object is active when its +! state depends on clock. Usually an active object encapsulates a +! task that updates the object's state. To the outer world the +! object looks like a normal object with methods that can be +! called from outside. Implementation of such methods must have a +! certain synchronization mechanism with the encapsulated task in +! order to prevent object's state corruption. + +! A typical instance of an active object is an animation widget. +! The widget state changes with the time, while as an object it +! has all properties of a normal widget. + +! The task + +! Implement an active integrator object. The object has an input +! and output. The input can be set using the method Input. The +! input is a function of time. The output can be queried using the +! method Output. The object integrates its input over the time and +! the result becomes the object's output. So if the input is K(t) +! and the output is S, the object state S is changed to S + (K(t1) +! + K(t0)) * (t1 - t0) / 2, i.e. it integrates K using the trapeze +! method. Initially K is constant 0 and S is 0. + +! In order to test the object: +! * set its input to sin (2π f t), where the frequency f=0.5Hz. +! The phase is irrelevant. +! * wait 2s +! * set the input to constant 0 +! * wait 0.5s + +! Verify that now the object's output is approximately 0 (the +! sine has the period of 2s). The accuracy of the result will +! depend on the OS scheduler time slicing and the accuracy of the +! clock. + +TUPLE: active-object timer function state previous-time ; + +: apply-stack-effect ( quot -- quot' ) + [ call( x -- x ) ] curry ; inline + +: nano-to-seconds ( -- seconds ) nano-count 9 10^ / ; + +: object-times ( active-object -- t1 t2 ) + [ previous-time>> ] + [ nano-to-seconds [ >>previous-time drop ] keep ] bi ; + +:: adding-function ( t1 t2 active-object -- function ) + t2 t1 active-object function>> apply-stack-effect bi@ + + t2 t1 - * 2 / [ + ] curry ; + +: integrate ( active-object -- ) + [ object-times ] + [ adding-function ] + [ swap apply-stack-effect change-state drop ] tri ; + +: ( -- object ) + active-object new + 0 >>state + nano-to-seconds >>previous-time + [ drop 0 ] >>function + dup [ integrate ] curry 1 nanoseconds every >>timer ; + +: destroy ( active-object -- ) timer>> stop-timer ; + +: input ( object quot -- object ) >>function ; + +: output ( object -- val ) state>> ; + +: active-test ( -- ) + + [ 2 pi 0.5 * * * sin ] input + 2 seconds sleep + [ drop 0 ] input + 0.5 seconds sleep + [ output . ] [ destroy ] bi ; + +MAIN: active-test diff --git a/extra/rosetta-code/align-columns/align-columns.factor b/extra/rosetta-code/align-columns/align-columns.factor new file mode 100644 index 0000000000..8f16a7bf83 --- /dev/null +++ b/extra/rosetta-code/align-columns/align-columns.factor @@ -0,0 +1,76 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: fry io kernel math math.functions math.order sequences +splitting strings ; +IN: rosetta.align-columns + +! http://rosettacode.org/wiki/Align_columns + +! Given a text file of many lines, where fields within a line +! are delineated by a single 'dollar' character, write a program +! that aligns each column of fields by ensuring that words in each +! column are separated by at least one space. Further, allow for +! each word in a column to be either left justified, right +! justified, or center justified within its column. + +! Use the following text to test your programs: + +! Given$a$text$file$of$many$lines,$where$fields$within$a$line$ +! are$delineated$by$a$single$'dollar'$character,$write$a$program +! that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ +! column$are$separated$by$at$least$one$space. +! Further,$allow$for$each$word$in$a$column$to$be$either$left$ +! justified,$right$justified,$or$center$justified$within$its$column. + +! Note that: + +! * The example input texts lines may, or may not, have trailing +! dollar characters. +! * All columns should share the same alignment. +! * Consecutive space characters produced adjacent to the end of +! lines are insignificant for the purposes of the task. +! * Output text will be viewed in a mono-spaced font on a plain +! text editor or basic terminal. +! * The minimum space between columns should be computed from +! the text and not hard-coded. +! * It is not a requirement to add separating characters between +! or around columns. + +CONSTANT: example-text "Given$a$text$file$of$many$lines,$where$fields$within$a$line$ +are$delineated$by$a$single$'dollar'$character,$write$a$program +that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ +column$are$separated$by$at$least$one$space. +Further,$allow$for$each$word$in$a$column$to$be$either$left$ +justified,$right$justified,$or$center$justified$within$its$column." + +: split-and-pad ( text -- lines ) + "\n" split [ "$" split harvest ] map + dup [ length ] [ max ] map-reduce + '[ _ "" pad-tail ] map ; + +: column-widths ( columns -- widths ) + [ [ length ] [ max ] map-reduce ] map ; + +SINGLETONS: +left+ +middle+ +right+ ; + +GENERIC: align-string ( str n alignment -- str' ) + +M: +left+ align-string drop CHAR: space pad-tail ; +M: +right+ align-string drop CHAR: space pad-head ; + +M: +middle+ align-string + drop + over length - 2 / + [ floor CHAR: space ] + [ ceiling CHAR: space ] bi surround ; + +: align-columns ( columns alignment -- columns' ) + [ dup column-widths ] dip '[ + [ _ align-string ] curry map + ] 2map ; + +: print-aligned ( text alignment -- ) + [ split-and-pad flip ] dip align-columns flip + [ [ write " " write ] each nl ] each ; + +! USAGE: example-text +left+ print-aligned diff --git a/extra/rosetta-code/amb/amb.factor b/extra/rosetta-code/amb/amb.factor new file mode 100644 index 0000000000..1a2009a552 --- /dev/null +++ b/extra/rosetta-code/amb/amb.factor @@ -0,0 +1,43 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: backtrack continuations kernel prettyprint sequences ; +IN: rosetta-code.amb + +! http://rosettacode.org/wiki/Amb + +! Define and give an example of the Amb operator. + +! The Amb operator takes some number of expressions (or values +! if that's simpler in the language) and nondeterministically +! yields the one or fails if given no parameter, amb returns the +! value that doesn't lead to failure. + +! The example is using amb to choose four words from the following strings: + +! set 1: "the" "that" "a" +! set 2: "frog" "elephant" "thing" +! set 3: "walked" "treaded" "grows" +! set 4: "slowly" "quickly" + +! It is a failure if the last character of word 1 is not equal +! to the first character of word 2, and similarly with word 2 and +! word 3, as well as word 3 and word 4. (the only successful +! sentence is "that thing grows slowly"). + +CONSTANT: words { + { "the" "that" "a" } + { "frog" "elephant" "thing" } + { "walked" "treaded" "grows" } + { "slowly" "quickly" } +} + +: letters-match? ( str1 str2 -- ? ) [ last ] [ first ] bi* = ; + +: sentence-match? ( seq -- ? ) dup rest [ letters-match? ] 2all? ; + +: select ( seq -- seq' ) [ amb-lazy ] map ; + +: search ( -- ) + words select dup sentence-match? [ " " join ] [ fail ] if . ; + +MAIN: search diff --git a/extra/rosetta-code/anagrams-deranged/anagrams-deranged.factor b/extra/rosetta-code/anagrams-deranged/anagrams-deranged.factor new file mode 100644 index 0000000000..ef29a493b6 --- /dev/null +++ b/extra/rosetta-code/anagrams-deranged/anagrams-deranged.factor @@ -0,0 +1,51 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: assocs fry http.client io.encodings.utf8 io.files +io.files.temp kernel math math.combinatorics sequences sorting +strings urls ; + +IN: rosettacode.anagrams-deranged + +! http://rosettacode.org/wiki/Anagrams/Deranged_anagrams + +! Two or more words are said to be anagrams if they have the +! same characters, but in a different order. By analogy with +! derangements we define a deranged anagram as two words with the +! same characters, but in which the same character does not appear +! in the same position in both words. + +! The task is to use the word list at +! http://www.puzzlers.org/pub/wordlists/unixdict.txt to find and +! show the longest deranged anagram. + +: derangement? ( str1 str2 -- ? ) [ = not ] 2all? ; + +: derangements ( seq -- seq ) + 2 [ first2 derangement? ] filter-combinations ; + +: parse-dict-file ( path -- hash ) + utf8 file-lines + H{ } clone [ + '[ + [ natural-sort >string ] keep + _ [ swap suffix ] with change-at + ] each + ] keep ; + +: anagrams ( hash -- seq ) + [ nip length 1 > ] assoc-filter values ; + +: deranged-anagrams ( path -- seq ) + parse-dict-file anagrams [ derangements ] map concat ; + +: (longest-deranged-anagrams) ( path -- anagrams ) + deranged-anagrams [ first length ] sort-with last ; + +: default-word-list ( -- path ) + "unixdict.txt" temp-file dup exists? [ + URL" http://puzzlers.org/pub/wordlists/unixdict.txt" + over download-to + ] unless ; + +: longest-deranged-anagrams ( -- anagrams ) + default-word-list (longest-deranged-anagrams) ; diff --git a/extra/rosetta-code/animate-pendulum/animate-pendulum.factor b/extra/rosetta-code/animate-pendulum/animate-pendulum.factor new file mode 100644 index 0000000000..9125c7ba9d --- /dev/null +++ b/extra/rosetta-code/animate-pendulum/animate-pendulum.factor @@ -0,0 +1,60 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors arrays calendar colors.constants kernel +locals math math.constants math.functions math.rectangles +math.vectors opengl sequences system timers ui ui.gadgets ui.render ; +IN: rosetta-code.animate-pendulum + +! http://rosettacode.org/wiki/Animate_a_pendulum + +! One good way of making an animation is by simulating a +! physical system and illustrating the variables in that system +! using a dynamically changing graphical display. The classic such +! physical system is a simple gravity pendulum. + +! For this task, create a simple physical model of a pendulum +! and animate it. + +CONSTANT: g 9.81 +CONSTANT: l 20 +CONSTANT: theta0 0.5 + +: current-time ( -- time ) nano-count -9 10^ * ; + +: T0 ( -- T0 ) 2 pi l g / sqrt * * ; +: omega0 ( -- omega0 ) 2 pi * T0 / ; +: theta ( -- theta ) current-time omega0 * cos theta0 * ; + +: relative-xy ( theta l -- xy ) + [ [ sin ] [ cos ] bi ] + [ [ * ] curry ] bi* bi@ 2array ; +: theta-to-xy ( origin theta l -- xy ) relative-xy v+ ; + +TUPLE: pendulum-gadget < gadget alarm ; + +: O ( gadget -- origin ) rect-bounds [ drop ] [ first 2 / ] bi* 0 2array ; +: window-l ( gadget -- l ) rect-bounds [ drop ] [ second ] bi* ; +: gadget-xy ( gadget -- xy ) [ O ] [ drop theta ] [ window-l ] tri theta-to-xy ; + +M: pendulum-gadget draw-gadget* + COLOR: black gl-color + [ O ] [ gadget-xy ] bi gl-line ; + +M: pendulum-gadget graft* ( gadget -- ) + [ call-next-method ] + [ + dup [ relayout-1 ] curry + 20 milliseconds every >>alarm drop + ] bi ; + +M: pendulum-gadget ungraft* + [ alarm>> stop-timer ] [ call-next-method ] bi ; + +: ( -- gadget ) + pendulum-gadget new + { 500 500 } >>pref-dim ; + +: pendulum-main ( -- ) + [ "pendulum" open-window ] with-ui ; + +MAIN: pendulum-main diff --git a/extra/rosetta-code/animation/animation.factor b/extra/rosetta-code/animation/animation.factor new file mode 100644 index 0000000000..62e40a711f --- /dev/null +++ b/extra/rosetta-code/animation/animation.factor @@ -0,0 +1,52 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors timers calendar fonts kernel models sequences ui +ui.gadgets ui.gadgets.labels ui.gestures ; +FROM: models => change-model ; +IN: rosetta-code.animation + +! http://rosettacode.org/wiki/Animation + +! Animation is the foundation of a great many parts of graphical +! user interfaces, including both the fancy effects when things +! change used in window managers, and of course games. The core of +! any animation system is a scheme for periodically changing the +! display while still remaining responsive to the user. This task +! demonstrates this. + +! Create a window containing the string "Hello World! " (the +! trailing space is significant). Make the text appear to be +! rotating right by periodically removing one letter from the end +! of the string and attaching it to the front. When the user +! clicks on the text, it should reverse its direction. + +CONSTANT: sentence "Hello World! " + +TUPLE: animated-label < label-control reversed alarm ; + +: ( model -- ) + sentence animated-label new-label swap >>model + monospace-font >>font ; + +: update-string ( str reverse -- str ) + [ unclip-last prefix ] [ unclip suffix ] if ; + +: update-model ( model reversed? -- ) + [ update-string ] curry change-model ; + +animated-label + H{ + { T{ button-down } [ [ not ] change-reversed drop ] } + } set-gestures + +M: animated-label graft* + [ [ [ model>> ] [ reversed>> ] bi update-model ] curry 400 milliseconds every ] keep + alarm<< ; + +M: animated-label ungraft* + alarm>> stop-timer ; + +: animated-main ( -- ) + [ sentence "Rosetta" open-window ] with-ui ; + +MAIN: animated-main diff --git a/extra/rosetta-code/arithmetic-evaluation/arithmetic-evaluation.factor b/extra/rosetta-code/arithmetic-evaluation/arithmetic-evaluation.factor new file mode 100644 index 0000000000..cb3a553b89 --- /dev/null +++ b/extra/rosetta-code/arithmetic-evaluation/arithmetic-evaluation.factor @@ -0,0 +1,69 @@ +USING: accessors kernel locals math math.parser peg.ebnf ; +IN: rosetta-code.arithmetic-evaluation + +! http://rosettacode.org/wiki/Arithmetic_evaluation + +! Create a program which parses and evaluates arithmetic +! expressions. + +! Requirements + +! * An abstract-syntax tree (AST) for the expression must be +! created from parsing the input. +! * The AST must be used in evaluation, also, so the input may not +! be directly evaluated (e.g. by calling eval or a similar +! language feature.) +! * The expression will be a string or list of symbols like +! "(1+3)*7". +! * The four symbols + - * / must be supported as binary operators +! with conventional precedence rules. +! * Precedence-control parentheses must also be supported. + +! Note + +! For those who don't remember, mathematical precedence is as +! follows: + +! * Parentheses +! * Multiplication/Division (left to right) +! * Addition/Subtraction (left to right) + +TUPLE: operator left right ; +TUPLE: add < operator ; C: add +TUPLE: sub < operator ; C: sub +TUPLE: mul < operator ; C: mul +TUPLE: div < operator ; C:
div + +EBNF: expr-ast +spaces = [\n\t ]* +digit = [0-9] +number = (digit)+ => [[ string>number ]] + +value = spaces number:n => [[ n ]] + | spaces "(" exp:e spaces ")" => [[ e ]] + +fac = fac:a spaces "*" value:b => [[ a b ]] + | fac:a spaces "/" value:b => [[ a b
]] + | value + +exp = exp:a spaces "+" fac:b => [[ a b ]] + | exp:a spaces "-" fac:b => [[ a b ]] + | fac + +main = exp:e spaces !(.) => [[ e ]] +;EBNF + +GENERIC: eval-ast ( ast -- result ) + +M: number eval-ast ; + +: recursive-eval ( ast -- left-result right-result ) + [ left>> eval-ast ] [ right>> eval-ast ] bi ; + +M: add eval-ast recursive-eval + ; +M: sub eval-ast recursive-eval - ; +M: mul eval-ast recursive-eval * ; +M: div eval-ast recursive-eval / ; + +: evaluate ( string -- result ) + expr-ast eval-ast ; diff --git a/extra/rosetta-code/balanced-brackets/balanced-brackets.factor b/extra/rosetta-code/balanced-brackets/balanced-brackets.factor new file mode 100644 index 0000000000..be175cc9ba --- /dev/null +++ b/extra/rosetta-code/balanced-brackets/balanced-brackets.factor @@ -0,0 +1,39 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: io formatting locals kernel math sequences unicode.case ; +IN: rosetta-code.balanced-brackets + +! http://rosettacode.org/wiki/Balanced_brackets + +! Task: + +! Generate a string with N opening brackets (“[”) and N closing +! brackets (“]”), in some arbitrary order. + +! Determine whether the generated string is balanced; that is, +! whether it consists entirely of pairs of opening/closing +! brackets (in that order), none of which mis-nest. + +! Examples: + +! (empty) OK +! [] OK ][ NOT OK +! [][] OK ][][ NOT OK +! [[][]] OK []][[] NOT OK + +:: balanced ( str -- ) + 0 :> counter! + 1 :> ok! + str + [ dup length 0 > ] + [ 1 cut swap + "[" = [ counter 1 + counter! ] [ counter 1 - counter! ] if + counter 0 < [ 0 ok! ] when + ] + while + drop + ok 0 = + [ "NO" ] + [ counter 0 > [ "NO" ] [ "YES" ] if ] + if + print ; diff --git a/extra/rosetta-code/bitmap-bezier/bitmap-bezier.factor b/extra/rosetta-code/bitmap-bezier/bitmap-bezier.factor new file mode 100644 index 0000000000..e223daca92 --- /dev/null +++ b/extra/rosetta-code/bitmap-bezier/bitmap-bezier.factor @@ -0,0 +1,36 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: arrays kernel locals math math.functions math.vectors +rosetta-code.bitmap rosetta-code.bitmap-line sequences ; +IN: rosetta-code.bitmap-bezier + +! http://rosettacode.org/wiki/Bitmap/Bézier_curves/Cubic + +! Using the data storage type defined on this page for raster +! images, and the draw_line function defined in this other one, +! draw a cubic bezier curves (definition on Wikipedia). + +:: (cubic-bezier) ( P0 P1 P2 P3 -- bezier ) + [ :> x + 1 x - 3 ^ P0 n*v + 1 x - sq 3 * x * P1 n*v + 1 x - 3 * x sq * P2 n*v + x 3 ^ P3 n*v + v+ v+ v+ ] ; inline + +! gives an interval of x from 0 to 1 to map the bezier function +: t-interval ( x -- interval ) + [ iota ] keep 1 - [ / ] curry map ; + +! turns a list of points into the list of lines between them +: points-to-lines ( seq -- seq ) + dup rest [ 2array ] 2map ; + +: draw-lines ( {R,G,B} points image -- ) + [ [ first2 ] dip draw-line ] curry with each ; + +:: bezier-lines ( {R,G,B} P0 P1 P2 P3 image -- ) + ! 100 is an arbitrary value.. could be given as a parameter.. + 100 t-interval P0 P1 P2 P3 (cubic-bezier) map + points-to-lines + {R,G,B} swap image draw-lines ; diff --git a/extra/rosetta-code/bitmap-line/bitmap-line.factor b/extra/rosetta-code/bitmap-line/bitmap-line.factor new file mode 100644 index 0000000000..18d96ce0bd --- /dev/null +++ b/extra/rosetta-code/bitmap-line/bitmap-line.factor @@ -0,0 +1,45 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors arrays kernel locals math math.functions +math.ranges math.vectors rosetta-code.bitmap sequences +ui.gadgets ; +IN: rosetta-code.bitmap-line + +! http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm + +! Using the data storage type defined on this page for raster +! graphics images, draw a line given 2 points with the Bresenham's +! algorithm. + +:: line-points ( pt1 pt2 -- points ) + pt1 first2 :> y0! :> x0! + pt2 first2 :> y1! :> x1! + y1 y0 - abs x1 x0 - abs > :> steep + steep [ + y0 x0 y0! x0! + y1 x1 y1! x1! + ] when + x0 x1 > [ + x0 x1 x0! x1! + y0 y1 y0! y1! + ] when + x1 x0 - :> deltax + y1 y0 - abs :> deltay + 0 :> current-error! + deltay deltax / abs :> deltaerr + 0 :> ystep! + y0 :> y! + y0 y1 < [ 1 ystep! ] [ -1 ystep! ] if + x0 x1 1 [ + y steep [ swap ] when 2array + current-error deltaerr + current-error! + current-error 0.5 >= [ + ystep y + y! + current-error 1 - current-error! + ] when + ] { } map-as ; + +! Needs rosetta-code.bitmap for the set-pixel function and to create the image +: draw-line ( {R,G,B} pt1 pt2 image -- ) + [ line-points ] dip + [ set-pixel ] curry with each ; diff --git a/extra/rosetta-code/bitmap/bitmap.factor b/extra/rosetta-code/bitmap/bitmap.factor new file mode 100644 index 0000000000..3cac8cba12 --- /dev/null +++ b/extra/rosetta-code/bitmap/bitmap.factor @@ -0,0 +1,43 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: arrays fry kernel math.matrices sequences ; +IN: rosetta-code.bitmap + +! http://rosettacode.org/wiki/Basic_bitmap_storage + +! Show a basic storage type to handle a simple RGB raster +! graphics image, and some primitive associated functions. + +! If possible provide a function to allocate an uninitialised +! image, given its width and height, and provide 3 additional +! functions: + +! * one to fill an image with a plain RGB color, +! * one to set a given pixel with a color, +! * one to get the color of a pixel. + +! (If there are specificities about the storage or the +! allocation, explain those.) + +! Various utilities +: meach ( matrix quot -- ) [ each ] curry each ; inline +: meach-index ( matrix quot -- ) + [ swap 2array ] prepose + [ curry each-index ] curry each-index ; inline +: mmap ( matrix quot -- matrix' ) [ map ] curry map ; inline +: mmap! ( matrix quot -- matrix' ) [ map! ] curry map! ; inline +: mmap-index ( matrix quot -- matrix' ) + [ swap 2array ] prepose + [ curry map-index ] curry map-index ; inline + +: matrix-dim ( matrix -- i j ) [ length ] [ first length ] bi ; +: set-Mi,j ( elt {i,j} matrix -- ) [ first2 swap ] dip nth set-nth ; +: Mi,j ( {i,j} matrix -- elt ) [ first2 swap ] dip nth nth ; + +! The storage functions +: ( width height -- image ) + zero-matrix [ drop { 0 0 0 } ] mmap ; +: fill-image ( {R,G,B} image -- image ) + swap '[ drop _ ] mmap! ; +: set-pixel ( {R,G,B} {i,j} image -- ) set-Mi,j ; inline +: get-pixel ( {i,j} image -- pixel ) Mi,j ; inline diff --git a/extra/rosetta-code/bulls-and-cows/bulls-and-cows.factor b/extra/rosetta-code/bulls-and-cows/bulls-and-cows.factor new file mode 100644 index 0000000000..061fab3c04 --- /dev/null +++ b/extra/rosetta-code/bulls-and-cows/bulls-and-cows.factor @@ -0,0 +1,90 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors assocs combinators fry grouping hashtables +kernel locals math math.parser math.ranges random sequences +strings io ascii ; +IN: rosetta-code.bulls-and-cows + +! http://rosettacode.org/wiki/Bulls_and_cows + +! This is an old game played with pencil and paper that was +! later implemented on computer. + +! The task is for the program to create a four digit random +! number from the digits 1 to 9, without duplication. The program +! should ask for guesses to this number, reject guesses that are +! malformed, then print the score for the guess. + +! The score is computed as: + +! 1. The player wins if the guess is the same as the randomly +! chosen number, and the program ends. + +! 2. A score of one bull is accumulated for each digit in the +! guess that equals the corresponding digit in the randomly +! chosen initial number. + +! 3. A score of one cow is accumulated for each digit in the +! guess that also appears in the randomly chosen number, but in +! the wrong position. + +TUPLE: score bulls cows ; +: ( -- score ) 0 0 score boa ; + +TUPLE: cow ; +: ( -- cow ) cow new ; + +TUPLE: bull ; +: ( -- bull ) bull new ; + +: inc-bulls ( score -- score ) dup bulls>> 1 + >>bulls ; +: inc-cows ( score -- score ) dup cows>> 1 + >>cows ; + +: random-nums ( -- seq ) 9 [1,b] 4 sample ; + +: add-digits ( seq -- n ) 0 [ swap 10 * + ] reduce number>string ; + +: new-number ( -- n narr ) random-nums dup add-digits ; + +: narr>nhash ( narr -- nhash ) { 1 2 3 4 } swap zip ; + +: num>hash ( n -- hash ) + [ 1string string>number ] { } map-as narr>nhash ; + +:: cow-or-bull ( n g -- arr ) + { + { [ n first g at n second = ] [ ] } + { [ n second g value? ] [ ] } + [ f ] + } cond ; + +: add-to-score ( arr -- score ) + [ bull? [ inc-bulls ] [ inc-cows ] if ] reduce ; + +: check-win ( score -- ? ) bulls>> 4 = ; + +: sum-score ( n g -- score ? ) + '[ _ cow-or-bull ] map sift add-to-score dup check-win ; + +: print-sum ( score -- str ) + dup bulls>> number>string "Bulls: " swap append swap cows>> number>string + " Cows: " swap 3append "\n" append ; + +: (validate-readln) ( str -- ? ) dup length 4 = not swap [ letter? ] all? or ; + +: validate-readln ( -- str ) + readln dup (validate-readln) + [ "Invalid input.\nPlease enter a valid 4 digit number: " + write flush drop validate-readln ] + when ; + +: win ( -- ) "\nYou've won! Good job. You're so smart." print flush ; + +: main-loop ( x -- ) + "Enter a 4 digit number: " write flush validate-readln num>hash swap + [ sum-score swap print-sum print flush ] keep swap not + [ main-loop ] [ drop win ] if ; + +: bulls-and-cows-main ( -- ) new-number drop narr>nhash main-loop ; + +MAIN: bulls-and-cows-main diff --git a/extra/rosetta-code/catalan-numbers/catalan-numbers.factor b/extra/rosetta-code/catalan-numbers/catalan-numbers.factor new file mode 100644 index 0000000000..c136dff1d0 --- /dev/null +++ b/extra/rosetta-code/catalan-numbers/catalan-numbers.factor @@ -0,0 +1,30 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math sequences ; +IN: rosetta-code.catalan-numbers + +! http://rosettacode.org/wiki/Catalan_numbers + +! Catalan numbers are a sequence of numbers which can be defined +! directly: +! Cn = 1/(n+1)(2n n) = (2n)! / (n+1)! * n! for n >= 0 + +! Or recursively: +! C0 = 1 +! Cn+1 = sum(Ci * Cn-i)) {0..n} for n >= 0 + +! Or alternatively (also recursive): +! C0 = 1 +! Cn = (2 * (2n - 1) / (n + 1)) * Cn-1 + +! Implement at least one of these algorithms and print out the +! first 15 Catalan numbers with each. Memoization is not required, +! but may be worth the effort when using the second method above. + +: next ( seq -- newseq ) + [ ] [ last ] [ length ] tri + [ 2 * 1 - 2 * ] [ 1 + ] bi / + * suffix ; + +: catalan ( n -- seq ) + V{ 1 } swap 1 - [ next ] times ; diff --git a/extra/rosetta-code/conjugate-transpose/conjugate-transpose-tests.factor b/extra/rosetta-code/conjugate-transpose/conjugate-transpose-tests.factor new file mode 100644 index 0000000000..5391a633b9 --- /dev/null +++ b/extra/rosetta-code/conjugate-transpose/conjugate-transpose-tests.factor @@ -0,0 +1,9 @@ +USING: kernel rosetta-code.conjugate-transpose tools.test ; +IN: rosetta-code.conjugate-transpose + +{ f t f } [ + { { C{ 1 2 } 0 } { 0 C{ 3 4 } } } + [ hermitian-matrix? ] + [ normal-matrix? ] + [ unitary-matrix? ] tri +] unit-test diff --git a/extra/rosetta-code/conjugate-transpose/conjugate-transpose.factor b/extra/rosetta-code/conjugate-transpose/conjugate-transpose.factor new file mode 100644 index 0000000000..b44b7fdae1 --- /dev/null +++ b/extra/rosetta-code/conjugate-transpose/conjugate-transpose.factor @@ -0,0 +1,41 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math.functions math.matrices sequences ; +IN: rosetta-code.conjugate-transpose + +! http://rosettacode.org/wiki/Conjugate_transpose + +! Suppose that a matrix M contains complex numbers. Then the +! conjugate transpose of M is a matrix MH containing the complex +! conjugates of the matrix transposition of M. + +! This means that row j, column i of the conjugate transpose +! equals the complex conjugate of row i, column j of the original +! matrix. + +! In the next list, M must also be a square matrix. + +! A Hermitian matrix equals its own conjugate transpose: MH = M. + +! A normal matrix is commutative in multiplication with its +! conjugate transpose: MHM = MMH. + +! A unitary matrix has its inverse equal to its conjugate +! transpose: MH = M − 1. This is true iff MHM = In and iff MMH = +! In, where In is the identity matrix. + +! Given some matrix of complex numbers, find its conjugate +! transpose. Also determine if it is a Hermitian matrix, normal +! matrix, or a unitary matrix. + +: conj-t ( matrix -- conjugate-transpose ) + flip [ [ conjugate ] map ] map ; + +: hermitian-matrix? ( matrix -- ? ) + dup conj-t = ; + +: normal-matrix? ( matrix -- ? ) + dup conj-t [ m. ] [ swap m. ] 2bi = ; + +: unitary-matrix? ( matrix -- ? ) + [ dup conj-t m. ] [ length identity-matrix ] bi = ; diff --git a/extra/rosetta-code/continued-fraction/continued-fraction.factor b/extra/rosetta-code/continued-fraction/continued-fraction.factor new file mode 100644 index 0000000000..7dfcefaf08 --- /dev/null +++ b/extra/rosetta-code/continued-fraction/continued-fraction.factor @@ -0,0 +1,79 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: arrays combinators io kernel locals math math.functions +math.ranges prettyprint sequences ; +IN: rosetta-code.continued-fraction + +! http://rosettacode.org/wiki/Continued_fraction + +! A number may be represented as a continued fraction (see +! Mathworld for more information) as follows: + +! The task is to write a program which generates such a number +! and prints a real representation of it. The code should be +! tested by calculating and printing the square root of 2, +! Napier's Constant, and Pi, using the following coefficients: + +! For the square root of 2, use a0 = 1 then aN = 2. bN is always 1. +! For Napier's Constant, use a0 = 2, then aN = N. b1 = 1 then bN = N − 1. +! For Pi, use a0 = 3 then aN = 6. bN = (2N − 1)2. + +! Every continued fraction must implement these two words. +GENERIC: cfrac-a ( n cfrac -- a ) +GENERIC: cfrac-b ( n cfrac -- b ) + +! square root of 2 +SINGLETON: sqrt2 +M: sqrt2 cfrac-a + ! If n is 1, then a_n is 1, else a_n is 2. + drop { { 1 [ 1 ] } [ drop 2 ] } case ; +M: sqrt2 cfrac-b + ! Always b_n is 1. + 2drop 1 ; + +! Napier's constant +SINGLETON: napier +M: napier cfrac-a + ! If n is 1, then a_n is 2, else a_n is n - 1. + drop { { 1 [ 2 ] } [ 1 - ] } case ; +M: napier cfrac-b + ! If n is 1, then b_n is 1, else b_n is n - 1. + drop { { 1 [ 1 ] } [ 1 - ] } case ; + +SINGLETON: pi +M: pi cfrac-a + ! If n is 1, then a_n is 3, else a_n is 6. + drop { { 1 [ 3 ] } [ drop 6 ] } case ; +M: pi cfrac-b + ! Always b_n is (n * 2 - 1)^2. + drop 2 * 1 - 2 ^ ; + +:: cfrac-estimate ( cfrac terms -- number ) + terms cfrac cfrac-a ! top = last a_n + terms 1 - 1 [a,b] [ :> n + n cfrac cfrac-b swap / ! top = b_n / top + n cfrac cfrac-a + ! top = top + a_n + ] each ; + +:: decimalize ( rational prec -- string ) + rational 1 /mod ! split whole, fractional parts + prec 10^ * ! multiply fraction by 10 ^ prec + [ >integer unparse ] bi@ ! convert digits to strings + :> fraction + "." ! push decimal point + prec fraction length - + dup 0 < [ drop 0 ] when + "0" concat ! push padding zeros + fraction 4array concat ; + + + +MAIN: main diff --git a/extra/rosetta-code/count-the-coins/count-the-coins-tests.factor b/extra/rosetta-code/count-the-coins/count-the-coins-tests.factor new file mode 100644 index 0000000000..254046693a --- /dev/null +++ b/extra/rosetta-code/count-the-coins/count-the-coins-tests.factor @@ -0,0 +1,7 @@ + +USING: tools.test ; + +IN: rosetta-code.count-the-coins + +{ 242 } [ 100 { 25 10 5 1 } make-change ] unit-test +{ 13398445413854501 } [ 100000 { 100 50 25 10 5 1 } make-change ] unit-test diff --git a/extra/rosetta-code/count-the-coins/count-the-coins.factor b/extra/rosetta-code/count-the-coins/count-the-coins.factor new file mode 100644 index 0000000000..e3d4a0cfde --- /dev/null +++ b/extra/rosetta-code/count-the-coins/count-the-coins.factor @@ -0,0 +1,45 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: arrays locals math math.ranges sequences sets sorting ; +IN: rosetta-code.count-the-coins + +! http://rosettacode.org/wiki/Count_the_coins + +! There are four types of common coins in US currency: quarters +! (25 cents), dimes (10), nickels (5) and pennies (1). There are 6 +! ways to make change for 15 cents: + +! A dime and a nickel; +! A dime and 5 pennies; +! 3 nickels; +! 2 nickels and 5 pennies; +! A nickel and 10 pennies; +! 15 pennies. + +! How many ways are there to make change for a dollar using +! these common coins? (1 dollar = 100 cents). + +! Optional: + +! Less common are dollar coins (100 cents); very rare are half +! dollars (50 cents). With the addition of these two coins, how +! many ways are there to make change for $1000? (note: the answer +! is larger than 232). + + :> ways + 1 ways set-first + coins [| coin | + coin cents [a,b] [| j | + j coin - ways nth j ways [ + ] change-nth + ] each + ] each ways last ; + +PRIVATE> + +! How many ways can we make the given amount of cents +! with the given set of coins? +: make-change ( cents coins -- ways ) + members [ ] inv-sort-with (make-change) ; diff --git a/extra/rosetta-code/equilibrium-index/equilibrium-index-tests.factor b/extra/rosetta-code/equilibrium-index/equilibrium-index-tests.factor new file mode 100644 index 0000000000..f697c217e9 --- /dev/null +++ b/extra/rosetta-code/equilibrium-index/equilibrium-index-tests.factor @@ -0,0 +1,4 @@ +USING: tools.test ; +IN: rosetta-code.equilibrium-index + +{ V{ 3 6 } } [ { -7 1 5 2 -4 3 0 } equilibrium-indices ] unit-test diff --git a/extra/rosetta-code/equilibrium-index/equilibrium-index.factor b/extra/rosetta-code/equilibrium-index/equilibrium-index.factor new file mode 100644 index 0000000000..9511b27652 --- /dev/null +++ b/extra/rosetta-code/equilibrium-index/equilibrium-index.factor @@ -0,0 +1,39 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math sequences ; +IN: rosetta-code.equilibrium-index + +! http://rosettacode.org/wiki/Equilibrium_index + +! An equilibrium index of a sequence is an index into the sequence such that the sum of elements at lower indices is equal to the sum of elements at higher indices. For example, in a sequence A: +! A0 = − 7 +! A1 = 1 +! A2 = 5 +! A3 = 2 +! A4 = − 4 +! A5 = 3 +! A6 = 0 + +! 3 is an equilibrium index, because: +! A0 + A1 + A2 = A4 + A5 + A6 + +! 6 is also an equilibrium index, because: +! A0 + A1 + A2 + A3 + A4 + A5 = 0 +! (sum of zero elements is zero) + +! 7 is not an equilibrium index, because it is not a valid index +! of sequence A. + +! Write a function that, given a sequence, returns its +! equilibrium indices (if any). Assume that the sequence may be +! very long. + +: accum-left ( seq id quot -- seq ) + accumulate nip ; inline + +: accum-right ( seq id quot -- seq ) + [ ] 2dip accum-left ; inline + +: equilibrium-indices ( seq -- inds ) + 0 [ + ] [ accum-left ] [ accum-right ] 3bi [ = ] 2map + V{ } swap dup length iota [ [ suffix ] curry [ ] if ] 2each ; diff --git a/extra/rosetta-code/fizzbuzz/fizzbuzz.factor b/extra/rosetta-code/fizzbuzz/fizzbuzz.factor new file mode 100644 index 0000000000..8babf09fe9 --- /dev/null +++ b/extra/rosetta-code/fizzbuzz/fizzbuzz.factor @@ -0,0 +1,17 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: io kernel math math.functions math.parser math.ranges +sequences ; +IN: rosetta-code.fizzbuzz + +: fizz ( n -- str ) 3 divisor? "Fizz" "" ? ; + +: buzz ( n -- str ) 5 divisor? "Buzz" "" ? ; + +: fizzbuzz ( n -- str ) + dup [ fizz ] [ buzz ] bi append [ number>string ] [ nip ] if-empty ; + +: fizzbuzz-main ( -- ) + 100 [1,b] [ fizzbuzz print ] each ; + +MAIN: fizzbuzz-main diff --git a/extra/rosetta-code/gray-code/gray-code.factor b/extra/rosetta-code/gray-code/gray-code.factor new file mode 100644 index 0000000000..d2d818f15c --- /dev/null +++ b/extra/rosetta-code/gray-code/gray-code.factor @@ -0,0 +1,52 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: arrays kernel locals math math.parser math.ranges +prettyprint sequences ; +IN: rosetta-code.gray-code + +! http://rosettacode.org/wiki/Gray_code + +! Gray code is a form of binary encoding where transitions +! between consecutive numbers differ by only one bit. This is a +! useful encoding for reducing hardware data hazards with values +! that change rapidly and/or connect to slower hardware as inputs. +! It is also useful for generating inputs for Karnaugh maps in +! order from left to right or top to bottom. + +! Create functions to encode a number to and decode a number +! from Gray code. Display the normal binary representations, Gray +! code representations, and decoded Gray code values for all 5-bit +! binary numbers (0-31 inclusive, leading 0's not necessary). + +! There are many possible Gray codes. The following encodes what +! is called "binary reflected Gray code." + +! Encoding (MSB is bit 0, b is binary, g is Gray code): +! if b[i-1] = 1 +! g[i] = not b[i] +! else +! g[i] = b[i] + +! Or: +! g = b xor (b logically right shifted 1 time) + +! Decoding (MSB is bit 0, b is binary, g is Gray code): +! b[0] = g[0] +! b[i] = g[i] xor b[i-1] + +: gray-encode ( n -- n' ) dup -1 shift bitxor ; + +:: gray-decode ( n! -- n' ) + n :> p! + [ n -1 shift dup n! 0 = not ] [ + p n bitxor p! + ] while + p ; + +: gray-code-main ( -- ) + -1 32 [a,b] [ + dup [ >bin ] [ gray-encode ] bi + [ >bin ] [ gray-decode ] bi 4array . + ] each ; + +MAIN: gray-code-main diff --git a/extra/rosetta-code/hailstone-sequence/hailstone-sequence.factor b/extra/rosetta-code/hailstone-sequence/hailstone-sequence.factor new file mode 100644 index 0000000000..1b867ab025 --- /dev/null +++ b/extra/rosetta-code/hailstone-sequence/hailstone-sequence.factor @@ -0,0 +1,56 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: arrays io kernel math math.ranges prettyprint sequences vectors ; +IN: rosetta-code.hailstone-sequence + +! http://rosettacode.org/wiki/Hailstone_sequence + +! The Hailstone sequence of numbers can be generated from a +! starting positive integer, n by: + +! * If n is 1 then the sequence ends. +! * If n is even then the next n of the sequence = n/2 +! * If n is odd then the next n of the sequence = (3 * n) + 1 + +! The (unproven), Collatz conjecture is that the hailstone +! sequence for any starting number always terminates. + +! Task Description: + +! 1. Create a routine to generate the hailstone sequence for a +! number. + +! 2. Use the routine to show that the hailstone sequence for the +! number 27 has 112 elements starting with 27, 82, 41, 124 and +! ending with 8, 4, 2, 1 + +! 3. Show the number less than 100,000 which has the longest +! hailstone sequence together with that sequences length. +! (But don't show the actual sequence)! + +: hailstone ( n -- seq ) + [ 1vector ] keep + [ dup 1 number= ] + [ + dup even? [ 2 / ] [ 3 * 1 + ] if + 2dup swap push + ] until + drop ; + +: hailstone-main ( -- ) + 27 hailstone dup dup + "The hailstone sequence from 27:" print + " has length " write length . + " starts with " write 4 head [ unparse ] map ", " join print + " ends with " write 4 tail* [ unparse ] map ", " join print + + ! Maps n => { length n }, and reduces to longest Hailstone sequence. + 1 100000 [a,b) + [ [ hailstone length ] keep 2array ] + [ [ [ first ] bi@ > ] most ] map-reduce + first2 + "The hailstone sequence from " write pprint + " has length " write pprint "." print ; + +MAIN: hailstone-main + diff --git a/extra/rosetta-code/hamming-lazy/hamming-lazy.factor b/extra/rosetta-code/hamming-lazy/hamming-lazy.factor new file mode 100644 index 0000000000..02bfcaf1fb --- /dev/null +++ b/extra/rosetta-code/hamming-lazy/hamming-lazy.factor @@ -0,0 +1,38 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: combinators fry kernel lists lists.lazy locals math ; +IN: rosetta-code.hamming-lazy + +! http://rosettacode.org/wiki/Hamming_numbers#Factor + +! Hamming numbers are numbers of the form +! H = 2^i * 3^j * 5^k where i, j, k >= 0 + +! Hamming numbers are also known as ugly numbers and also +! 5-smooth numbers (numbers whose prime divisors are less or equal +! to 5). + +! Generate the sequence of Hamming numbers, in increasing order. +! In particular: + +! 1. Show the first twenty Hamming numbers. +! 2. Show the 1691st Hamming number (the last one below 231). +! 3. Show the one millionth Hamming number (if the language – or +! a convenient library – supports arbitrary-precision integers). + +:: sort-merge ( xs ys -- result ) + xs car :> x + ys car :> y + { + { [ x y < ] [ [ x ] [ xs cdr ys sort-merge ] lazy-cons ] } + { [ x y > ] [ [ y ] [ ys cdr xs sort-merge ] lazy-cons ] } + [ [ x ] [ xs cdr ys cdr sort-merge ] lazy-cons ] + } cond ; + +:: hamming ( -- hamming ) + f :> h! + [ 1 ] [ + h 2 3 5 [ '[ _ * ] lazy-map ] tri-curry@ tri + sort-merge sort-merge + ] lazy-cons h! h ; + diff --git a/extra/rosetta-code/hamming/hamming.factor b/extra/rosetta-code/hamming/hamming.factor new file mode 100644 index 0000000000..15ba190073 --- /dev/null +++ b/extra/rosetta-code/hamming/hamming.factor @@ -0,0 +1,50 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors deques dlists fry kernel make math math.order ; +IN: rosetta-code.hamming + +! http://rosettacode.org/wiki/Hamming_numbers#Factor + +! Hamming numbers are numbers of the form +! H = 2^i * 3^j * 5^k where i, j, k >= 0 + +! Hamming numbers are also known as ugly numbers and also +! 5-smooth numbers (numbers whose prime divisors are less or equal +! to 5). + +! Generate the sequence of Hamming numbers, in increasing order. +! In particular: + +! 1. Show the first twenty Hamming numbers. +! 2. Show the 1691st Hamming number (the last one below 231). +! 3. Show the one millionth Hamming number (if the language – or +! a convenient library – supports arbitrary-precision integers). + +TUPLE: hamming-iterator 2s 3s 5s ; + +: ( -- hamming-iterator ) + hamming-iterator new + 1 1dlist >>2s + 1 1dlist >>3s + 1 1dlist >>5s ; + +: enqueue ( n hamming-iterator -- ) + [ [ 2 * ] [ 2s>> ] bi* push-back ] + [ [ 3 * ] [ 3s>> ] bi* push-back ] + [ [ 5 * ] [ 5s>> ] bi* push-back ] 2tri ; + +: next ( hamming-iterator -- n ) + dup [ 2s>> ] [ 3s>> ] [ 5s>> ] tri + 3dup [ peek-front ] tri@ min min + [ + '[ + dup peek-front _ = + [ pop-front* ] [ drop ] if + ] tri@ + ] [ swap enqueue ] [ ] tri ; + +: next-n ( hamming-iterator n -- seq ) + swap '[ _ [ _ next , ] times ] { } make ; + +: nth-from-now ( hamming-iterator n -- m ) + 1 - over '[ _ next drop ] times next ; diff --git a/extra/rosetta-code/happy-numbers/happy-numbers-tests.factor b/extra/rosetta-code/happy-numbers/happy-numbers-tests.factor new file mode 100644 index 0000000000..5a57dc916e --- /dev/null +++ b/extra/rosetta-code/happy-numbers/happy-numbers-tests.factor @@ -0,0 +1,4 @@ +USING: tools.test ; +IN: rosetta-code.happy-numbers + +{ { 1 7 10 13 19 23 28 31 } } [ 8 happy-numbers ] unit-test diff --git a/extra/rosetta-code/happy-numbers/happy-numbers.factor b/extra/rosetta-code/happy-numbers/happy-numbers.factor new file mode 100644 index 0000000000..1eab929fe7 --- /dev/null +++ b/extra/rosetta-code/happy-numbers/happy-numbers.factor @@ -0,0 +1,38 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: combinators kernel make math sequences ; +IN: rosetta-code.happy-numbers + +! http://rosettacode.org/wiki/Happy_numbers#Factor + +! From Wikipedia, the free encyclopedia: + +! A happy number is defined by the following process. Starting +! with any positive integer, replace the number by the sum of the +! squares of its digits, and repeat the process until the number +! equals 1 (where it will stay), or it loops endlessly in a cycle +! which does not include 1. Those numbers for which this process +! ends in 1 are happy numbers, while those that do not end in 1 +! are unhappy numbers. Display an example of your output here. + +! Task: Find and print the first 8 happy numbers. + +: squares ( n -- s ) + 0 [ over 0 > ] [ [ 10 /mod sq ] dip + ] while nip ; + +: (happy?) ( n1 n2 -- ? ) + [ squares ] [ squares squares ] bi* { + { [ dup 1 = ] [ 2drop t ] } + { [ 2dup = ] [ 2drop f ] } + [ (happy?) ] + } cond ; + +: happy? ( n -- ? ) + dup (happy?) ; + +: happy-numbers ( n -- seq ) + [ + 0 [ over 0 > ] [ + dup happy? [ dup , [ 1 - ] dip ] when 1 + + ] while 2drop + ] { } make ; diff --git a/extra/rosetta-code/haversine-formula/haversine-formula.factor b/extra/rosetta-code/haversine-formula/haversine-formula.factor new file mode 100644 index 0000000000..2af50fa60b --- /dev/null +++ b/extra/rosetta-code/haversine-formula/haversine-formula.factor @@ -0,0 +1,35 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: arrays kernel math math.constants math.functions +math.vectors sequences ; +IN: rosetta-code.haversine-formula + +! http://rosettacode.org/wiki/Haversine_formula + +! The haversine formula is an equation important in navigation, +! giving great-circle distances between two points on a sphere +! from their longitudes and latitudes. It is a special case of a +! more general formula in spherical trigonometry, the law of +! haversines, relating the sides and angles of spherical +! "triangles". + +! Task: Implement a great-circle distance function, or use a +! library function, to show the great-circle distance between +! Nashville International Airport (BNA) in Nashville, TN, USA: N +! 36°7.2', W 86°40.2' (36.12, -86.67) and Los Angeles +! International Airport (LAX) in Los Angeles, CA, USA: N 33°56.4', +! W 118°24.0' (33.94, -118.40). + +CONSTANT: R_earth 6372.8 ! in kilometers + +: haversin ( x -- y ) cos 1 swap - 2 / ; + +: haversininv ( y -- x ) 2 * 1 swap - acos ; + +: haversineDist ( as bs -- d ) + [ [ 180 / pi * ] map ] bi@ + [ [ swap - haversin ] 2map ] + [ [ first cos ] bi@ * 1 swap 2array ] + 2bi + v. + haversininv R_earth * ; diff --git a/extra/rosetta-code/hofstadter-ffs/hofstadter-ffs.factor b/extra/rosetta-code/hofstadter-ffs/hofstadter-ffs.factor new file mode 100644 index 0000000000..f4164194c1 --- /dev/null +++ b/extra/rosetta-code/hofstadter-ffs/hofstadter-ffs.factor @@ -0,0 +1,48 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math namespaces sequences ; +IN: rosetta-code.hofstadter-ffs + +! These two sequences of positive integers are defined as: +! R(1) = 1 ; S(1) = 1 +! R(n) = R(n-1) + S(n-1) , n > 1 +! The sequence S(n) is further defined as the sequence of +! positive integers not present in R(n). + +! Sequence R starts: 1, 3, 7, 12, 18, ... +! Sequence S starts: 2, 4, 5, 6, 8, ... + +! Task: + +! 1. Create two functions named ffr and ffs that when given n +! return R(n) or S(n) respectively. +! (Note that R(1) = 1 and S(1) = 2 to avoid off-by-one errors). +! 2. No maximum value for n should be assumed. +! 3. Calculate and show that the first ten values of R are: 1, +! 3, 7, 12, 18, 26, 35, 45, 56, and 69 +! 4. Calculate and show that the first 40 values of ffr plus the +! first 960 values of ffs include all the integers from 1 to 1000 +! exactly once. + +SYMBOL: S V{ 2 } S set +SYMBOL: R V{ 1 } R set + +: next ( s r -- news newr ) + 2dup [ last ] bi@ + suffix + dup [ + [ dup last 1 + dup ] dip member? [ 1 + ] when suffix + ] dip ; + +: inc-SR ( n -- ) + dup 0 <= + [ drop ] + [ [ S get R get ] dip [ next ] times R set S set ] + if ; + +: ffs ( n -- S(n) ) + dup S get length - inc-SR + 1 - S get nth ; + +: ffr ( n -- R(n) ) + dup R get length - inc-SR + 1 - R get nth ; diff --git a/extra/rosetta-code/hofstadter-q/hofstadter-q.factor b/extra/rosetta-code/hofstadter-q/hofstadter-q.factor new file mode 100644 index 0000000000..8606d25685 --- /dev/null +++ b/extra/rosetta-code/hofstadter-q/hofstadter-q.factor @@ -0,0 +1,42 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math prettyprint sequences ; +IN: rosetta-code.hofstadter-q + +! http://rosettacode.org/wiki/Hofstadter_Q_sequence + +! The Hofstadter Q sequence is defined as: +! Q(1) = Q(2) = 1 +! Q(n) = Q(n - Q(n-1)) + Q(n - Q(n-2)) , n > 2 + +! It is defined like the Fibonacci sequence, but whereas the +! next term in the Fibonacci sequence is the sum of the previous +! two terms, in the Q sequence the previous two terms tell you how +! far to go back in the Q sequence to find the two numbers to sum +! to make the next term of the sequence. + +! Task + +! 1. Confirm and display that the first ten terms of the sequence +! are: 1, 1, 2, 3, 3, 4, 5, 5, 6, and 6 + +! 2. Confirm and display that the 1000'th term is: 502 + +! Optional extra credit + +! * Count and display how many times a member of the sequence is +! less than its preceding term for terms up to and including the +! 100,000'th term. + +! * Ensure that the extra credit solution 'safely' handles being +! initially asked for an n'th term where n is large. + +! (This point is to ensure that caching and/or recursion limits, +! if it is a concern, is correctly handled). + + : next ( seq -- newseq ) + dup 2 tail* over length [ swap - ] curry map + [ dupd swap nth ] map 0 [ + ] reduce suffix ; + +: qs-main ( -- ) + { 1 1 } 1000 [ next ] times dup 10 head . 999 swap nth . ; diff --git a/extra/rosetta-code/inverted-index/inverted-index.factor b/extra/rosetta-code/inverted-index/inverted-index.factor new file mode 100644 index 0000000000..8b50cf5de3 --- /dev/null +++ b/extra/rosetta-code/inverted-index/inverted-index.factor @@ -0,0 +1,34 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: assocs fry io.encodings.utf8 io.files kernel sequences +sets splitting vectors ; +IN: rosetta-code.inverted-index + +! http://rosettacode.org/wiki/Inverted_index + +! An Inverted Index is a data structure used to create full text +! search. + +! Given a set of text files, implement a program to create an +! inverted index. Also create a user interface to do a search +! using that inverted index which returns a list of files that +! contain the query term / terms. The search index can be in +! memory. + +: file-words ( file -- assoc ) + utf8 file-contents " ,;:!?.()[]{}\n\r" split harvest ; + +: add-to-file-list ( files file -- files ) + over [ swap [ adjoin ] keep ] [ nip 1vector ] if ; + +: add-to-index ( words index file -- ) + '[ _ [ _ add-to-file-list ] change-at ] each ; + +: (index-files) ( files index -- ) + [ [ [ file-words ] keep ] dip swap add-to-index ] curry each ; + +: index-files ( files -- index ) + H{ } clone [ (index-files) ] keep ; + +: query ( terms index -- files ) + [ at ] curry map [ ] [ intersect ] map-reduce ; diff --git a/extra/rosetta-code/knapsack-unbounded/knapsack-unbounded.factor b/extra/rosetta-code/knapsack-unbounded/knapsack-unbounded.factor new file mode 100644 index 0000000000..369edb5c08 --- /dev/null +++ b/extra/rosetta-code/knapsack-unbounded/knapsack-unbounded.factor @@ -0,0 +1,68 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors combinators kernel locals math math.order +math.vectors sequences sequences.product combinators.short-circuit ; +IN: rosetta-code.knapsack-unbounded + +! http://rosettacode.org/wiki/Knapsack_problem/Unbounded + +! A traveller gets diverted and has to make an unscheduled stop +! in what turns out to be Shangri La. Opting to leave, he is +! allowed to take as much as he likes of the following items, so +! long as it will fit in his knapsack, and he can carry it. He +! knows that he can carry no more than 25 'weights' in total; and +! that the capacity of his knapsack is 0.25 'cubic lengths'. + +! Looking just above the bar codes on the items he finds their +! weights and volumes. He digs out his recent copy of a financial +! paper and gets the value of each item. + +! He can only take whole units of any item, but there is much +! more of any item than he could ever carry + +! How many of each item does he take to maximise the value of +! items he is carrying away with him? + +! Note: + +! There are four solutions that maximise the value taken. Only +! one need be given. + +CONSTANT: values { 3000 1800 2500 } +CONSTANT: weights { 0.3 0.2 2.0 } +CONSTANT: volumes { 0.025 0.015 0.002 } + +CONSTANT: max-weight 25.0 +CONSTANT: max-volume 0.25 + +TUPLE: bounty amounts value weight volume ; + +: ( items -- bounty ) + [ bounty new ] dip { + [ >>amounts ] + [ values v. >>value ] + [ weights v. >>weight ] + [ volumes v. >>volume ] + } cleave ; + +: valid-bounty? ( bounty -- ? ) + { [ weight>> max-weight <= ] + [ volume>> max-volume <= ] } 1&& ; + +M:: bounty <=> ( a b -- <=> ) + a valid-bounty? [ + b valid-bounty? [ + a b [ value>> ] compare + ] [ +gt+ ] if + ] [ b valid-bounty? +lt+ +eq+ ? ] if ; + +: find-max-amounts ( -- amounts ) + weights volumes [ + [ max-weight swap / ] + [ max-volume swap / ] bi* min >integer + ] 2map ; + +: best-bounty ( -- bounty ) + find-max-amounts [ 1 + iota ] map + [ ] [ max ] map-reduce ; + diff --git a/extra/rosetta-code/knapsack/knapsack.factor b/extra/rosetta-code/knapsack/knapsack.factor new file mode 100644 index 0000000000..ada59fd96d --- /dev/null +++ b/extra/rosetta-code/knapsack/knapsack.factor @@ -0,0 +1,103 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors arrays fry io kernel locals make math +math.order math.parser math.ranges sequences sorting ; +IN: rosetta-code.knapsack + +! http://rosettacode.org/wiki/Knapsack_problem/0-1 + +! A tourist wants to make a good trip at the weekend with his +! friends. They will go to the mountains to see the wonders of +! nature, so he needs to pack well for the trip. He has a good +! knapsack for carrying things, but knows that he can carry a +! maximum of only 4kg in it and it will have to last the whole +! day. He creates a list of what he wants to bring for the trip +! but the total weight of all items is too much. He then decides +! to add columns to his initial list detailing their weights and a +! numerical value representing how important the item is for the +! trip. + +! The tourist can choose to take any combination of items from +! the list, but only one of each item is available. He may not cut +! or diminish the items, so he can only take whole units of any +! item. + +! Which items does the tourist carry in his knapsack so that +! their total weight does not exceed 400 dag [4 kg], and their +! total value is maximised? + +TUPLE: item + name weight value ; + +CONSTANT: items { + T{ item f "map" 9 150 } + T{ item f "compass" 13 35 } + T{ item f "water" 153 200 } + T{ item f "sandwich" 50 160 } + T{ item f "glucose" 15 60 } + T{ item f "tin" 68 45 } + T{ item f "banana" 27 60 } + T{ item f "apple" 39 40 } + T{ item f "cheese" 23 30 } + T{ item f "beer" 52 10 } + T{ item f "suntan cream" 11 70 } + T{ item f "camera" 32 30 } + T{ item f "t-shirt" 24 15 } + T{ item f "trousers" 48 10 } + T{ item f "umbrella" 73 40 } + T{ item f "waterproof trousers" 42 70 } + T{ item f "waterproof overclothes" 43 75 } + T{ item f "note-case" 22 80 } + T{ item f "sunglasses" 7 20 } + T{ item f "towel" 18 12 } + T{ item f "socks" 4 50 } + T{ item f "book" 30 10 } + } + +CONSTANT: limit 400 + +: make-table ( -- table ) + items length 1 + [ limit 1 + 0 ] replicate ; + +:: iterate ( item-no table -- ) + item-no table nth :> prev + item-no 1 + table nth :> curr + item-no items nth :> item + limit [1,b] [| weight | + weight prev nth + weight item weight>> - dup 0 >= + [ prev nth item value>> + max ] + [ drop ] if + weight curr set-nth + ] each ; + +: fill-table ( table -- ) + [ items length iota ] dip + '[ _ iterate ] each ; + +:: extract-packed-items ( table -- items ) + [ + limit :> weight! + items length iota [| item-no | + item-no table nth :> prev + item-no 1 + table nth :> curr + weight [ curr nth ] [ prev nth ] bi = + [ + item-no items nth + [ name>> , ] [ weight>> weight swap - weight! ] bi + ] unless + ] each + ] { } make ; + +: solve-knapsack ( -- items value ) + make-table [ fill-table ] + [ extract-packed-items ] [ last last ] tri ; + +: knapsack-main ( -- ) + solve-knapsack + "Total value: " write number>string print + "Items packed: " print + natural-sort + [ " " write print ] each ; + +MAIN: knapsack-main diff --git a/extra/rosetta-code/long-multiplication/long-multiplication.factor b/extra/rosetta-code/long-multiplication/long-multiplication.factor new file mode 100644 index 0000000000..4eafc22abe --- /dev/null +++ b/extra/rosetta-code/long-multiplication/long-multiplication.factor @@ -0,0 +1,33 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math sequences ; +IN: rosetta-code.long-multiplication + +! http://rosettacode.org/wiki/Long_multiplication + +! In this task, explicitly implement long multiplication. This +! is one possible approach to arbitrary-precision integer algebra. + +! For output, display the result of 2^64 * 2^64. The decimal +! representation of 2^64 is: + +! 18446744073709551616 + +! The output of 2^64 * 2^64 is 2^128, and that is: + +! 340282366920938463463374607431768211456 + +: longmult-seq ( xs ys -- zs ) + [ * ] cartesian-map + dup length iota [ 0 ] map + [ prepend ] 2map + [ ] [ [ 0 suffix ] dip [ + ] 2map ] map-reduce ; + +: integer->digits ( x -- xs ) + { } swap [ dup 0 > ] [ 10 /mod swap [ prefix ] dip ] while drop ; + +: digits->integer ( xs -- x ) + 0 [ swap 10 * + ] reduce ; + +: longmult ( x y -- z ) + [ integer->digits ] bi@ longmult-seq digits->integer ; diff --git a/extra/rosetta-code/look-and-say/look-and-say.factor b/extra/rosetta-code/look-and-say/look-and-say.factor new file mode 100644 index 0000000000..8b981c5fc7 --- /dev/null +++ b/extra/rosetta-code/look-and-say/look-and-say.factor @@ -0,0 +1,36 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel make math math.parser sequences ; +IN: rosetta-code.look-and-say + +! http://rosettacode.org/wiki/Look-and-say_sequence + +! Sequence Definition +! * Take a decimal number +! * Look at the number, visually grouping consecutive runs of +! the same digit. +! * Say the number, from left to right, group by group; as how +! many of that digit there are - followed by the digit grouped. +! This becomes the next number of the sequence. + +! The sequence is from John Conway, of Conway's Game of Life fame. + +! An example: +! * Starting with the number 1, you have one 1 which produces 11. +! * Starting with 11, you have two 1's i.e. 21 +! * Starting with 21, you have one 2, then one 1 i.e. (12)(11) which becomes 1211 +! * Starting with 1211 you have one 1, one 2, then two 1's i.e. (11)(12)(21) which becomes 111221 + +! Task description + +! Write a program to generate successive members of the look-and-say sequence. + +: (look-and-say) ( str -- ) + unclip-slice swap [ 1 ] 2dip [ + 2dup = [ drop [ 1 + ] dip ] [ + [ [ number>string % ] dip , 1 ] dip + ] if + ] each [ number>string % ] [ , ] bi* ; + +: look-and-say ( str -- str' ) + [ (look-and-say) ] "" make ; diff --git a/extra/rosetta-code/luhn-test/luhn-test.factor b/extra/rosetta-code/luhn-test/luhn-test.factor new file mode 100644 index 0000000000..814cc31b9e --- /dev/null +++ b/extra/rosetta-code/luhn-test/luhn-test.factor @@ -0,0 +1,72 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math math.parser math.order math.ranges sequences ; +IN: rosetta-code.luhn-test + +! http://rosettacode.org/wiki/Luhn_test_of_credit_card_numbers + +! The Luhn test is used by some credit card companies to +! distinguish valid credit card numbers from what could be a +! random selection of digits. + +! Those companies using credit card numbers that can be +! validated by the Luhn test have numbers that pass the following +! test: + +! 1. Reverse the order of the digits in the number. + +! 2. Take the first, third, ... and every other odd digit in the +! reversed digits and sum them to form the partial sum s1 + +! 3. Taking the second, fourth ... and every other even digit in +! the reversed digits: +! a. Multiply each digit by two and sum the digits if the +! answer is greater than nine to form partial sums for the +! even digits +! b. Sum the partial sums of the even digits to form s2 + +! 4. If s1 + s2 ends in zero then the original number is in the +! form of a valid credit card number as verified by the Luhn test. + +! For example, if the trial number is 49927398716: + +! Reverse the digits: +! 61789372994 +! Sum the odd digits: +! 6 + 7 + 9 + 7 + 9 + 4 = 42 = s1 +! The even digits: +! 1, 8, 3, 2, 9 +! Two times each even digit: +! 2, 16, 6, 4, 18 +! Sum the digits of each multiplication: +! 2, 7, 6, 4, 9 +! Sum the last: +! 2 + 7 + 6 + 4 + 9 = 28 = s2 + +! s1 + s2 = 70 which ends in zero which means that 49927398716 +! passes the Luhn test + +! The task is to write a function/method/procedure/subroutine +! that will validate a number with the Luhn test, and use it to +! validate the following numbers: +! 49927398716 +! 49927398717 +! 1234567812345678 +! 1234567812345670 + +: reversed-digits ( n -- list ) + { } swap + [ dup 0 > ] + [ 10 /mod swapd suffix swap ] + while drop ; + +: luhn-digit ( n -- n ) + reversed-digits dup length iota [ + 2dup swap nth + swap odd? [ 2 * 10 /mod + ] when + ] map sum 10 mod + nip ; + +: luhn? ( n -- ? ) + luhn-digit 0 = ; + diff --git a/extra/rosetta-code/menu/menu.factor b/extra/rosetta-code/menu/menu.factor new file mode 100644 index 0000000000..03d198e5f7 --- /dev/null +++ b/extra/rosetta-code/menu/menu.factor @@ -0,0 +1,35 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: formatting io kernel math math.parser sequences ; +IN: rosetta-code.menu + +! http://rosettacode.org/wiki/Menu + +! Given a list containing a number of strings of which one is to +! be selected and a prompt string, create a function that: + +! * Print a textual menu formatted as an index value followed by +! its corresponding string for each item in the list. +! * Prompt the user to enter a number. +! * Return the string corresponding to the index number. + +! The function should reject input that is not an integer or is +! an out of range integer index by recreating the whole menu +! before asking again for a number. The function should return an +! empty string if called with an empty list. + +! For test purposes use the four phrases: “fee fie”, “huff and +! puff”, “mirror mirror” and “tick tock” in a list. + +! Note: This task is fashioned after the action of the Bash select statement. + +: print-menu ( seq -- ) + [ 1 + swap "%d - %s\n" printf ] each-index + "Your choice? " write flush ; + +: select ( seq -- result ) + dup print-menu + readln string>number [ + 1 - swap 2dup bounds-check? + [ nth ] [ nip select ] if + ] [ select ] if* ; diff --git a/extra/rosetta-code/multiplication-tables/multiplication-tables.factor b/extra/rosetta-code/multiplication-tables/multiplication-tables.factor new file mode 100644 index 0000000000..6b8b563259 --- /dev/null +++ b/extra/rosetta-code/multiplication-tables/multiplication-tables.factor @@ -0,0 +1,26 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: io kernel math math.parser math.ranges sequences ; +IN: rosetta-code.multiplication-tables + +! http://rosettacode.org/wiki/Multiplication_tables + +! Produce a formatted 12×12 multiplication table of the kind +! memorised by rote when in primary school. + +! Only print the top half triangle of products. + +: print-row ( n -- ) + [ number>string 2 CHAR: space pad-head write " |" write ] + [ 1 - [ " " write ] times ] + [ + dup 12 [a,b] + [ * number>string 4 CHAR: space pad-head write ] with each + ] tri nl ; + +: print-table ( -- ) + " " write + 1 12 [a,b] [ number>string 4 CHAR: space pad-head write ] each nl + " +" write + 12 [ "----" write ] times nl + 1 12 [a,b] [ print-row ] each ; diff --git a/extra/rosetta-code/n-queens/n-queens.factor b/extra/rosetta-code/n-queens/n-queens.factor new file mode 100644 index 0000000000..8b26a812c5 --- /dev/null +++ b/extra/rosetta-code/n-queens/n-queens.factor @@ -0,0 +1,29 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel sequences math math.combinatorics formatting io locals ; +IN: rosetta-code.n-queens + +! http://rosettacode.org/wiki/N-queens_problem + +! Solve the eight queens puzzle. You can extend the problem to +! solve the puzzle with a board of side NxN. + +:: safe? ( board q -- ? ) + [let q board nth :> x + q iota [ + x swap + [ board nth ] keep + q swap - + [ + = not ] + [ - = not ] 3bi and + ] all? + ] ; + +: solution? ( board -- ? ) + dup length iota [ dupd safe? ] all? nip ; + +: queens ( n -- l ) + iota all-permutations [ solution? ] filter ; + +: queens. ( n -- ) + queens [ [ 1 + "%d " printf ] each nl ] each ; diff --git a/extra/rosetta-code/number-reversal/number-reversal.factor b/extra/rosetta-code/number-reversal/number-reversal.factor new file mode 100644 index 0000000000..2680601de0 --- /dev/null +++ b/extra/rosetta-code/number-reversal/number-reversal.factor @@ -0,0 +1,44 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: formatting io kernel math math.parser math.ranges +namespaces random sequences strings ; +IN: rosetta-code.number-reversal + +! http://rosettacode.org/wiki/Number_reversal_game + +! Given a jumbled list of the numbers 1 to 9 that are definitely +! not in ascending order, show the list then ask the player how +! many digits from the left to reverse. Reverse those digits, then +! ask again, until all the digits end up in ascending order. + +! The score is the count of the reversals needed to attain the +! ascending order. + +! Note: Assume the players input does not need extra validation. + +: make-jumbled-array ( -- sorted jumbled ) + CHAR: 1 CHAR: 9 [a,b] [ 1string ] map dup clone randomize + [ 2dup = ] [ randomize ] while ; + +SYMBOL: trials + +: prompt ( jumbled -- n ) + trials get "#%2d: " printf + ", " join write + " Flip how many? " write flush + readln string>number ; + +: game-loop ( sorted jumbled -- ) + 2dup = [ + 2drop trials get + "\nYou took %d attempts to put the digits in order!\n" printf + flush + ] [ + trials [ 1 + ] change + dup dup prompt head-slice reverse! drop + game-loop + ] if ; + +: play ( -- ) + 0 trials set + make-jumbled-array game-loop ; diff --git a/extra/rosetta-code/odd-word/odd-word.factor b/extra/rosetta-code/odd-word/odd-word.factor new file mode 100644 index 0000000000..67f9f57103 --- /dev/null +++ b/extra/rosetta-code/odd-word/odd-word.factor @@ -0,0 +1,101 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: continuations kernel io io.streams.string locals unicode.categories ; +IN: rosetta-code.odd-word + +! http://rosettacode.org/wiki/Odd_word_problem + +! Write a program that solves the odd word problem with the +! restrictions given below. + +! Description: You are promised an input stream consisting of +! English letters and punctuations. It is guaranteed that + +! * the words (sequence of consecutive letters) are delimited by +! one and only one punctuation; that +! * the stream will begin with a word; that +! * the words will be at least one letter long; and that +! * a full stop (.) appears after, and only after, the last word. + +! For example, what,is,the;meaning,of:life. is such a stream +! with six words. Your task is to reverse the letters in every +! other word while leaving punctuations intact, producing e.g. +! "what,si,the;gninaem,of:efil.", while observing the following +! restrictions: + +! Only I/O allowed is reading or writing one character at a +! time, which means: no reading in a string, no peeking ahead, no +! pushing characters back into the stream, and no storing +! characters in a global variable for later use; + +! You are not to explicitly save characters in a collection data +! structure, such as arrays, strings, hash tables, etc, for later +! reversal; + +! You are allowed to use recursions, closures, continuations, +! threads, coroutines, etc., even if their use implies the storage +! of multiple characters. + +! Test case: work on both the "life" example given above, and +! the text we,are;not,in,kansas;any,more. + + + +:: read-odd-word ( -- ) + f :> first-continuation! + f :> last-continuation! + f :> reverse! + ! Read characters. Loop until end of stream. + [ read1 dup ] [ + dup Letter? [ + ! This character is a letter. + reverse [ + ! Odd word: Write letters in reverse order. + last-continuation savecc dup [ + last-continuation! + 2drop ! Drop letter and previous continuation. + ] [ + ! After jump: print letters in reverse. + drop ! Drop f. + swap write1 ! Write letter. + jump-back ! Follow chain of continuations. + ] if + ] [ + ! Even word: Write letters immediately. + write1 + ] if + ] [ + ! This character is punctuation. + reverse [ + ! End odd word. Fix trampoline, follow chain of continuations + ! (to print letters in reverse), then bounce off trampoline. + savecc dup [ + first-continuation! + last-continuation jump-back + ] [ drop ] if + write1 ! Write punctuation. + f reverse! ! Begin even word. + ] [ + write1 ! Write punctuation. + t reverse! ! Begin odd word. + ! Create trampoline to bounce to (future) first-continuation. + savecc dup [ + last-continuation! + ] [ drop first-continuation jump-back ] if + ] if + ] if + ] while + ! Drop f from read1. Then print a cosmetic newline. + drop nl ; + +: odd-word ( string -- ) + [ read-odd-word ] with-string-reader ; + diff --git a/extra/rosetta-code/one-d-cellular/one-d-cellular.factor b/extra/rosetta-code/one-d-cellular/one-d-cellular.factor new file mode 100644 index 0000000000..1f3af66393 --- /dev/null +++ b/extra/rosetta-code/one-d-cellular/one-d-cellular.factor @@ -0,0 +1,52 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: bit-arrays io kernel locals math sequences ; +IN: rosetta-code.one-d-cellular + +! http://rosettacode.org/wiki/One-dimensional_cellular_automata + +! Assume an array of cells with an initial distribution of live +! and dead cells, and imaginary cells off the end of the array +! having fixed values. + +! Cells in the next generation of the array are calculated based +! on the value of the cell and its left and right nearest +! neighbours in the current generation. If, in the following +! table, a live cell is represented by 1 and a dead cell by 0 then +! to generate the value of the cell at a particular index in the +! array of cellular values you use the following table: + +! 000 -> 0 # +! 001 -> 0 # +! 010 -> 0 # Dies without enough neighbours +! 011 -> 1 # Needs one neighbour to survive +! 100 -> 0 # +! 101 -> 1 # Two neighbours giving birth +! 110 -> 1 # Needs one neighbour to survive +! 111 -> 0 # Starved to death. + +: bool-sum ( bool1 bool2 -- sum ) + [ [ 2 ] [ 1 ] if ] + [ [ 1 ] [ 0 ] if ] if ; + +:: neighbours ( index world -- # ) + index [ 1 - ] [ 1 + ] bi [ world ?nth ] bi@ bool-sum ; + +: count-neighbours ( world -- neighbours ) + [ length iota ] keep [ neighbours ] curry map ; + +: life-law ( alive? neighbours -- alive? ) + swap [ 1 = ] [ 2 = ] if ; + +: step ( world -- world' ) + dup count-neighbours [ life-law ] ?{ } 2map-as ; + +: print-cellular ( world -- ) + [ CHAR: # CHAR: _ ? ] "" map-as print ; + +: main-cellular ( -- ) + ?{ f t t t f t t f t f t f t f t f f t f f } + 10 [ dup print-cellular step ] times print-cellular ; + +MAIN: main-cellular + diff --git a/extra/rosetta-code/opengl/opengl.factor b/extra/rosetta-code/opengl/opengl.factor new file mode 100644 index 0000000000..dfdf8fa446 --- /dev/null +++ b/extra/rosetta-code/opengl/opengl.factor @@ -0,0 +1,42 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math math.rectangles opengl.gl sequences ui +ui.gadgets ui.render ; +IN: rosetta-code.opengl + +! http://rosettacode.org/wiki/OpenGL + +! In this task, the goal is to display a smooth shaded triangle +! with OpenGL. + +TUPLE: triangle-gadget < gadget ; + +: reshape ( width height -- ) + [ 0 0 ] 2dip glViewport + GL_PROJECTION glMatrixMode + glLoadIdentity + -30.0 30.0 -30.0 30.0 -30.0 30.0 glOrtho + GL_MODELVIEW glMatrixMode ; + +: paint ( -- ) + 0.3 0.3 0.3 0.0 glClearColor + GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT bitor glClear + GL_SMOOTH glShadeModel + glLoadIdentity + -15.0 -15.0 0.0 glTranslatef + GL_TRIANGLES glBegin + 1.0 0.0 0.0 glColor3f 0.0 0.0 glVertex2f + 0.0 1.0 0.0 glColor3f 30.0 0.0 glVertex2f + 0.0 0.0 1.0 glColor3f 0.0 30.0 glVertex2f + glEnd + glFlush ; + +M: triangle-gadget pref-dim* drop { 640 480 } ; +M: triangle-gadget draw-gadget* + rect-bounds nip first2 reshape paint ; + +: triangle-window ( -- ) + [ triangle-gadget new "Triangle" open-window ] with-ui ; + +MAIN: triangle-window + diff --git a/extra/rosetta-code/ordered-words/ordered-words.factor b/extra/rosetta-code/ordered-words/ordered-words.factor new file mode 100644 index 0000000000..95b6d3f42c --- /dev/null +++ b/extra/rosetta-code/ordered-words/ordered-words.factor @@ -0,0 +1,37 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: fry grouping http.client io io.encodings.utf8 io.files +io.files.temp kernel math math.order memoize sequences +unicode.case urls ; +IN: rosetta-code.ordered-words + +! http://rosettacode.org/wiki/Ordered_words + +! Define an ordered word as a word in which the letters of the +! word appear in alphabetic order. Examples include 'abbey' and +! 'dirt'. + +! The task is to find and display all the ordered words in this +! dictionary that have the longest word length. (Examples that +! access the dictionary file locally assume that you have +! downloaded this file yourself.) The display needs to be shown on +! this page. + +MEMO: word-list ( -- seq ) + "unixdict.txt" temp-file dup exists? [ + URL" http://puzzlers.org/pub/wordlists/unixdict.txt" + over download-to + ] unless utf8 file-lines ; + +: ordered-word? ( word -- ? ) + >lower 2 [ first2 <= ] all? ; + +: filter-longest-words ( seq -- seq' ) + dup [ length ] [ max ] map-reduce + '[ length _ = ] filter ; + +: ordered-words-main ( -- ) + word-list [ ordered-word? ] filter + filter-longest-words [ print ] each ; + +MAIN: ordered-words-main diff --git a/extra/rosetta-code/pascals-triangle/pascals-triangle.factor b/extra/rosetta-code/pascals-triangle/pascals-triangle.factor new file mode 100644 index 0000000000..2c1a55ad43 --- /dev/null +++ b/extra/rosetta-code/pascals-triangle/pascals-triangle.factor @@ -0,0 +1,33 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: grouping kernel math sequences ; +IN: rosetta-code.pascals-triangle + +! http://rosettacode.org/wiki/Pascal%27s_triangle + +! Pascal's triangle is an interesting math concept. Its first few rows look like this: +! 1 +! 1 1 +! 1 2 1 +! 1 3 3 1 + +! where each element of each row is either 1 or the sum of the +! two elements right above it. For example, the next row would be +! 1 (since the first element of each row doesn't have two elements +! above it), 4 (1 + 3), 6 (3 + 3), 4 (3 + 1), and 1 (since the +! last element of each row doesn't have two elements above it). +! Each row n (starting with row 0 at the top) shows the +! coefficients of the binomial expansion of (x + y)n. + +! Write a function that prints out the first n rows of the +! triangle (with f(1) yielding the row consisting of only the +! element 1). This can be done either by summing elements from the +! previous rows or using a binary coefficient or combination +! function. Behavior for n <= 0 does not need to be uniform, but +! should be noted. + +: (pascal) ( seq -- newseq ) + dup last 0 prefix 0 suffix 2 [ sum ] map suffix ; + +: pascal ( n -- seq ) + 1 - { { 1 } } swap [ (pascal) ] times ; diff --git a/extra/rosetta-code/probabilistic-choice/probabilistic-choice.factor b/extra/rosetta-code/probabilistic-choice/probabilistic-choice.factor new file mode 100644 index 0000000000..cee4003bbd --- /dev/null +++ b/extra/rosetta-code/probabilistic-choice/probabilistic-choice.factor @@ -0,0 +1,66 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: arrays assocs combinators.random io kernel macros math +math.statistics prettyprint quotations sequences sorting formatting ; +IN: rosettacode.probabilistic-choice + +! http://rosettacode.org/wiki/Probabilistic_choice + +! Given a mapping between items and their required probability +! of occurrence, generate a million items randomly subject to the +! given probabilities and compare the target probability of +! occurrence versus the generated values. + +! The total of all the probabilities should equal one. (Because +! floating point arithmetic is involved this is subject to +! rounding errors). + +! Use the following mapping to test your programs: +! aleph 1/5.0 +! beth 1/6.0 +! gimel 1/7.0 +! daleth 1/8.0 +! he 1/9.0 +! waw 1/10.0 +! zayin 1/11.0 +! heth 1759/27720 # adjusted so that probabilities add to 1 + +CONSTANT: data +{ + { "aleph" 1/5.0 } + { "beth" 1/6.0 } + { "gimel" 1/7.0 } + { "daleth" 1/8.0 } + { "he" 1/9.0 } + { "waw" 1/10.0 } + { "zayin" 1/11.0 } + { "heth" f } +} + +MACRO: case-probas ( data -- case-probas ) + [ first2 [ swap 1quotation 2array ] [ 1quotation ] if* ] map 1quotation ; + +: expected ( name data -- float ) + 2dup at [ 2nip ] [ nip values sift sum 1 swap - ] if* ; + +: generate ( # case-probas -- seq ) + H{ } clone + [ [ [ casep ] [ inc-at ] bi* ] 2curry times ] keep ; inline + +: normalize ( seq # -- seq ) + [ clone ] dip [ /f ] curry assoc-map ; + +: summarize1 ( name value data -- ) + [ over ] dip expected + "%6s: %10f %10f\n" printf ; + +: summarize ( generated data -- ) + "Key" "Value" "expected" "%6s %10s %10s\n" printf + [ summarize1 ] curry assoc-each ; + +: generate-normalized ( # proba -- seq ) + [ generate ] [ drop normalize ] 2bi ; inline + +: example ( # data -- ) + [ case-probas generate-normalized ] + [ summarize ] bi ; inline diff --git a/extra/rosetta-code/pythagorean-triples/pythagorean-triples.factor b/extra/rosetta-code/pythagorean-triples/pythagorean-triples.factor new file mode 100644 index 0000000000..f99affcfc2 --- /dev/null +++ b/extra/rosetta-code/pythagorean-triples/pythagorean-triples.factor @@ -0,0 +1,80 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors arrays formatting kernel literals math +math.functions math.matrices math.ranges sequences ; +IN: rosetta-code.pythagorean-triples + +! http://rosettacode.org/wiki/Pythagorean_triples + +! A Pythagorean triple is defined as three positive integers +! (a,b,c) where a < b < c, and a2 + b2 = c2. They are called +! primitive triples if a,b,c are coprime, that is, if their +! pairwise greatest common divisors gcd(a,b) = gcd(a,c) = gcd(b,c) +! = 1. Because of their relationship through the Pythagorean +! theorem, a, b, and c are coprime if a and b are coprime +! (gcd(a,b) = 1). Each triple forms the length of the sides of a +! right triangle, whose perimeter is P = a + b + c. + +! Task + +! The task is to determine how many Pythagorean triples there +! are with a perimeter no larger than 100 and the number of these +! that are primitive. + +! Extra credit: Deal with large values. Can your program handle +! a max perimeter of 1,000,000? What about 10,000,000? +! 100,000,000? + +! Note: the extra credit is not for you to demonstrate how fast +! your language is compared to others; you need a proper algorithm +! to solve them in a timely manner. + +CONSTANT: T1 { + { 1 2 2 } + { -2 -1 -2 } + { 2 2 3 } +} +CONSTANT: T2 { + { 1 2 2 } + { 2 1 2 } + { 2 2 3 } +} +CONSTANT: T3 { + { -1 -2 -2 } + { 2 1 2 } + { 2 2 3 } +} + +CONSTANT: base { 3 4 5 } + +TUPLE: triplets-count primitives total ; + +: <0-triplets-count> ( -- a ) 0 0 \ triplets-count boa ; + +: next-triplet ( triplet T -- triplet' ) [ 1array ] [ m. ] bi* first ; + +: candidates-triplets ( seed -- candidates ) + ${ T1 T2 T3 } [ next-triplet ] with map ; + +: add-triplets ( current-triples limit triplet -- stop ) + sum 2dup > [ + /i [ + ] curry change-total + [ 1 + ] change-primitives drop t + ] [ 3drop f ] if ; + +: all-triplets ( current-triples limit seed -- triplets ) + 3dup add-triplets [ + candidates-triplets [ all-triplets ] with swapd reduce + ] [ 2drop ] if ; + +: count-triplets ( limit -- count ) + <0-triplets-count> swap base all-triplets ; + +: pprint-triplet-count ( limit count -- ) + [ total>> ] [ primitives>> ] bi + "Up to %d: %d triples, %d primitives.\n" printf ; + +: pyth ( -- ) + 8 [1,b] [ 10^ dup count-triplets pprint-triplet-count ] each ; + + diff --git a/extra/rosetta-code/raycasting/raycasting-tests.factor b/extra/rosetta-code/raycasting/raycasting-tests.factor new file mode 100644 index 0000000000..d57e4bac24 --- /dev/null +++ b/extra/rosetta-code/raycasting/raycasting-tests.factor @@ -0,0 +1,10 @@ + +USING: tools.test ; + +IN: rosetta-code.raycasting + +CONSTANT: square { { -2 -1 } { 1 -2 } { 2 1 } { -1 2 } } + +{ t } [ square { 0 0 } raycast ] unit-test +{ f } [ square { 5 5 } raycast ] unit-test +{ f } [ square { 2 0 } raycast ] unit-test diff --git a/extra/rosetta-code/raycasting/raycasting.factor b/extra/rosetta-code/raycasting/raycasting.factor new file mode 100644 index 0000000000..dd03886997 --- /dev/null +++ b/extra/rosetta-code/raycasting/raycasting.factor @@ -0,0 +1,125 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: kernel prettyprint sequences arrays math math.vectors ; +IN: rosetta-code.raycasting + + +! http://rosettacode.org/wiki/Ray-casting_algorithm + +! Given a point and a polygon, check if the point is inside or +! outside the polygon using the ray-casting algorithm. + +! A pseudocode can be simply: + +! count ← 0 +! foreach side in polygon: +! if ray_intersects_segment(P,side) then +! count ← count + 1 +! if is_odd(count) then +! return inside +! else +! return outside + +! Where the function ray_intersects_segment return true if the +! horizontal ray starting from the point P intersects the side +! (segment), false otherwise. + +! An intuitive explanation of why it works is that every time we +! cross a border, we change "country" (inside-outside, or +! outside-inside), but the last "country" we land on is surely +! outside (since the inside of the polygon is finite, while the +! ray continues towards infinity). So, if we crossed an odd number +! of borders we was surely inside, otherwise we was outside; we +! can follow the ray backward to see it better: starting from +! outside, only an odd number of crossing can give an inside: +! outside-inside, outside-inside-outside-inside, and so on (the - +! represents the crossing of a border). + +! So the main part of the algorithm is how we determine if a ray +! intersects a segment. The following text explain one of the +! possible ways. + +! Looking at the image on the right, we can easily be convinced +! of the fact that rays starting from points in the hatched area +! (like P1 and P2) surely do not intersect the segment AB. We also +! can easily see that rays starting from points in the greenish +! area surely intersect the segment AB (like point P3). + +! So the problematic points are those inside the white area (the +! box delimited by the points A and B), like P4. + +! Let us take into account a segment AB (the point A having y +! coordinate always smaller than B's y coordinate, i.e. point A is +! always below point B) and a point P. Let us use the cumbersome +! notation PAX to denote the angle between segment AP and AX, +! where X is always a point on the horizontal line passing by A +! with x coordinate bigger than the maximum between the x +! coordinate of A and the x coordinate of B. As explained +! graphically by the figures on the right, if PAX is greater than +! the angle BAX, then the ray starting from P intersects the +! segment AB. (In the images, the ray starting from PA does not +! intersect the segment, while the ray starting from PB in the +! second picture, intersects the segment). + +! Points on the boundary or "on" a vertex are someway special +! and through this approach we do not obtain coherent results. +! They could be treated apart, but it is not necessary to do so. + +! An algorithm for the previous speech could be (if P is a +! point, Px is its x coordinate): + +! ray_intersects_segment: +! P : the point from which the ray starts +! A : the end-point of the segment with the smallest y coordinate +! (A must be "below" B) +! B : the end-point of the segment with the greatest y coordinate +! (B must be "above" A) +! if Py = Ay or Py = By then +! Py ← Py + ε +! end if +! if Py < Ay or Py > By then +! return false +! else if Px > max(Ax, Bx) then +! return false +! else +! if Px < min(Ax, Bx) then +! return true +! else +! if Ax ≠ Bx then +! m_red ← (By - Ay)/(Bx - Ax) +! else +! m_red ← ∞ +! end if +! if Ax ≠ Px then +! m_blue ← (Py - Ay)/(Px - Ax) +! else +! m_blue ← ∞ +! end if +! if m_blue ≥ m_red then +! return true +! else +! return false +! end if +! end if +! end if + +! (To avoid the "ray on vertex" problem, the point is moved +! upward of a small quantity ε) + +: between ( a b x -- ? ) [ last ] tri@ [ < ] curry bi@ xor ; + +: lincomb ( a b x -- w ) + 3dup [ last ] tri@ + [ - ] curry bi@ + [ drop ] 2dip + neg 2dup + [ / ] curry bi@ + [ [ v*n ] curry ] bi@ bi* v+ ; + +: leftof ( a b x -- ? ) dup [ lincomb ] dip [ first ] bi@ > ; + +: ray ( a b x -- ? ) [ between ] [ leftof ] 3bi and ; + +: raycast ( poly x -- ? ) + [ dup first suffix [ rest-slice ] [ but-last-slice ] bi ] dip + [ ray ] curry 2map + f [ xor ] reduce ; diff --git a/extra/rosetta-code/sierpinski-triangle/sierpinski-triangle.factor b/extra/rosetta-code/sierpinski-triangle/sierpinski-triangle.factor new file mode 100644 index 0000000000..0f1bbc993c --- /dev/null +++ b/extra/rosetta-code/sierpinski-triangle/sierpinski-triangle.factor @@ -0,0 +1,42 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: io kernel math sequences ; +IN: rosetta-code.sierpinski-triangle + +! http://rosettacode.org/wiki/Sierpinski_triangle + +! Produce an ASCII representation of a Sierpinski triangle of +! order N. For example, the Sierpinski triangle of order 4 should +! look like this: + +! * +! * * +! * * +! * * * * +! * * +! * * * * +! * * * * +! * * * * * * * * +! * * +! * * * * +! * * * * +! * * * * * * * * +! * * * * +! * * * * * * * * +! * * * * * * * * +! * * * * * * * * * * * * * * * * + +: iterate-triangle ( triange spaces -- triangle' ) + [ [ dup surround ] curry map ] + [ drop [ dup " " glue ] map ] 2bi append ; + +: (sierpinski) ( triangle spaces n -- triangle' ) + dup 0 = [ 2drop "\n" join ] [ + [ + [ iterate-triangle ] + [ nip dup append ] 2bi + ] dip 1 - (sierpinski) + ] if ; + +: sierpinski ( n -- ) + [ { "*" } " " ] dip (sierpinski) print ; diff --git a/extra/rosetta-code/standard-deviation/standard-deviation.factor b/extra/rosetta-code/standard-deviation/standard-deviation.factor new file mode 100644 index 0000000000..12feca3bee --- /dev/null +++ b/extra/rosetta-code/standard-deviation/standard-deviation.factor @@ -0,0 +1,38 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors io kernel math math.functions math.parser +sequences ; +IN: rosetta-code.standard-deviation + +! http://rosettacode.org/wiki/Standard_deviation + +! Write a stateful function, class, generator or coroutine that +! takes a series of floating point numbers, one at a time, and +! returns the running standard deviation of the series. The task +! implementation should use the most natural programming style of +! those listed for the function in the implementation language; +! the task must state which is being used. Do not apply Bessel's +! correction; the returned standard deviation should always be +! computed as if the sample seen so far is the entire population. + +! Use this to compute the standard deviation of this +! demonstration set, {2,4,4,4,5,5,7,9}, which is 2. + +TUPLE: standard-deviator sum sum^2 n ; + +: ( -- standard-deviator ) + 0.0 0.0 0 standard-deviator boa ; + +: current-std ( standard-deviator -- std ) + [ [ sum^2>> ] [ n>> ] bi / ] + [ [ sum>> ] [ n>> ] bi / sq ] bi - sqrt ; + +: add-value ( value standard-deviator -- ) + [ nip [ 1 + ] change-n drop ] + [ [ + ] change-sum drop ] + [ [ [ sq ] dip + ] change-sum^2 drop ] 2tri ; + +: std-main ( -- ) + { 2 4 4 4 5 5 7 9 } + [ [ add-value ] curry each ] keep + current-std number>string print ; diff --git a/extra/rosetta-code/ternary-logic/ternary-logic.factor b/extra/rosetta-code/ternary-logic/ternary-logic.factor new file mode 100644 index 0000000000..c1508bb563 --- /dev/null +++ b/extra/rosetta-code/ternary-logic/ternary-logic.factor @@ -0,0 +1,68 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: combinators kernel ; +IN: rosetta-code.ternary-logic + +! http://rosettacode.org/wiki/Ternary_logic + +! In logic, a three-valued logic (also trivalent, ternary, or +! trinary logic, sometimes abbreviated 3VL) is any of several +! many-valued logic systems in which there are three truth values +! indicating true, false and some indeterminate third value. This +! is contrasted with the more commonly known bivalent logics (such +! as classical sentential or boolean logic) which provide only for +! true and false. Conceptual form and basic ideas were initially +! created by Łukasiewicz, Lewis and Sulski. These were then +! re-formulated by Grigore Moisil in an axiomatic algebraic form, +! and also extended to n-valued logics in 1945. + +! Task: + +! * Define a new type that emulates ternary logic by storing data trits. + +! * Given all the binary logic operators of the original +! programming language, reimplement these operators for the new +! Ternary logic type trit. + +! * Generate a sampling of results using trit variables. + +! * Kudos for actually thinking up a test case algorithm where +! ternary logic is intrinsically useful, optimises the test case +! algorithm and is preferable to binary logic. + +SINGLETON: m +UNION: trit t m POSTPONE: f ; + +GENERIC: >trit ( object -- trit ) +M: trit >trit ; + +: tnot ( trit1 -- trit ) + >trit { { t [ f ] } { m [ m ] } { f [ t ] } } case ; + +: tand ( trit1 trit2 -- trit ) + >trit { + { t [ >trit ] } + { m [ >trit { { t [ m ] } { m [ m ] } { f [ f ] } } case ] } + { f [ >trit drop f ] } + } case ; + +: tor ( trit1 trit2 -- trit ) + >trit { + { t [ >trit drop t ] } + { m [ >trit { { t [ t ] } { m [ m ] } { f [ m ] } } case ] } + { f [ >trit ] } + } case ; + +: txor ( trit1 trit2 -- trit ) + >trit { + { t [ tnot ] } + { m [ >trit drop m ] } + { f [ >trit ] } + } case ; + +: t= ( trit1 trit2 -- trit ) + { + { t [ >trit ] } + { m [ >trit drop m ] } + { f [ tnot ] } + } case ; diff --git a/extra/rosetta-code/text-processing/max-licenses/max-licenses.factor b/extra/rosetta-code/text-processing/max-licenses/max-licenses.factor new file mode 100644 index 0000000000..9943470916 --- /dev/null +++ b/extra/rosetta-code/text-processing/max-licenses/max-licenses.factor @@ -0,0 +1,80 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors http.client io io.encodings.ascii io.files +io.files.temp kernel math math.parser memoize sequences +splitting urls ; +IN: rosetta-code.text-processing.max-licenses + +! http://rosettacode.org/wiki/Text_processing/Max_licenses_in_use + +! A company currently pays a fixed sum for the use of a +! particular licensed software package. In determining if it has a +! good deal it decides to calculate its maximum use of the +! software from its license management log file. + +! Assume the software's licensing daemon faithfully records a +! checkout event when a copy of the software starts and a checkin +! event when the software finishes to its log file. An example of +! checkout and checkin events are: + +! License OUT @ 2008/10/03_23:51:05 for job 4974 +! ... +! License IN @ 2008/10/04_00:18:22 for job 4974 + +! Save the 10,000 line log file from here into a local file then +! write a program to scan the file extracting both the maximum +! licenses that were out at any time, and the time(s) at which +! this occurs. + +TUPLE: maxlicense max-count current-count times ; + + ( -- max ) -1 0 V{ } clone \ maxlicense boa ; inline + +: out? ( line -- ? ) [ "OUT" ] dip subseq? ; inline + +: line-time ( line -- time ) " " split harvest fourth ; inline + +: update-max-count ( max -- max' ) + dup [ current-count>> ] [ max-count>> ] bi > + [ dup current-count>> >>max-count V{ } clone >>times ] when ; + +: (inc-current-count) ( max ? -- max' ) + [ [ 1 + ] change-current-count ] + [ [ 1 - ] change-current-count ] + if + update-max-count ; inline + +: inc-current-count ( max ? time -- max' time ) + [ (inc-current-count) ] dip ; + +: current-max-equal? ( max -- max ? ) + dup [ current-count>> ] [ max-count>> ] bi = ; + +: update-time ( max time -- max' ) + [ current-max-equal? ] dip + swap + [ [ suffix ] curry change-times ] [ drop ] if ; + +: split-line ( line -- ? time ) [ out? ] [ line-time ] bi ; + +: process ( max line -- max ) split-line inc-current-count update-time ; + +MEMO: mlijobs ( -- lines ) + "mlijobs.txt" temp-file dup exists? [ + URL" http://rosettacode.org/resources/mlijobs.txt" + over download-to + ] unless ascii file-lines ; + +PRIVATE> + +: find-max-licenses ( -- max ) + mlijobs [ process ] reduce ; + +: print-max-licenses ( max -- ) + [ times>> ] [ max-count>> ] bi + "Maximum simultaneous license use is " write + number>string write + " at the following times: " print + [ print ] each ; diff --git a/extra/rosetta-code/top-rank/top-rank.factor b/extra/rosetta-code/top-rank/top-rank.factor new file mode 100644 index 0000000000..49ac7ec62d --- /dev/null +++ b/extra/rosetta-code/top-rank/top-rank.factor @@ -0,0 +1,70 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors assocs fry io kernel math.parser sequences +sorting ; +IN: rosetta-code.top-rank + +! http://rosettacode.org/wiki/Top_rank_per_group + +! Find the top N salaries in each department, where N is +! provided as a parameter. + +! Use this data as a formatted internal data structure (adapt it +! to your language-native idioms, rather than parse at runtime), +! or identify your external data source: + +! Employee Name,Employee ID,Salary,Department +! Tyler Bennett,E10297,32000,D101 +! John Rappl,E21437,47000,D050 +! George Woltman,E00127,53500,D101 +! Adam Smith,E63535,18000,D202 +! Claire Buckman,E39876,27800,D202 +! David McClellan,E04242,41500,D101 +! Rich Holcomb,E01234,49500,D202 +! Nathan Adams,E41298,21900,D050 +! Richard Potter,E43128,15900,D101 +! David Motsinger,E27002,19250,D202 +! Tim Sampair,E03033,27000,D101 +! Kim Arlich,E10001,57000,D190 +! Timothy Grove,E16398,29900,D190 + +TUPLE: employee name id salary department ; + +CONSTANT: employees { + T{ employee f "Tyler Bennett" "E10297" 32000 "D101" } + T{ employee f "John Rappl" "E21437" 47000 "D050" } + T{ employee f "George Woltman" "E00127" 53500 "D101" } + T{ employee f "Adam Smith" "E63535" 18000 "D202" } + T{ employee f "Claire Buckman" "E39876" 27800 "D202" } + T{ employee f "David McClellan" "E04242" 41500 "D101" } + T{ employee f "Rich Holcomb" "E01234" 49500 "D202" } + T{ employee f "Nathan Adams" "E41298" 21900 "D050" } + T{ employee f "Richard Potter" "E43128" 15900 "D101" } + T{ employee f "David Motsinger" "E27002" 19250 "D202" } + T{ employee f "Tim Sampair" "E03033" 27000 "D101" } + T{ employee f "Kim Arlich" "E10001" 57000 "D190" } + T{ employee f "Timothy Grove" "E16398" 29900 "D190" } + } + +: group-by ( seq quot -- hash ) + H{ } clone [ '[ dup @ _ push-at ] each ] keep ; inline + +: prepare-departments ( seq -- departments ) + [ department>> ] group-by + [ [ salary>> ] inv-sort-with ] assoc-map ; + +: first-n-each ( seq n quot -- ) + [ short head-slice ] dip each ; inline + +: top-rank-main ( -- ) + employees prepare-departments [ + [ "Department " write write ":" print ] dip + 3 [ + [ id>> write " $" write ] + [ salary>> number>string write " " write ] + [ name>> print ] tri + ] first-n-each + nl + ] assoc-each ; + +MAIN: top-rank-main diff --git a/extra/rosetta-code/towers-of-hanoi/towers-of-hanoi.factor b/extra/rosetta-code/towers-of-hanoi/towers-of-hanoi.factor new file mode 100644 index 0000000000..2e7919e900 --- /dev/null +++ b/extra/rosetta-code/towers-of-hanoi/towers-of-hanoi.factor @@ -0,0 +1,21 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: formatting kernel locals math ; +IN: rosetta-code.towers-of-hanoi + +! http://rosettacode.org/wiki/Towers_of_Hanoi + +! In this task, the goal is to solve the Towers of Hanoi problem +! with recursion. + +: move ( from to -- ) + "%d->%d\n" printf ; + +:: hanoi ( n from to other -- ) + n 0 > [ + n 1 - from other to hanoi + from to move + n 1 - other to from hanoi + ] when ; + +! USAGE: 3 1 3 2 hanoi diff --git a/extra/rosetta-code/tree-traversal/tree-traversal.factor b/extra/rosetta-code/tree-traversal/tree-traversal.factor new file mode 100644 index 0000000000..1a0ad9f449 --- /dev/null +++ b/extra/rosetta-code/tree-traversal/tree-traversal.factor @@ -0,0 +1,99 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: accessors combinators deques dlists fry io kernel +math.parser ; +IN: rosetta-code.tree-traversal + +! http://rosettacode.org/wiki/Tree_traversal + +! Implement a binary tree where each node carries an integer, +! and implement preoder, inorder, postorder and level-order +! traversal. Use those traversals to output the following tree: + +! 1 +! / \ +! / \ +! / \ +! 2 3 +! / \ / +! 4 5 6 +! / / \ +! 7 8 9 + +! The correct output should look like this: + +! preorder: 1 2 4 7 5 3 6 8 9 +! inorder: 7 4 2 5 1 8 6 9 3 +! postorder: 7 4 5 2 8 9 6 3 1 +! level-order: 1 2 3 4 5 6 7 8 9 + +TUPLE: node data left right ; + +CONSTANT: example-tree + T{ node f 1 + T{ node f 2 + T{ node f 4 + T{ node f 7 f f } + f + } + T{ node f 5 f f } + } + T{ node f 3 + T{ node f 6 + T{ node f 8 f f } + T{ node f 9 f f } + } + f + } + } + +: preorder ( node quot: ( data -- ) -- ) + [ [ data>> ] dip call ] + [ [ left>> ] dip over [ preorder ] [ 2drop ] if ] + [ [ right>> ] dip over [ preorder ] [ 2drop ] if ] + 2tri ; inline recursive + +: inorder ( node quot: ( data -- ) -- ) + [ [ left>> ] dip over [ inorder ] [ 2drop ] if ] + [ [ data>> ] dip call ] + [ [ right>> ] dip over [ inorder ] [ 2drop ] if ] + 2tri ; inline recursive + +: postorder ( node quot: ( data -- ) -- ) + [ [ left>> ] dip over [ postorder ] [ 2drop ] if ] + [ [ right>> ] dip over [ postorder ] [ 2drop ] if ] + [ [ data>> ] dip call ] + 2tri ; inline recursive + +: (levelorder) ( dlist quot: ( data -- ) -- ) + over deque-empty? [ 2drop ] [ + [ dup pop-front ] dip { + [ [ data>> ] dip call drop ] + [ drop left>> [ swap push-back ] [ drop ] if* ] + [ drop right>> [ swap push-back ] [ drop ] if* ] + [ nip (levelorder) ] + } 3cleave + ] if ; inline recursive + +: levelorder ( node quot: ( data -- ) -- ) + [ 1dlist ] dip (levelorder) ; inline + +: levelorder2 ( node quot: ( data -- ) -- ) + [ 1dlist ] dip + [ dup deque-empty? not ] swap '[ + dup pop-front + [ data>> @ ] + [ left>> [ over push-back ] when* ] + [ right>> [ over push-back ] when* ] tri + ] while drop ; inline + +: tree-traversal-main ( -- ) + example-tree [ number>string write " " write ] { + [ "preorder: " write preorder nl ] + [ "inorder: " write inorder nl ] + [ "postorder: " write postorder nl ] + [ "levelorder: " write levelorder nl ] + [ "levelorder2: " write levelorder2 nl ] + } 2cleave ; + +MAIN: tree-traversal-main diff --git a/extra/rosetta-code/web-scraping/web-scraping.factor b/extra/rosetta-code/web-scraping/web-scraping.factor new file mode 100644 index 0000000000..402a960124 --- /dev/null +++ b/extra/rosetta-code/web-scraping/web-scraping.factor @@ -0,0 +1,21 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: http.client io kernel math sequences ; +IN: rosetta-code.web-scraping + +! http://rosettacode.org/wiki/Web_scraping + +! Create a program that downloads the time from this URL: +! http://tycho.usno.navy.mil/cgi-bin/timer.pl and then prints the +! current UTC time by extracting just the UTC time from the web +! page's HTML. + +! If possible, only use libraries that come at no extra monetary +! cost with the programming language and that are widely available +! and popular such as CPAN for Perl or Boost for C++. + +: web-scraping-main ( -- ) + "http://tycho.usno.navy.mil/cgi-bin/timer.pl" http-get nip + [ "UTC" swap start [ 9 - ] [ 1 - ] bi ] keep subseq print ; + +MAIN: web-scraping-main diff --git a/extra/rosetta-code/y-combinator/y-combinator-tests.factor b/extra/rosetta-code/y-combinator/y-combinator-tests.factor new file mode 100644 index 0000000000..f0abf72e49 --- /dev/null +++ b/extra/rosetta-code/y-combinator/y-combinator-tests.factor @@ -0,0 +1,6 @@ +USING: kernel tools.test ; +IN: rosettacode.y-combinator + +[ 120 ] [ 5 [ almost-fac ] Y call ] unit-test +[ 8 ] [ 6 [ almost-fib ] Y call ] unit-test + diff --git a/extra/rosetta-code/y-combinator/y-combinator.factor b/extra/rosetta-code/y-combinator/y-combinator.factor new file mode 100644 index 0000000000..fed325b9f0 --- /dev/null +++ b/extra/rosetta-code/y-combinator/y-combinator.factor @@ -0,0 +1,31 @@ +! Copyright (c) 2012 Anonymous +! See http://factorcode.org/license.txt for BSD license. +USING: fry kernel math ; +IN: rosettacode.y-combinator + +! http://rosettacode.org/wiki/Y_combinator + +! In strict functional programming and the lambda calculus, +! functions (lambda expressions) don't have state and are only +! allowed to refer to arguments of enclosing functions. This rules +! out the usual definition of a recursive function wherein a +! function is associated with the state of a variable and this +! variable's state is used in the body of the function. + +! The Y combinator is itself a stateless function that, when +! applied to another stateless function, returns a recursive +! version of the function. The Y combinator is the simplest of the +! class of such functions, called fixed-point combinators. + +! The task is to define the stateless Y combinator and use it to +! compute factorials and Fibonacci numbers from other stateless +! functions or lambda expressions. + +: Y ( quot -- quot ) + '[ [ dup call call ] curry _ call ] dup call( x -- x ) ; + +: almost-fac ( quot -- quot ) + '[ dup zero? [ drop 1 ] [ dup 1 - _ call * ] if ] ; + +: almost-fib ( quot -- quot ) + '[ dup 2 >= [ 1 2 [ - _ call ] bi-curry@ bi + ] when ] ;