Факториальные алгоритмы на разных языках

Я хочу видеть все различные способы, с которыми вы можете столкнуться, для факториала подпрограммы или программы. Надежда состоит в том, что каждый может приехать сюда и посмотреть, хотят ли они изучать новый язык.

Идеи:

  • Процедурные
  • Functional
  • Объектно-ориентированный
  • Один вкладыш
  • Запутанный
  • Oddball
  • Плохой код
  • Polyglot

В принципе, я хочу увидеть пример, различные способы написания алгоритма и то, что они будут выглядеть на разных языках.

Пожалуйста, ограничьте его одним примером для каждой записи. Я позволю вам иметь более одного примера для каждого ответа, если вы пытаетесь выделить конкретный стиль, язык или просто продуманную идею, которая поддается одному сообщению.

Единственное реальное требование - найти факториал данного аргумента во всех представленных языках.

Будьте творческими!

Рекомендуемое руководство:

# Language Name: Optional Style type

   - Optional bullet points

    Code Goes Here

Other informational text goes here

Я часто буду идти и отредактировать любой ответ, который не имеет достойного форматирования.

Ответ 1

Полиглот: 5 языков, все с использованием bignums

Итак, я написал полиглот, который работает на трех языках, которые я часто пишу, а также один из моего другого ответа на этот вопрос и тот, который я только что узнал сегодня. Это автономная программа, которая считывает одну строку, содержащую неотрицательное целое число, и печатает одну строку, содержащую ее факториал. Bignums используются на всех языках, поэтому максимальный вычислимый факториал зависит только от ваших ресурсов компьютера.

  • Perl: используется встроенный пакет bignum. Запустите с помощью perl FILENAME.
  • Haskell: использует встроенные бонусы. Запустите с помощью runhugs FILENAME или вашего любимого эквивалента компилятора.
  • С++: требуется GMP для поддержки бонуса. Для компиляции с g++ используйте g++ -lgmpxx -lgmp -x c++ FILENAME для ссылки на нужные библиотеки. После компиляции запустите ./a.out. Или используйте свой любимый эквивалент компилятора.
  • brainf * ck: я написал некоторую поддержку bignum в этом сообщении. Используя классическое распространение Muller, скомпилируйте с 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){/*<<<[<<<<]<<<[<<
use 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;};#-]<->
'+<[>-<[-]]>]<<[<<<<]<<<<-[>>+<<-]>>[<<+>+>-]+<[>-+++
-}--	<[-]]>[-<<++++++++++<<<<-[>>+<<-]>>[<<+>+>-++
fact 0	= 1 -- ><><><><	> <><><	]+<[>-<[-]]>]<<[<<+ +
fact	n=n*fact(n-1){-<<]>>>>[[>>+<<-]>>[<<+>+++>+-}
main=do{n<-readLn;print(fact n)}-- +>-]<->+<[>>>>+<<+
{-x<-<[-]]>[-]>>]>]>>>[>>>>]<<<<[>+++++++[<+++++++>-]
<--.<<<<]+written+by+++A+Rex+++2009+.';#+++x-}--x*/;}

Ответ 2

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    

Ответ 3

Это один из самых быстрых алгоритмов, до 170!. Это не удается, необъяснимо выше 170!, и относительно медленное для небольших факториалов, но для факториалов между 80 и 170 он невероятно быстро по сравнению со многими алгоритмами.

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

Там также есть интерактивный интерфейс попробуйте сейчас!

Сообщите мне, если вы обнаружите ошибку или более быструю реализацию для больших факториалов.


EDIT:

Этот алгоритм немного медленнее, но дает результаты за пределами 170:

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

Он также упрощает их в различные другие представления.

Ответ 4

С++: метапрограммирование шаблонов

Использует классический enum hack.

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 является константой, когда компилятор выполнил свою работу.

Ответ 5

Пробелы

   	.
 .
 	.
		.
  	.
   	.
			 .
 .
	 	 .
	  .
   	.
 .
  .
 			 .
		  			 .
 .
	.
