不同语言的因子algorithm

我想看看你能想出的所有不同的方法,一个阶乘子程序或程序。 希望任何人都能来这里看看他们是否想学习一门新的语言。

思路:

  • 程序
  • 实用
  • 面向对象
  • 一个内衬
  • 混淆
  • 古怪
  • 错误的代码
  • 多语种

基本上我想看一个例子,写一个algorithm的不同方式,以及他们在不同语言中的样子。

请限制每个条目的一个例子。 如果你试图强调一个特定的风格,语言,或只是一个适合在一个职位上的思想清晰的想法,我会让你每个答案有不止一个例子。

唯一真正的要求是它必须find所有语言所代表的一个给定论据的阶乘。

有创意!

推荐指南:

 #语言名称:可选样式types

    - 可选项目符号

    代码在这里

其他信息文本在这里

我会ocasionally去编辑任何没有体面格式的答案。

Polyglot:5种语言,全部使用bignums

于是,我写了一篇以我经常写的三种语言写作的多语种语言,以及另外一个关于这个问题的答案,以及我今天刚刚学到的一个。 这是一个独立的程序,它读取一个包含非负整数的单行,并打印包含其阶乘的单行。 所有语言都使用Bignum,所以最大可计算因子仅取决于您的计算机资源。

  • Perl :使用内置的bignum包。 用perl FILENAME运行。
  • Haskell :使用内置的bignums。 用runhugs FILENAME或你最喜欢的编译器的等价物运行。
  • C ++ :需要GMP支持bignum。 用g ++编译,使用g++ -lgmpxx -lgmp -x c++ FILENAME来链接正确的库。 编译后,运行./a.out 。 或者使用你最喜欢的编译器的等效。
  • brainf * ck :我在这篇文章中写了一些bignum的支持。 使用Muller的经典发行版 ,使用bf < FILENAME > EXECUTABLE编译bf < FILENAME > EXECUTABLE 。 使输出可执行并运行它。 或者使用你最喜欢的发行版
  • 空格 :使用内置的bignum支持。 用wspace FILENAME运行。

编辑:添加Whitespace作为第五语言。 顺便说一句,不要用<code>标签包装代码; 它打破了空白。 而且,这个代码在固定宽度上看起来好多了。

  char //#b = 0 + 0 { -  | 0 * /;  #>>>>,---------- [>>>>,--------
 #define a / *# - ] >>>> ++ <<<<<<<< [> ++++++ [<------>  - ] < -  <<<
 #Perl> <> <> <> <> <> <<] >>>> [[>> + <<  - ] >> [<< +> +>  - ] < - >
 #C ++  - > <> <> <> <> <> <> <> <+ <[>>>> + <<<  -  <[ - ]]> [ - ]
 #Haskell >>]> [ -  <<<<< [<<<<] >>>> [[>> + <<  - ] >> [<< +> +>  - ] >>]
 #Whitespace >>>> [ -  [> + < - ] + >>>>] <<<< [<<<<] <<<< [<<<<
 #brainf * ck> <] >>>>> [>>> [>>>>] >>>> [>>>>] <<<< [[>>>> * /
 EXP;  ; //;#+ <<<<  - ] <<<] >>>> + <<<<<<< [<<<<] [POLYGLOT ^ 5。
 #include <gmpxx.h> //] >>>>  -  [>>> [>>>>] >>>> [>>>>] <<<< [>>
 #define eval int main()//> + <<<  - ] >>> [<<< + >> +>  - >
 #include <iostream> // <] < -  [>> + << [ - ]] << [<<<<] >>>> [> [>>>
 #define print std :: cout << //> <+ < - ]> [<< +> +>  - ] << [>>>
 #define z std :: cin >> // << + <<<  - ] >>> [<<< + >> +>  - ] < - > +++++
 #define c / * ++++ [ -  <[ -  [>>>> + <<<<  - ]] >>>> [<<<< + >>>>  - ] << * /
 #define abs int $ n //> <<] <[>> + <<<< [ - ] >> [<< + >>  - ]] >>] <
 #define uc mpz_class fact(int $ n){/ * <<< [<<<<] <<< [<<
