Dolby is now a Browserling customer!
1 day ago
Yet another computer programming blog.
cfold’ f z [] = z
cfold’ f z (x:xs) = f x z (\y -> cfold’ f y xs)
cfold f z l = cfold’ (\x t g -> f x (g t)) z l
(\x t g -> (*) x (g t))It says that given the head of the list, x, a base value for the fold, t, and the function g that yields the result of the fold for the tail of the list when it is given t, the result of the whole fold is the list head multiplied by the value of the fold for the list tail.
cfold (+) 0 [1]
(\f z l -> cfold' (\x t g -> f x (g t)) z l) (+) 0 [1]
cfold' (\x t g -> (+) x (g t)) 0 [1]
(\f z (x:xs) -> f x z (\y -> cfold' f y xs)) (\x t g -> (+) x (g t)) 0 [1]
(\x t g -> (+) x (g t)) 1 0 (\y -> cfold' (\x t g -> (+) x (g t)) y [])
(+) 1 ((\y -> cfold' (\x t g -> (+) x (g t)) y []) 0)
(+) 1 0
1
$ cd ~/koodi/auto<tab> <enter>
$ j auto <enter>
Then we compile with -O3:#include <stdio.h>
unsigned long int fib(int n) {
if (n < 3)
return 1;
return fib(n-2) + fib(n-1);
}
int main() {
int i;
for (i=1; i < 46; i++)
printf("fib(%d) = %ld\n", i, fib(i));
return 0;
}
llvm-gcc -O3 fib.c -o fib-llvm-gcc
gcc -O3 fib.c -o fib-gcc
time ./fib-llvm-gcc
real 0m3.053s
user 0m3.052s
sys 0m0.000s
time ./fib-gcc
real 0m11.176s
user 0m11.173s
sys 0m0.004s
wc fib-llvm-gcc.S
108 288 1900 fib-llvm-gcc.S
wc fib-gcc.S
291 738 4485 fib-gcc.S
"Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that contains only five floors. Baker does not live on the top floor. Cooper does not live on the bottom floor. Fletcher does not live on either the top or the bottom floor. Miller lives on a higher floor than does Cooper. Smith does not live on a floor adjacent to Fletcher's. Fletcher does not live on a floor adjacent to Cooper's. Where does everyone live?" (SICP, pp. 418)A Haskell version of the (almost) same solution follows (Control.Monad and Data.List are needed):
Nondeterminism allows us to omit writing the loops that try all possible execution paths. Nondeterministic computing can be imagined as if the computer simultaneously tried all the possible branches of a computation, where the computation branches every time there are multiple choices to proceed, and stops the branches that yield no result, and finally, returns all results from the succeeded branches.type Name = String
type Floor = Int
adjacent :: Floor -> Floor -> Bool
adjacent a b = abs (a-b) == 1
distinct :: [Floor] -> Bool
distinct l = l == nub l
dinesman :: [[(Name,Floor)]]
dinesman = do
baker <- [1..5]
cooper <- [1..5]
fletcher <- [1..5]
miller <- [1..5]
smith <- [1..5]
guard (distinct [baker,cooper,fletcher,miller,smith])
guard (baker /= 5)
guard (cooper /= 1)
guard (not (fletcher == 1) || fletcher == 5))
guard (miller > cooper)
guard (not (adjacent smith fletcher))
guard (not (adjacent fletcher cooper))
return [("Baker", baker),
("Cooper", cooper),
("Fletcher", fletcher),
("Miller", miller),
("Smith", smith)]
class Monad m => MonadPlus m whereThe operation mzero denotes failure while the operation mplus denotes choice or combination. Here are the semantics of the operations:
mzero :: m a
mplus :: m a -> m a -> m a
mzero >>= f = mzeroThe first reads that if a failure is applied on some action, the result is still a failure. The second reads that if something other than a failure is added to a failure, the result is the non-failure thing. The third reads that if a failure is added to something other than a failure, the result is again the non-failure thing. The two previous definitions are thus analogous to logical OR. The last one reads that the mplus binary operation is associative.
a `mplus` mzero = a
mzero `mplus` b = b
a `mplus` (b `mplus` c) = (a `mplus` b) `mplus` c
instance MonadPlus [] whereThe previous means that with lists, the empty list represents a failure and appending represents combination.
mzero = []
a `mplus` b = a ++ b
guard :: MonadPlus m => Bool -> m ()So guard is an operation that takes a boolean expression and returns a () value meaning "no information" if the boolean argument evaluates to true, and mzero if the boolean argument evaluates to false.
guard True = return ()
guard False = mzero