Frage

Ich möchte alle verschiedenen Möglichkeiten sehen, die Sie für eine faktorielle Unterroutine oder ein faktorielles Programm entwickeln können.Die Hoffnung ist, dass jeder hierher kommen und sehen kann, ob er vielleicht eine neue Sprache lernen möchte.

Ideen:

  • Verfahrenstechnisch
  • Funktional
  • Objektorientierte
  • Einzeiler
  • Verschleiert
  • Merkwürdig
  • Schlechter Code
  • Polyglott

Grundsätzlich möchte ich ein Beispiel für verschiedene Arten des Schreibens eines Algorithmus sehen und wie diese in verschiedenen Sprachen aussehen würden.

Bitte beschränken Sie sich auf ein Beispiel pro Eintrag.Ich erlaube Ihnen, mehr als ein Beispiel pro Antwort anzugeben, wenn Sie versuchen, einen bestimmten Stil, eine bestimmte Sprache oder einfach nur eine gut durchdachte Idee hervorzuheben, die sich für einen Beitrag eignet.

Die einzige wirkliche Anforderung besteht darin, die Fakultät eines bestimmten Arguments in allen dargestellten Sprachen zu finden.

Seien Sie kreativ!

Empfohlene Richtlinie:

# Language Name: Optional Style type

   - Optional bullet points

    Code Goes Here

Other informational text goes here

Gelegentlich werde ich jede Antwort bearbeiten, die keine angemessene Formatierung aufweist.

War es hilfreich?

Lösung

Polyglott:5 Sprachen, alle mit Bignums

Also habe ich eine Polyglotte geschrieben, die in den drei Sprachen funktioniert, in denen ich oft schreibe, sowie eine aus meiner anderen Antwort auf diese Frage und eine, die ich heute erst gelernt habe.Es handelt sich um ein eigenständiges Programm, das eine einzelne Zeile mit einer nichtnegativen Ganzzahl liest und eine einzelne Zeile mit ihrer Fakultät ausgibt.Bignums werden in allen Sprachen verwendet, daher hängt die maximal berechenbare Fakultät nur von den Ressourcen Ihres Computers ab.

  • Perl:verwendet das integrierte Bignum-Paket.Lauf mit perl FILENAME.
  • Haskell:verwendet integrierte Bignums.Lauf mit runhugs FILENAME oder das Äquivalent Ihres Lieblings-Compilers.
  • C++:erfordert GMP für Bignum-Unterstützung.Zum Kompilieren mit g++ verwenden Sie g++ -lgmpxx -lgmp -x c++ FILENAME um mit den richtigen Bibliotheken zu verlinken.Nach dem Kompilieren ausführen ./a.out.Oder verwenden Sie das Äquivalent Ihres bevorzugten Compilers.
  • Brainf*ck:Ich habe ein paar Bignum-Support geschrieben dieser Beitrag.Benutzen Mullers klassische Distribution, kompilieren mit bf < FILENAME > EXECUTABLE.Machen Sie die Ausgabe ausführbar und führen Sie sie aus.Oder nutzen Sie Ihre Lieblingsdistribution.
  • Leerzeichen:verwendet integrierte Bignum-Unterstützung.Lauf mit wspace FILENAME.

Bearbeiten: Leerzeichen als fünfte Sprache hinzugefügt.Übrigens, tun Sie es nicht Wickeln Sie den Code mit ein <code> Stichworte;es durchbricht das Leerzeichen.Außerdem sieht der Code in fester Breite viel besser aus.

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

Andere Tipps

lolcode:

Entschuldigung, ich konnte nicht widerstehen 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    

Dies ist einer der schnelleren Algorithmen 170!.Es scheitert unerklärlicherweise über 170 hinaus!, und es ist relativ langsam für kleine Fakultäten, aber für Fakultäten dazwischen 80 Und 170 Im Vergleich zu vielen Algorithmen ist es unglaublich schnell.

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

Es gibt auch eine Online-Schnittstelle, Probieren Sie es jetzt aus!

Lassen Sie mich wissen, wenn Sie einen Fehler oder eine schnellere Implementierung für große Fakultäten finden.


BEARBEITEN:

Dieser Algorithmus ist etwas langsamer, liefert aber Ergebnisse über 170:

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

Es vereinfacht sie auch in verschiedene andere Darstellungen.

C++:Vorlagen-Metaprogrammierung

Verwendet den klassischen Enum-Hack.

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

template<>
struct factorial<0> {
    enum { result = 1 };
};

Verwendung.

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

Die Fakultät wird vollständig zur Kompilierungszeit basierend auf dem Vorlagenparameter n berechnet.Daher ist „factorial<4>::result“ eine Konstante, sobald der Compiler seine Arbeit erledigt hat.

Leerzeichen

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

Es war schwierig, es hier richtig anzuzeigen, aber jetzt habe ich versucht, es aus der Vorschau zu kopieren, und es funktioniert.Sie müssen die Nummer eingeben und die Eingabetaste drücken.