.
  	 .
 .
.
	.
 	.
.
.
.

Трудно было заставить его показать это правильно, но теперь я попытался скопировать его из предварительного просмотра, и он работает. Вам нужно ввести номер и нажать enter.

Ответ 7

Поиск в С#:

Ничего рассчитать на самом деле, просто посмотрите. Чтобы расширить его, добавьте еще 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];
}

Ответ 8

Lazy K

Ваши кошмары с чисто функциональным программированием сбываются!

Единственный Эзотерический полный язык программирования Turing, который имеет:

  • Сугубо функциональный фундамент, ядро ​​и библиотеки --- на самом деле здесь полный API: S K I
  • Нет lambdas даже!
  • Нет числа или списки, необходимые или разрешенные
  • Нет явной рекурсии, но бесконечный ленивый поток - механизм ввода-вывода

Здесь факториальный код во всей его скобке:

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 combinator для рекурсии

Если вы заинтересованы в попытке понять это, вот исходный код Scheme для запуска через компилятор Lazier:

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

(для подходящих определений Y, cons, 1, 10, 42, 1+ и *).

EDIT:

Lazy K Factorial in Decimal

(10 КБ тарабарщины, иначе я бы вставлял его). Например, в приглашении Unix:

    $ echo "4" | ./lazy facdec.lazy
    24
    $ echo "5" | ./lazy facdec.lazy
    120

Довольно медленный для чисел выше, скажем, 5.

Код является раздутым, потому что мы должны включить код библиотеки для всех наших собственных примитивов (код написан на Hazy, интерпретатор lambda calculus и LC-to-Lazy K, написанный в Haskell).

Ответ 9

XSLT 1.0

Входной файл 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>

Сохраните оба файла в одном каталоге и откройте factorial.xml в IE.

Ответ 10

Python: функциональный, однострочный

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

Примечание:

  • Он поддерживает большие целые числа. Пример:

print factorial(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915\
608941463976156518286253697920827223758251185210916864000000000000000000000000

  • Это не работает для n < 0.

Ответ 11

APL (oddball/one-liner):

×/⍳X
  • ⍳X расширяет X в массив целых чисел 1..X
  • ×/умножает каждый элемент в массиве

Или со встроенным оператором:

!X

Источник: http://www.webber-labs.com/mpl/lectures/ppt-slides/01.ppt

Ответ 12

Perl6

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

Я почти не знаю о Perl6. Но я предполагаю, что этот оператор [*] такой же, как Haskell product.

Этот код работает на Pugs и, возможно, Parrot (я не проверял его.)

Edit

Этот код также работает.

sub postfix:<!> ($n) { [*] 1..$n }

# This function(?) call like below ... It looks like mathematical notation.
say 10!;

Ответ 13

x86-64 Сборка: процедурный

Вы можете вызывать это из C (только с GCC на linux amd64). Сборка собрана с 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

Ответ 14

Рекурсивно в Inform 7

(он напоминает вам COBOL, потому что он предназначен для написания текстовых приключений, пропорциональный шрифт преднамерен):

Чтобы решить, какое число является факториалом (n - число):
     , если n равно нулю, выберите один из них;     в противном случае решить факториал (n минус один) раз n.

Если вы хотите называть эту функцию ( "фразу" ) из игры, вам нужно определить правило действия и грамматики:

"Факториальная игра" [это должна быть первая строка источника]

Есть комната. [должен быть хотя бы один!]

Факториализация - это действие, применяемое к числу.

Понять "факториал [число]" как факторизацию.

Проведение факториализации:
          n - факториал числа, понимаемого,     Скажите "Это [n]".

Ответ 15

Haskell:

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

Ответ 16

С#: LINQ

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

Ответ 17

Эрланг: хвост рекурсивный

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

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

Ответ 18

Brainf * ск

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

Написал Майкл Рейтстенштейн.

Ответ 19

ОСНОВНАЯ: старая школа

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

Ответ 20

F #: Функциональный

Прямо вперед:

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

Ответ 21

Пакет (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

Ответ 22

Рекурсивный пролог

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

Рекурсивный пролог хвоста

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).

Ответ 23

ruby ​​recursive

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

использование:

factorial[5]
 => 120

Ответ 24

Схема

Вот простое рекурсивное определение:

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

В хвостовых рекурсивных функциях схемы используется постоянное пространство стека. Вот версия факториала, которая является хвостовой рекурсивной:

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

Ответ 25

D Шаблоны: Функциональные

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)