使用bignum; sub#<<] >>>>  - ] >>>>] >>> [> [ - ] >>>] <<<< [>> + <<  - ]
 z {$ _ [0 + 0] = readline(* STDIN);} sub fact {my($ n)= shift;#>>
 #[<< +> +>  - ] < - > + <[>  -  <[ - ]]> [ -  <<  -  <<<< [>> + <<  - ] >> [<< +> +> + * /
 uc; if($ n == 0){return 1;} return $ n * fact($ n-1);  } //;#
 eval {abs; z($ n); print fact($ n); print(“\ n”)/ * 2;};# - ] < - >
 “+ <[>  -  <[ - ]]>] << [<<<] <<<<  -  [>> + <<  - ] >> [<< +> +>  - ] + <[>  - +++
 - }  -  <[ - ]]> [ -  << ++++++++++ <<<<  -  [>> + <<  - ] >> [<< +> +>  -  ++
其实0 = 1  - > <> <> <> <> <> <> <] + <[>  -  <[ - ]]>] << [
事实n = n * fact(n-1){ -  <<] >>>> [[>> + <<  - ] >> [<< +> +++> +  - }
 main = do {n <-readLn; print(fact n)}  -  +>  - ] < - > + <[>>>> + << +
 {-x < -  <[ - ]]> [ - ] >>]>] >>> [>>>>] <<<< [> +++++++ [<+++++++ >  - ]
 < -  <<<<] +书面+ +++由A +雷克斯+++ 2009 +';#+++ X  - }  -  X * /;}

lolcode:

对不起,我无法抗拒xD

 HAI CAN HAS STDIO? I HAS A VAR I HAS A INT I HAS A CHEEZBURGER I HAS A FACTORIALNUM IM IN YR LOOP UP VAR!!1 TIEMZD INT!![CHEEZBURGER] UP FACTORIALNUM!!1 IZ VAR BIGGER THAN FACTORIALNUM? GTFO IM OUTTA YR LOOP U SEEZ INT KTHXBYE 

这是更快的algorithm之一,多达170! 。 它的失败难以解释超过170 !,对于小的因子分解来说相对较慢,但对于80到170之间的分解因子而言,与许多algorithm相比,这是非常快的。

 curl http://www.google.com/search?q=170! 

还有一个在线界面, 现在就试试吧!

让我知道如果你发现一个错误,或更快的实现大的阶乘。


编辑:

这个algorithm稍微慢一点,但是结果超出了170:

 curl http://www58.wolframalpha.com/input/?i=171! 

它也简化成各种其他表示。

C ++:模板元编程

使用经典的枚举黑客。

 template<unsigned int n> struct factorial { enum { result = n * factorial<n - 1>::result }; }; template<> struct factorial<0> { enum { result = 1 }; }; 

用法。

 const unsigned int x = factorial<4>::result; 

因子在编译时根据模板参数n完全计算。 因此,一旦编译器完成工作,factorial <4> :: result就是一个常量。

空白

 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。
 。

这很难让它在这里正确显示,但现在我试图从预览中复制它,它的工作原理。 您需要input号码并按回车。

我发现下面的实现只是很搞笑:

Haskell程序员的演变

Python程序员的演变

请享用!

C#查找:

没有什么可以计算的,只是查一查。 要扩展它,添加另外8个数字到表中,并且64位整数处于它们的极限。 除此之外,还需要一个BigNum类。

 public static int Factorial(int f) { if (f<0 || f>12) { throw new ArgumentException("Out of range for integer factorial"); } int [] fact={1,1,2,6,24,120,720,5040,40320,362880,3628800, 39916800,479001600}; return fact[f]; } 

懒惰的 K

你纯粹的function编程噩梦成真!

唯一的深奥的图灵完整编程语言 ,具有:

  • 一个纯粹的function基础,核心和库 – 事实上,这里是完整的API: SKI
  • 甚至没有lambdas !
  • 没有数字或列表需要或允许
  • 没有明确的recursion,但是, 允许recursion
  • 一个简单的无限惰stream基于I / O机制

以下是所有括号内的Factorial代码:

 K(SII(S(K(S(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(K(S(K(S(K(S(K(S(SI(K(S(K(S(S(KS)K)I)) (S(S(KS)K)(SII(S(S(KS)K)I))))))))K))))))(S(K(S(K(S(SI(K(S(K(S(SI(K(S(K(S(S(KS)K)I)) (S(S(KS)K)(SII(S(S(KS)K)I))(S(S(KS)K))(S(SII)I(S(S(KS)K)I))))))))K))))))) (S(S(KS)K)(K(S(S(KS)K)))))))))(K(S(K(S(S(KS)K)))K))))(SII))II) 

