]> gitweb.factorcode.org Git - factor.git/blob - extra/project-euler/151/151.factor
Merge git://projects.elasticdog.com/git/factor into public
[factor.git] / extra / project-euler / 151 / 151.factor
1 ! Copyright (c) 2008 Eric Mertens.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: assocs combinators kernel math math.order namespaces sequences
4     sequences.lib ;
5 IN: project-euler.151
6
7 ! http://projecteuler.net/index.php?section=problems&id=151
8
9 ! DESCRIPTION
10 ! -----------
11
12 ! A printing shop runs 16 batches (jobs) every week and each batch requires a
13 ! sheet of special colour-proofing paper of size A5.
14
15 ! Every Monday morning, the foreman opens a new envelope, containing a large
16 ! sheet of the special paper with size A1.
17
18 ! He proceeds to cut it in half, thus getting two sheets of size A2. Then he
19 ! cuts one of them in half to get two sheets of size A3 and so on until he
20 ! obtains the A5-size sheet needed for the first batch of the week.
21
22 ! All the unused sheets are placed back in the envelope.
23
24 ! At the beginning of each subsequent batch, he takes from the envelope one
25 ! sheet of paper at random. If it is of size A5, he uses it. If it is larger,
26 ! he repeats the 'cut-in-half' procedure until he has what he needs and any
27 ! remaining sheets are always placed back in the envelope.
28
29 ! Excluding the first and last batch of the week, find the expected number of
30 ! times (during each week) that the foreman finds a single sheet of paper in
31 ! the envelope.
32
33 ! Give your answer rounded to six decimal places using the format x.xxxxxx .
34
35
36 ! SOLUTION
37 ! --------
38
39 SYMBOL: table
40
41 : (pick-sheet) ( seq i -- newseq )
42     [
43         <=> sgn
44         {
45             { -1 [ ] }
46             {  0 [ 1- ] }
47             {  1 [ 1+ ] }
48         } case
49     ] curry map-index ;
50
51 DEFER: (euler151)
52
53 : pick-sheet ( seq i -- res )
54     2dup swap nth dup zero? [
55         3drop 0
56     ] [
57         [ (pick-sheet) (euler151) ] dip *
58     ] if ;
59
60 : (euler151) ( x -- y )
61     table get [ {
62         { { 0 0 0 1 } [ 0 ] }
63         { { 0 0 1 0 } [ { 0 0 0 1 } (euler151) 1+ ] }
64         { { 0 1 0 0 } [ { 0 0 1 1 } (euler151) 1+ ] }
65         { { 1 0 0 0 } [ { 0 1 1 1 } (euler151) 1+ ] }
66         [ [ dup length [ pick-sheet ] with map sum ] [ sum ] bi / ]
67      } case ] cache ;
68
69 : euler151 ( -- answer )
70     [
71         H{ } clone table set
72         { 1 1 1 1 } (euler151)
73     ] with-scope ;
74
75 ! TODO: doesn't work currently, problem in area of 'with map' in (euler151)
76
77 ! [ euler151 ] 100 ave-time
78 ! ? ms run time - 100 trials
79
80 MAIN: euler151