Ответ 26

Нечетные примеры? Как насчет использования гамма-функции! Поскольку 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 x y -> x +. y)
                          (Array.mapi 
                              (fun i x -> 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)))

Ответ 27

Программист Freshman Haskell

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

Программист Sophomore Haskell в MIT (изучена схема как первокурсник)

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] и присоединился к "Ban n + k patterns" -movement [2])

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

Старший программист Haskell (проголосовали за Никсона Бьюкенена Буша - "склоняется вправо" )

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

Другой старший программист Haskell (проголосовали за Макговерна Биафра Надер - "наклоняется влево" )

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

Еще один старший программист Haskell (наклонился так далеко, он снова вернулся!)

-- using foldr to simulate foldl

fac n = foldr (\x g n -> g (x*n)) id [1..n] 1

Память программиста Haskell (ежедневно принимает Гинкго Билоба)

facs = scanl (*) 1 [1..]

fac n = facs !! n

Бессмысленный (ахм) "Непосредственный" программист 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 i n d = until d n i

Итеративный однострочный программист Haskell (бывший программист APL и C)

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

Накопительный программист Haskell (создание до быстрой кульминации)

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

fac = facAcc 1

Продолжающий проход программист Haskell (поднял RABBITS в первые годы, затем переехал в Нью-Джерси)

facCps k 0 = k 1
facCps k n = facCps (k . (n *)) (n-1)

fac = facCps id

Бойскаут-программист Haskell (любит привязывать узлы, всегда "почтительно", он принадлежит Церкви наименее фиксированной точки [8])

y f = f (y f)

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

Комбинированный программист Haskell (избегает переменных, если не обфускации; все это curryings просто фаза, хотя это редко мешает)

s f g x = f x (g x)

k x y   = x

b f g x = f (g x)

c f g x = f x g

y f     = f (y f)

cond p f g x = if p x then f x else g x