特征:

  • 没有减法或条件
  • 打印所有因子(如果您等待足够长的时间)
  • 使用第二层教会数字将第N个因子转换为N! 星号跟着一个换行符
  • 使用Y组合器进行recursion

如果您有兴趣尝试理解它,请使用Lazier编译器运行的Scheme源代码:

 (lazy-def '(fac input) '((Y (lambda (fna) ((lambda (b) ((cons 10) ((b (cons 42)) (f (1+ n) b)))) (* an)))) 1 1)) 

(对于Y,cons,1,10,42,1+和*的合适的定义)。

编辑:

懒十K因子十进制

( 10KB的胡言乱语 ,否则我会粘贴它)。 例如,在Unix提示符下:

     $ echo“4”|  ./lazy facdec.lazy
     24
     $ echo“5”|  ./lazy facdec.lazy
     120

上面的数字比较慢,比如说5。

代码是臃肿的,因为我们必须包括我们自己的所有原语 (用Hazy编写的代码,lambda演算解释器和用Haskell编写的LC到Lazy K编译器)的库代码 。

XSLT 1.0

input文件factorial.xml

 <?xml version="1.0"?> <?xml-stylesheet href="factorial.xsl" type="text/xsl" ?> <n> 20 </n> 

XSLT文件factorial.xsl

 <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" > <xsl:output method="text"/> <!-- 0! = 1 --> <xsl:template match="text()[. = 0]"> 1 </xsl:template> <!-- n! = (n-1)! * n--> <xsl:template match="text()[. > 0]"> <xsl:variable name="x"> <xsl:apply-templates select="msxsl:node-set( . - 1 )/text()"/> </xsl:variable> <xsl:value-of select="$x * ."/> </xsl:template> <!-- Calculate n! --> <xsl:template match="/n"> <xsl:apply-templates select="text()"/> </xsl:template> </xsl:stylesheet> 

将这两个文件保存在同一个目录中,并在IE中打开factorial.xml

Python:function,单线程

 factorial = lambda n: reduce(lambda x,y: x*y, range(1, n+1), 1) 

注意:

  • 它支持大整数。 例:

 print factorial(100) 93326215443944152681699238856266700490715968264381621468592963895217599993229915\ 608941463976156518286253697920827223758251185210916864000000000000000000000000 

  • 它不适用于n <0

APL (古怪/单线):

 ×/⍳X 
  1. X将X扩展为整数1..X的数组
  2. ×/乘以数组中的每个元素

或者使用内置的运算符:

 !X 

资料来源: http : //www.webber-labs.com/mpl/lectures/ppt-slides/01.ppt

Perl6

 sub factorial ($n) { [*] 1..$n } 

我几乎不知道Perl6。 但是我猜这个[*]运算符和Haskell的product是一样的。

这个代码运行在帕格 ,也许鹦鹉 (我没有检查它。)

编辑

这个代码也起作用。

 sub postfix:<!> ($n) { [*] 1..$n } # This function(?) call like below ... It looks like mathematical notation. say 10!; 

x86-64汇编:程序

你可以从C调用它(只在linux amd64上用GCC进行testing)。 大会与nasm组装。

 section .text global factorial ; factorial in x86-64 - n is passed in via RDI register ; takes a 64-bit unsigned integer ; returns a 64-bit unsigned integer in RAX register ; C declaration in GCC: ; extern unsigned long long factorial(unsigned long long n); factorial: enter 0,0 ; n is placed in rdi by caller mov rax, 1 ; factorial = 1 mov rcx, 2 ; i = 2 loopstart: cmp rcx, rdi ja loopend mul rcx ; factorial *= i inc rcx jmp loopstart loopend: leave ret 

在Inform 7中recursion地

(它让你想起COBOL,因为它是用来写文本冒险的;比例字体是故意的):

决定(n – 一个数字)的阶乘是多less?
如果n是零,则决定一个;
否则决定(n减1)n的阶乘。