Ich finde die folgenden Implementierungen einfach urkomisch:

Die Entwicklung eines Haskell-Programmierers

Entwicklung eines Python-Programmierers

Genießen!

C#-Suche:

Eigentlich gibt es nichts zu berechnen, schauen Sie einfach nach.Um es zu erweitern, fügen Sie der Tabelle weitere 8 Zahlen hinzu, und 64-Bit-Ganzzahlen sind an ihrer Grenze.Darüber hinaus ist eine BigNum-Klasse erforderlich.

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

Faul K

Ihre rein funktionalen Programmieralbträume werden wahr!

Die einzige Esoterische Turing-vollständige Programmiersprache das hat:

  • Eine rein funktionale Grundlage, ein Kern und Bibliotheken – tatsächlich ist hier die vollständige API: SKI
  • NEIN Lambdas sogar!
  • NEIN Zahlen oder Listen benötigt oder erlaubt
  • Keine explizite Rekursion, aber dennoch ermöglicht Rekursion
  • Eine einfache unendlicher Lazy Stream-basierter I/O-Mechanismus

Hier ist der Factorial-Code in seiner ganzen Pracht in Klammern:

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)

Merkmale:

  • Keine Subtraktion oder Bedingungen
  • Druckt alle Fakultäten (wenn Sie lange genug warten)
  • Verwendet eine zweite Schicht kirchlicher Ziffern, um die N-te Fakultät in N umzuwandeln!Sternchen gefolgt von einem Zeilenumbruch
  • Verwendet die Y-Kombinator für Rekursion

Falls Sie daran interessiert sind, es zu verstehen, finden Sie hier den Scheme-Quellcode, der durch den Lazier-Compiler ausgeführt werden kann:

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

(für geeignete Definitionen von Y, cons, 1, 10, 42, 1+ und *).

BEARBEITEN:

Lazy-K-Fakultät in Dezimalzahl

(10 KB Kauderwelsch sonst würde ich es einfügen).Beispielsweise an der Unix-Eingabeaufforderung:

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

Eher langsam für Zahlen über beispielsweise 5.

Der Code ist etwas aufgebläht, weil wir ihn einbinden müssen Bibliothekscode für alle unsere eigenen Grundelemente (Code geschrieben Dunstig, ein in Haskell geschriebener Lambda-Kalkül-Interpreter und LC-to-Lazy-K-Compiler).

XSLT 1.0

Die Eingabedatei, faktorielle.xml:

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

Die XSLT-Datei, faktorielle.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>

Speichern Sie beide Dateien im selben Verzeichnis und öffnen Sie sie faktorielle.xml im IE.

Python:Funktional, einzeilig

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

NOTIZ:

  • Es unterstützt große ganze Zahlen.Beispiel:

print factorial(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915\
608941463976156518286253697920827223758251185210916864000000000000000000000000

  • Es funktioniert nicht n < 0.

APL (seltsam/einzeilig):

×/⍳X
  1. ⍳X erweitert X in ein Array der ganzen Zahlen 1..X
  2. ×/ multipliziert jedes Element im Array

Oder mit dem integrierten Operator:

!X

Quelle: http://www.webber-labs.com/mpl/lectures/ppt-slides/01.ppt

Perl6

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

Ich weiß kaum etwas über Perl6.Aber ich vermute das [*] Der Operator ist derselbe wie der von Haskell product.

Dieser Code läuft weiter Möpse, und vielleicht Papagei (Ich habe es nicht überprüft.)

Bearbeiten

Dieser Code funktioniert auch.

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

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

x86-64-Montage:Verfahrenstechnisch

Sie können dies von C aus aufrufen (nur mit GCC unter Linux amd64 getestet).Die Baugruppe wurde mit Nasm zusammengebaut.

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

Rekursiv in Inform 7

(es erinnert an COBOL, weil es zum Schreiben von Textabenteuern dient;proportionale Schriftart ist gewollt):

Um zu entscheiden, welche Zahl die Fakultät von (n – eine Zahl) ist:
Wenn n Null ist, entscheiden Sie sich für Eins.
Andernfalls entscheiden Sie sich für die Fakultät von (n minus eins) mal n.

Wenn Sie diese Funktion („Phrase“) tatsächlich aus einem Spiel aufrufen möchten, müssen Sie eine Aktion und eine Grammatikregel definieren:

„Das Faktorialspiel“ [dies muss die erste Zeile der Quelle sein]

Es gibt ein Zimmer.[Es muss mindestens einen geben!]

Faktorisieren ist eine Aktion, die auf eine Zahl angewendet wird.

Verstehen Sie „Fakultät [eine Zahl]“ als Fakultät.

Faktorisierung durchführen:
Sei n die Fakultät der verstandenen Zahl;
Sagen Sie „Es ist [n]“.

C#:LINQ

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

Erlang:Schwanz rekursiv

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

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

Haskell:

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

Brainf*ck

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

Geschrieben von Michael Reitzenstein.

BASIC:alte Schule

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

Charge (NT):

@echo off

set n=%1
set result=1

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

echo %result%

Verwendung:C:>factorial.bat 15

F#:Funktional

Ganz einfach:

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

Lust auf mehr:

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

Rekursiver Prolog

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

Schwanzrekursiver Prolog

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

Ruby rekursiv

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

Verwendung:

factorial[5]
 => 120

Planen

Hier ist eine einfache rekursive Definition:

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

In Scheme verwenden tail-rekursive Funktionen konstanten Stapelspeicherplatz.Hier ist eine Version von „factorial“, die schwanzrekursiv ist:

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

Kuriose Beispiele?Wie wäre es mit der Gammafunktion?Seit, Gamma n = (n-1)!.

OCaml:Verwendung von 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)))