fac  = y (b (cond ((==) 0) (k 1)) (b (s (*)) (c b 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 [email protected](_: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 m n) = prjFun (eval env m) (eval env n)
eval env (Abs x m) = Fun  (\v -> eval ((x,v) : env) m)
eval env (Rec x m) = 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 (он делает это с классом, hes получил, что fundep Джонс! После Томаса Холлгренса "Забава с функциональными зависимостями" [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 a b c | a b -> c where
  add :: a -> b -> c

instance              Add  Zero    b  b
instance Add a b c => Add (Succ a) b (Succ c)


-- multiplication, a la Prolog

class Mul a b c | a b -> c where
  mul :: a -> b -> c

instance                           Mul  Zero    b Zero
instance (Mul a b c, Add b c d) => Mul (Succ a) b d


-- factorial, a la Prolog

class Fac a b | a -> b where
  fac :: a -> b

instance                                Fac  Zero    One
instance (Fac n k, Mul (Succ n) k m) => Fac (Succ n) m

-- try, for "instance" (sorry):
-- 
--     :t fac four

Начинающий выпускник Haskell (высшее образование имеет тенденцию освобождать от мелких проблем о, например, эффективности аппаратных целых чисел)

-- the natural numbers, a la Peano

data Nat = Zero | Succ Nat


-- iteration and some applications

iter z s  Zero    = z
iter z s (Succ n) = s (iter z s n)

plus n = iter n     Succ
mult n = iter Zero (plus n)


-- primitive recursion

primrec z s  Zero    = z
primrec z s (Succ n) = s n (primrec z s n)


-- two versions of factorial

fac  = snd . iter (one, one) (\(a,b) -> (Succ a, mult a b))
fac' = primrec one (mult . Succ)


-- for convenience and testing (try e.g. "fac five")

int = iter 0 (1+)

instance Show Nat where
  show = show . int

(zero : one : two : three : four : five : _) = iterate Succ Zero

Программист Origamist Haskell (всегда начинается с "основной складки птицы" )

-- (curried, list) fold and an application

fold c n []     = n
fold c n (x:xs) = c x (fold c n xs)

prod = fold (*) 1


-- (curried, boolean-based, list) unfold and an application

unfold p f g x = 
  if p x 
     then [] 
     else f x : unfold p f g (g x)

downfrom = unfold (==0) id pred


-- hylomorphisms, as-is or "unfolded" (ouch! sorry ...)

refold  c n p f g   = fold c n . unfold p f g

refold' c n p f g x = 
  if p x 
     then n 
     else c (f x) (refold' c n p f g (g x))


-- several versions of factorial, all (extensionally) equivalent

fac   = prod . downfrom
fac'  = refold  (*) 1 (==0) id pred
fac'' = refold' (*) 1 (==0) id pred

Картезианский наклонный программист Haskell (предпочитает греческую еду, избегает острого индийского материала; вдохновленный Лексом Августейном "Сортировка морфизмов" [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  f  g    = cata g . ana f

hylo' f (n,c) = either (const n) (c . pair (id, hylo' f (c,n))) . f

pair (f,g) (x,y) = (f x, g y)


-- several versions of factorial, all (extensionally) equivalent

fac   = prod . downfrom
fac'  = hylo  uncount (1, mult)
fac'' = hylo' uncount (1, mult)

Ph.D. Программист 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 z s  Zero    = z
nelim z s (Succ n) = s n

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 a b = Nil | Cons a b  deriving Show

instance Functor (L a) where
  fmap f = lelim Nil (\a b -> Cons a (f b))

lelim n c  Nil       = n
lelim n c (Cons a b) = c a b

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 f x = f x x

fac = prod . upto

Программист Post-doc Haskell (из Уустау, Вене и Пардоса "Рекуррентные схемы из Комонад" [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 (g x)

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 m f


-- explicit products and their functorial action

data Prod e c = Pair c e

outl (Pair x y) = x
outr (Pair x y) = y

fork f g x = Pair (f x) (g x)

instance Functor (Prod e) where
  fmap g = fork (g . outl) outr


-- comonads, the categorical "opposite" of monads

class Functor n => Comonad n where
  extr :: n a -> a
  dupl :: n a -> n (n a)

instance Comonad (Prod e) where
  extr = outl
  dupl = fork id outr


-- generalized catamorphisms, zygomorphisms and paramorphisms

gcata :: (Functor f, Comonad n) =>
           (forall a. f (n a) -> n (f a))
             -> (f (n c) -> 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 f n)) = 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

Уполномоченный профессор (обучение Haskell первокурсникам)

fac n = product [1..n]

Ответ 28

PowerShell

function factorial( [int] $n ) 
{ 
    $result = 1; 

    if ( $n -gt 1 ) 
    { 
        $result = $n * ( factorial ( $n - 1 ) ) 
    } 

    $result 
}

Здесь однострочный:

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

Ответ 29

Java 1.6: рекурсивный, memoized (для последующих вызовов)

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;
}

Ответ 30

Bash: рекурсивный

В bash и рекурсивный, но с дополнительным преимуществом, что он имеет дело с каждой итерацией в новом процессе. Максимум, который он может вычислить, равен 20 перед переполнением, но вы все равно можете запустить его для больших чисел, если вам не нужен ответ и вы хотите, чтобы ваша система упала;)

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