如果你想从游戏中调用这个函数(“短语”),你需要定义一个动作和语法规则:

“阶乘游戏”[这一定是源头的第一行]

有一个房间。 [必须至less有一个!]

因式分解是适用于一个数字的操作。

理解“阶乘[数字]”作为因式分解。

进行sorting:
设n是所理解数目的阶乘。
说“这是[n]”。

C#:LINQ

  public static int factorial(int n) { return (Enumerable.Range(1, n).Aggregate(1, (previous, value) => previous * value)); } 

Erlang:尾recursion

 fac(0) -> 1; fac(N) when N > 0 -> fac(N, 1). fac(1, R) -> R; fac(N, R) -> fac(N - 1, R * N). 

哈斯克尔:

 ones = 1 : ones integers = head ones : zipWith (+) integers (tail ones) factorials = head integers : zipWith (*) factorials (tail integers) 

Brainf * CK

 +++++ >+<[[->>>>+<<<<]>>>>[-<<<<+>>+>>]<<<<>[->>+<<]<>>>[-<[->>+<<]>>[-<<+<+>>>]<]<[-]><<<-] 

由Michael Reitzenstein撰写。

BASIC:老派

 10 HOME 20 INPUT N 30 LET ANS = 1 40 FOR I = 1 TO N 50 ANS = ANS * I 60 NEXT I 70 PRINT ANS 

批次(NT):

 @echo off set n=%1 set result=1 for /l %%i in (%n%, -1, 1) do ( set /a result=result * %%i ) echo %result% 

用法:C:> factorial.bat 15

F#:function

直前进:

 let rec fact x = if x < 0 then failwith "Invalid value." elif x = 0 then 1 else x * fact (x - 1) 

变得花俏:

 let fact x = [1 .. x] |> List.fold_left ( * ) 1 

recursionProlog

 fac(0,1). fac(N,X) :- N1 is N -1, fac(N1, T), X is N * T. 

尾recursionProlog

 fac(0,N,N). fac(X,N,T) :- A is N * X, X1 is X - 1, fac(X1,A,T). fac(N,T) :- fac(N,1,T). 

rubyrecursion

 (factorial=Hash.new{|h,k|k*h[k-1]})[1]=1 

用法:

 factorial[5] => 120 

scheme

这是一个简单的recursion定义:

 (define (factorial x) (if (= x 0) 1 (* x (factorial (- x 1))))) 

在Scheme中,尾recursion函数使用常量堆栈空间。 这是一个尾recursion的阶乘版本:

 (define factorial (letrec ((fact (lambda (x accum) (if (= x 0) accum (fact (- x 1) (* accum x)))))) (lambda (x) (fact x 1)))) 

Oddball的例子? 怎么使用伽玛function! 既然, Gamma n = (n-1)!

OCaml:使用Gamma

 let rec gamma z = let pi = 4.0 *. atan 1.0 in if z < 0.5 then pi /. ((sin (pi*.z)) *. (gamma (1.0 -. z))) else let consts = [| 0.99999999999980993; 676.5203681218851; -1259.1392167224028; 771.32342877765313; -176.61502916214059; 12.507343278686905; -0.13857109526572012; 9.9843695780195716e-6; 1.5056327351493116e-7; |] in let z = z -. 1.0 in let results = Array.fold_right (fun xy -> x +. y) (Array.mapi (fun ix -> if i = 0 then x else x /. (z+.(float i))) consts ) 0.0 in let x = z +. (float (Array.length consts)) -. 1.5 in let final = (sqrt (2.0*.pi)) *. (x ** (z+.0.5)) *. (exp (-.x)) *. result in final let factorial_gamma n = int_of_float (gamma (float (n+1))) 

新生Haskell程序员

 fac n = if n == 0 then 1 else n * fac (n-1) 

大二的Haskell程序员,在麻省理工学院(大一学习Scheme)

 fac = (\(n) -> (if ((==) n 0) then 1 else ((*) n (fac ((-) n 1))))) 

初级Haskell程序员(开始Peano玩家)

 fac 0 = 1 fac (n+1) = (n+1) * fac n 

另一名初级Haskell程序员(读到n + k模式是“Haskell恶心的一部分”[1],并join了“Ban n + k模式”运动[2])

 fac 0 = 1 fac n = n * fac (n-1) 