Erstsemester-Haskell-Programmierer

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

Sophomore Haskell -Programmierer am MIT (Studienschema als Neuling)

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

Junior Haskell -Programmierer (Anfang Peano Player)

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

Ein weiterer Junior-Haskell-Programmierer (Lesen Sie, dass N+K-Muster „ein ekelhafter Teil von Haskell“ [1] sind und sich den „Ban N+K-Mustern“ angeschlossen haben [2])

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

Senior Haskell -Programmierer (gestimmt für Nixon Buchanan Bush - „Lehnt sich rechts“)

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

Ein weiterer Senior -Haskell -Programmierer (gestimmt für McGovern Biafra Nader - „Leans links“)

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

Ein weiterer Senior -Haskell -Programmierer (lehnte sich so weit rechts, er kam wieder nach links zurück!)

-- using foldr to simulate foldl

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

Memoisierung von Haskell -Programmierer (täglich Ginkgo Biloba)

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

fac n = facs !! n

Sinnloser (ahem) „punktfreier“ Haskell-Programmierer (untersucht in Oxford)

fac = foldr (*) 1 . enumFromTo 1

Iterativer Haskell -Programmierer (ehemaliger Pascal -Programmierer)

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

Iterativer Ein-Liner-Haskell-Programmierer (ehemaliger APL und C-Programmierer)

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

Haskell -Programmierer akkumulieren (auf einen schnellen Höhepunkt aufbauen)

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

fac = facAcc 1

Fortsetzung von Haskell-Programmierer (Erhöhte Kaninchen in frühen Jahren, dann nach New Jersey gezogen)

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

fac = facCps id

Boy Scout Haskell -Programmierer (mag es, Knoten zu binden;Immer „ehrfürchtig“, gehört er zur Kirche des am wenigsten festen Punktes [8])

y f = f (y f)

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

Kombinatorischer Haskell -Programmierer (meidet Variablen, wenn nicht die Verschleierung;Das ganze Schmoren ist nur eine Phase, auch wenn es selten hinderlich ist)

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

Listenkodierender Haskell-Programmierer (bevorzugt es, in Unary zu zählen)

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

Interpretiver Haskell -Programmierer (nie eine Sprache getroffen, die er nicht mochte)

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

Statischer Haskell -Programmierer (er macht es mit Klasse, er hat diesen Fundep Jones!Nach Thomas Hallgrens „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 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

Der Absolvent Haskell Programmierer (Graduate Education neigt dazu, einen von kleinen Bedenken hinsichtlich der Effizienz von Hardware-basierten Ganzzahlen zu befreien)

-- 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 -Programmierer (beginnt immer mit der „einfachen Vogelfaltung“)

-- (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

Cartesianal in Haskell-Programmierer (bevorzugt das griechische Essen, vermeidet das würzige indische Sachen.inspiriert von Lex Augusteijns „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  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 -Programmierer (aß so viele Bananas, dass seine Augen ausgeschaltet sind, jetzt braucht er neue Objektive!)

-- 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-Programmierer (aus Uustalu, Vene und Pardos „Recursion Schemata From Comonaden“ [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

Professor (unterrichtet Haskell an Neulinge)

fac n = product [1..n]

D-Vorlagen:Funktional

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

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

oder

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

So verwendet:

factorial!(5)

Java 1.6:rekursiv, auswendig gelernt (für nachfolgende Aufrufe)

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

Power Shell

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

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

    $result 
}

Hier ist ein Einzeiler:

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

Bash:Rekursiv

In Bash und rekursiv, aber mit dem zusätzlichen Vorteil, dass jede Iteration in einem neuen Prozess behandelt wird.Es kann maximal !20 berechnen, bevor es zum Überlauf kommt. Sie können es aber trotzdem für große Zahlen ausführen, wenn Ihnen die Antwort egal ist und Sie möchten, dass Ihr System umfällt ;)

#!/bin/bash
echo $(($1 * `( [[ $1 -gt 1 ]] && ./$0 $(($1 - 1)) ) || echo 1`));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top