Haskell高级程序员(尼克松Buchanan布什投票 – “倾斜”)

 fac n = foldr (*) 1 [1..n] 

另一位高级Haskell程序员(投票赞成麦戈文比夫拉纳德 – “向左倾斜”)

 fac n = foldl (*) 1 [1..n] 

还有另外一个Haskell的程序员(到目前为止,他又回来了!)

 -- using foldr to simulate foldl fac n = foldr (\xgn -> g (x*n)) id [1..n] 1 

记住Haskell程序员(每日银杏叶)

 facs = scanl (*) 1 [1..] fac n = facs !! n 

毫无意义(ahem)“无分”Haskell程序员(在牛津学习)

 fac = foldr (*) 1 . enumFromTo 1 

迭代Haskell程序员(原Pascal程序员)

 fac n = result (for init next done) where init = (0,1) next (i,m) = (i+1, m * (i+1)) done (i,_) = i==n result (_,m) = m for ind = until dni 

迭代单线程Haskell程序员(原APL和C程序员)

 fac n = snd (until ((>n) . fst) (\(i,m) -> (i+1, i*m)) (1,1)) 

积累Haskell程序员(build立一个快速的高潮)

 facAcc a 0 = a facAcc an = facAcc (n*a) (n-1) fac = facAcc 1 

继续传递Haskell程序员(早年提出了RABBITS,然后搬到新泽西州)

 facCps k 0 = k 1 facCps kn = facCps (k . (n *)) (n-1) fac = facCps id 

童子军Haskell程序员(喜欢打结;总是“虔诚的”,他属于最低定点教会[8])

 yf = f (yf) fac = y (\fn -> if (n==0) then 1 else n * f (n-1)) 

组合Haskell程序员(避开variables,如果不是混淆,所有这些currying只是一个阶段,尽pipe它很less妨碍)

 sfgx = fx (gx) kxy = x bfgx = f (gx) cfgx = fxg yf = f (yf) cond pfgx = if px then fx else gx fac = y (b (cond ((==) 0) (k 1)) (b (s (*)) (cb pred))) 

列表编码Haskell程序员(更喜欢以一元计数)

 arb = () -- "undefined" is also a good RHS, as is "arb" :) listenc n = replicate n arb listprj f = length . f . listenc listprod xs ys = [ i (x,y) | x<-xs, y<-ys ] where i _ = arb facl [] = listenc 1 facl n@(_:pred) = listprod n (facl pred) fac = listprj facl 

解释Haskell程序员(从来没有“遇到一种语言”,他不喜欢)

 -- a dynamically-typed term language data Term = Occ Var | Use Prim | Lit Integer | App Term Term | Abs Var Term | Rec Var Term type Var = String type Prim = String -- a domain of values, including functions data Value = Num Integer | Bool Bool | Fun (Value -> Value) instance Show Value where show (Num n) = show n show (Bool b) = show b show (Fun _) = "" prjFun (Fun f) = f prjFun _ = error "bad function value" prjNum (Num n) = n prjNum _ = error "bad numeric value" prjBool (Bool b) = b prjBool _ = error "bad boolean value" binOp inj f = Fun (\i -> (Fun (\j -> inj (f (prjNum i) (prjNum j))))) -- environments mapping variables to values type Env = [(Var, Value)] getval x env = case lookup x env of Just v -> v Nothing -> error ("no value for " ++ x) -- an environment-based evaluation function eval env (Occ x) = getval x env eval env (Use c) = getval c prims eval env (Lit k) = Num k eval env (App mn) = prjFun (eval env m) (eval env n) eval env (Abs xm) = Fun (\v -> eval ((x,v) : env) m) eval env (Rec xm) = f where f = eval ((x,f) : env) m -- a (fixed) "environment" of language primitives times = binOp Num (*) minus = binOp Num (-) equal = binOp Bool (==) cond = Fun (\b -> Fun (\x -> Fun (\y -> if (prjBool b) then x else y))) prims = [ ("*", times), ("-", minus), ("==", equal), ("if", cond) ] -- a term representing factorial and a "wrapper" for evaluation facTerm = Rec "f" (Abs "n" (App (App (App (Use "if") (App (App (Use "==") (Occ "n")) (Lit 0))) (Lit 1)) (App (App (Use "*") (Occ "n")) (App (Occ "f") (App (App (Use "-") (Occ "n")) (Lit 1)))))) fac n = prjNum (eval [] (App facTerm (Lit n))) 

静态的Haskell程序员(他是用class来做的,他有那个fundep Jones!在Thomas Hallgren的“Fun with Functional Dependencies”之后[7])

 -- static Peano constructors and numerals data Zero data Succ n type One = Succ Zero type Two = Succ One type Three = Succ Two type Four = Succ Three -- dynamic representatives for static Peanos zero = undefined :: Zero one = undefined :: One two = undefined :: Two three = undefined :: Three four = undefined :: Four -- addition, a la Prolog class Add abc | ab -> c where add :: a -> b -> c instance Add Zero bb instance Add abc => Add (Succ a) b (Succ c) -- multiplication, a la Prolog class Mul abc | ab -> c where mul :: a -> b -> c instance Mul Zero b Zero instance (Mul abc, Add bcd) => Mul (Succ a) bd -- factorial, a la Prolog class Fac ab | a -> b where fac :: a -> b instance Fac Zero One instance (Fac nk, Mul (Succ n) km) => Fac (Succ n) m -- try, for "instance" (sorry): -- -- :t fac four 

刚gradle的Haskell程序员(研究生教育倾向于从一个小问题上解放出来,例如基于硬件的整数的效率)

 -- the natural numbers, a la Peano data Nat = Zero | Succ Nat -- iteration and some applications iter zs Zero = z iter zs (Succ n) = s (iter zsn) plus n = iter n Succ mult n = iter Zero (plus n) -- primitive recursion primrec zs Zero = z primrec zs (Succ n) = sn (primrec zsn) -- two versions of factorial fac = snd . iter (one, one) (\(a,b) -> (Succ a, mult ab)) fac' = primrec one (mult . Succ) -- for convenience and testing (try eg "fac five") int = iter 0 (1+) instance Show Nat where show = show . int (zero : one : two : three : four : five : _) = iterate Succ Zero 

原始Haskell程序员(总是从“基本的鸟褶”开始)

 -- (curried, list) fold and an application fold cn [] = n fold cn (x:xs) = cx (fold cn xs) prod = fold (*) 1 -- (curried, boolean-based, list) unfold and an application unfold pfgx = if px then [] else fx : unfold pfg (gx) downfrom = unfold (==0) id pred -- hylomorphisms, as-is or "unfolded" (ouch! sorry ...) refold cnpfg = fold cn . unfold pfg refold' cnpfgx = if px then n else c (fx) (refold' cnpfg (gx)) -- several versions of factorial, all (extensionally) equivalent fac = prod . downfrom fac' = refold (*) 1 (==0) id pred fac'' = refold' (*) 1 (==0) id pred 

笛卡尔倾向的Haskell程序员(喜欢希腊食物,避免辛辣的印度东西;灵感来自Lex Augusteijn的“Sorting Morphisms”[3])

 -- (product-based, list) catamorphisms and an application cata (n,c) [] = n cata (n,c) (x:xs) = c (x, cata (n,c) xs) mult = uncurry (*) prod = cata (1, mult) -- (co-product-based, list) anamorphisms and an application ana f = either (const []) (cons . pair (id, ana f)) . f cons = uncurry (:) downfrom = ana uncount uncount 0 = Left () uncount n = Right (n, n-1) -- two variations on list hylomorphisms hylo fg = cata g . ana f hylo' f (n,c) = either (const n) (c . pair (id, hylo' f (c,n))) . f pair (f,g) (x,y) = (fx, gy) -- several versions of factorial, all (extensionally) equivalent fac = prod . downfrom fac' = hylo uncount (1, mult) fac'' = hylo' uncount (1, mult) 

博士 Haskell程序员(吃了那么多香蕉,他的眼睛没有了,现在他需要新的镜头!)

 -- explicit type recursion based on functors newtype Mu f = Mu (f (Mu f)) deriving Show in x = Mu x out (Mu x) = x -- cata- and ana-morphisms, now for *arbitrary* (regular) base functors cata phi = phi . fmap (cata phi) . out ana psi = in . fmap (ana psi) . psi -- base functor and data type for natural numbers, -- using a curried elimination operator data N b = Zero | Succ b deriving Show instance Functor N where fmap f = nelim Zero (Succ . f) nelim zs Zero = z nelim zs (Succ n) = sn type Nat = Mu N -- conversion to internal numbers, conveniences and applications int = cata (nelim 0 (1+)) instance Show Nat where show = show . int zero = in Zero suck = in . Succ -- pardon my "French" (Prelude conflict) plus n = cata (nelim n suck ) mult n = cata (nelim zero (plus n)) -- base functor and data type for lists data L ab = Nil | Cons ab deriving Show instance Functor (L a) where fmap f = lelim Nil (\ab -> Cons a (fb)) lelim nc Nil = n lelim nc (Cons ab) = cab type List a = Mu (L a) -- conversion to internal lists, conveniences and applications list = cata (lelim [] (:)) instance Show a => Show (List a) where show = show . list prod = cata (lelim (suck zero) mult) upto = ana (nelim Nil (diag (Cons . suck)) . out) diag fx = fxx fac = prod . upto 

博士后Haskell程序员(来自Uustalu,Vene和Pardo的“Comonadsrecursionscheme”[4])

 -- explicit type recursion with functors and catamorphisms newtype Mu f = In (f (Mu f)) unIn (In x) = x cata phi = phi . fmap (cata phi) . unIn -- base functor and data type for natural numbers, -- using locally-defined "eliminators" data N c = Z | S c instance Functor N where fmap g Z = Z fmap g (S x) = S (gx) type Nat = Mu N zero = In Z suck n = In (S n) add m = cata phi where phi Z = m phi (S f) = suck f mult m = cata phi where phi Z = zero phi (S f) = add mf -- explicit products and their functorial action data Prod ec = Pair ce outl (Pair xy) = x outr (Pair xy) = y fork fgx = Pair (fx) (gx) instance Functor (Prod e) where fmap g = fork (g . outl) outr -- comonads, the categorical "opposite" of monads class Functor n => Comonad n where extr :: na -> a dupl :: na -> n (na) instance Comonad (Prod e) where extr = outl dupl = fork id outr -- generalized catamorphisms, zygomorphisms and paramorphisms gcata :: (Functor f, Comonad n) => (forall a. f (na) -> n (fa)) -> (f (nc) -> c) -> Mu f -> c gcata dist phi = extr . cata (fmap phi . dist . fmap dupl) zygo chi = gcata (fork (fmap outl) (chi . fmap outr)) para :: Functor f => (f (Prod (Mu f) c) -> c) -> Mu f -> c para = zygo In -- factorial, the *hard* way! fac = para phi where phi Z = suck zero phi (S (Pair fn)) = mult f (suck n) -- for convenience and testing int = cata phi where phi Z = 0 phi (S f) = 1 + f instance Show (Mu N) where show = show . int 

终身教授(向新生教授哈斯克尔)

 fac n = product [1..n] 

D模板:function

 template factorial(int n : 1) { const factorial = 1; } template factorial(int n) { const factorial = n * factorial!(n-1); } 

要么

 template factorial(int n) { static if(n == 1) const factorial = 1; else const factorial = n * factorial!(n-1); } 

像这样使用:

 factorial!(5) 

Java 1.6: recursive, memoized (for subsequent calls)

 private static Map<BigInteger, BigInteger> _results = new HashMap() public static BigInteger factorial(BigInteger n){ if (0 >= n.compareTo(BigInteger.ONE)) return BigInteger.ONE.max(n); if (_results.containsKey(n)) return _results.get(n); BigInteger result = factorial(n.subtract(BigInteger.ONE)).multiply(n); _results.put(n, result); return result; } 

PowerShell

 function factorial( [int] $n ) { $result = 1; if ( $n -gt 1 ) { $result = $n * ( factorial ( $n - 1 ) ) } $result } 

这里是一个单行的:

 $n..1 | % {$result = 1}{$result *= $_}{$result} 

Bash: Recursive

In bash and recursive, but with the added advantage that it deals with each iteration in a new process. The max it can calculate is !20 before overflowing, but you can still run it for big numbers if you don't care about the answer and want your system to fall over 😉

 #!/bin/bash echo $(($1 * `( [[ $1 -gt 1 ]] && ./$0 $(($1 - 1)) ) || echo 1`));