2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,24 +1,41 @@
|
|||
''Left factorials'', <math>!n</math>, may refer to either ''subfactorials'' or to ''factorial sums'';
|
||||
the same notation can be confusingly seen used for the two different definitions.
|
||||
'''Left factorials''', <big><big>!n</big></big>, may refer to either ''subfactorials'' or to ''factorial sums'';
|
||||
<br>the same notation can be confusingly seen used for the two different definitions.
|
||||
|
||||
Sometimes, ''subfactorials'' (also known as ''derangements'') use any of the notations:
|
||||
:::::::* <big> <span style="font-family:serif">!''n''`</span> </big>
|
||||
:::::::* <big> <math>!n'</math> </big>
|
||||
:::::::* <big> <span style="font-family:serif">''n''¡</span> </big>
|
||||
Sometimes, ''subfactorials'' (also known as ''derangements'') may use any of the notations:
|
||||
:::::::* <big><big> <span style="font-family:serif">!''n''`</span> </big></big>
|
||||
:::::::* <big><big> <span style="font-family:serif">!''n''</span> </big></big>
|
||||
:::::::* <big><big> <span style="font-family:serif">''n''¡</span> </big></big>
|
||||
|
||||
<br>This Rosetta Code task will be using this formula for ''left factorial'':
|
||||
:<math> !n = \sum_{k=0}^{n-1} k! </math>
|
||||
(It may not be visually obvious, but the last example uses an upside-down exclamation mark.)
|
||||
|
||||
|
||||
<br>This Rosetta Code task will be using this formula for '''left factorial''':
|
||||
<big><big>
|
||||
::: <math> !n = \sum_{k=0}^{n-1} k! </math>
|
||||
</big></big>
|
||||
where
|
||||
:<math>!0 = 0</math>
|
||||
<big><big>
|
||||
::: <math>!0 = 0</math>
|
||||
</big></big>
|
||||
|
||||
|
||||
;Task
|
||||
Display the left factorials for:
|
||||
* zero through ten (inclusive)
|
||||
* 20 through 110 (inclusive) by tens
|
||||
|
||||
<br>
|
||||
Display the length (in decimal digits) of the left factorials for:
|
||||
* 1,000, 2,000 through 10,000 (inclusive), by thousands.
|
||||
|
||||
|
||||
;Also see
|
||||
* The OEIS entry: [http://oeis.org/A003422 A003422 left factorials]
|
||||
* The MathWorld entry: [http://mathworld.wolfram.com/LeftFactorial.html left factorial]
|
||||
* The MathWorld entry: [http://mathworld.wolfram.com/FactorialSums.html factorial sums]
|
||||
* The MathWorld entry: [http://mathworld.wolfram.com/Subfactorial.html subfactorial]
|
||||
* The Rosetta Code entry: [http://rosettacode.org/wiki/Permutations/Derangements permutations/derangements (subfactorials)]
|
||||
* The OEIS entry: [http://oeis.org/A003422 A003422 left factorials]
|
||||
* The MathWorld entry: [http://mathworld.wolfram.com/LeftFactorial.html left factorial]
|
||||
* The MathWorld entry: [http://mathworld.wolfram.com/FactorialSums.html factorial sums]
|
||||
* The MathWorld entry: [http://mathworld.wolfram.com/Subfactorial.html subfactorial]
|
||||
|
||||
|
||||
;Related task:
|
||||
* [http://rosettacode.org/wiki/Permutations/Derangements permutations/derangements (subfactorials)]
|
||||
<br><br>
|
||||
|
|
|
|||
127
Task/Left-factorials/C++/left-factorials.cpp
Normal file
127
Task/Left-factorials/C++/left-factorials.cpp
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#if 1 // optimized for 64-bit architecture
|
||||
typedef unsigned long usingle;
|
||||
typedef unsigned long long udouble;
|
||||
const int word_len = 32;
|
||||
#else // optimized for 32-bit architecture
|
||||
typedef unsigned short usingle;
|
||||
typedef unsigned long udouble;
|
||||
const int word_len = 16;
|
||||
#endif
|
||||
|
||||
class bignum {
|
||||
private:
|
||||
// rep_.size() == 0 if and only if the value is zero.
|
||||
// Otherwise, the word rep_[0] keeps the least significant bits.
|
||||
vector<usingle> rep_;
|
||||
public:
|
||||
explicit bignum(usingle n = 0) { if (n > 0) rep_.push_back(n); }
|
||||
bool equals(usingle n) const {
|
||||
if (n == 0) return rep_.empty();
|
||||
if (rep_.size() > 1) return false;
|
||||
return rep_[0] == n;
|
||||
}
|
||||
bignum add(usingle addend) const {
|
||||
bignum result(0);
|
||||
udouble sum = addend;
|
||||
for (size_t i = 0; i < rep_.size(); ++i) {
|
||||
sum += rep_[i];
|
||||
result.rep_.push_back(sum & (((udouble)1 << word_len) - 1));
|
||||
sum >>= word_len;
|
||||
}
|
||||
if (sum > 0) result.rep_.push_back((usingle)sum);
|
||||
return result;
|
||||
}
|
||||
bignum add(const bignum& addend) const {
|
||||
bignum result(0);
|
||||
udouble sum = 0;
|
||||
size_t sz1 = rep_.size();
|
||||
size_t sz2 = addend.rep_.size();
|
||||
for (size_t i = 0; i < max(sz1, sz2); ++i) {
|
||||
if (i < sz1) sum += rep_[i];
|
||||
if (i < sz2) sum += addend.rep_[i];
|
||||
result.rep_.push_back(sum & (((udouble)1 << word_len) - 1));
|
||||
sum >>= word_len;
|
||||
}
|
||||
if (sum > 0) result.rep_.push_back((usingle)sum);
|
||||
return result;
|
||||
}
|
||||
bignum multiply(usingle factor) const {
|
||||
bignum result(0);
|
||||
udouble product = 0;
|
||||
for (size_t i = 0; i < rep_.size(); ++i) {
|
||||
product += (udouble)rep_[i] * factor;
|
||||
result.rep_.push_back(product & (((udouble)1 << word_len) - 1));
|
||||
product >>= word_len;
|
||||
}
|
||||
if (product > 0)
|
||||
result.rep_.push_back((usingle)product);
|
||||
return result;
|
||||
}
|
||||
void divide(usingle divisor, bignum& quotient, usingle& remainder) const {
|
||||
quotient.rep_.resize(0);
|
||||
udouble dividend = 0;
|
||||
remainder = 0;
|
||||
for (size_t i = rep_.size(); i > 0; --i) {
|
||||
dividend = ((udouble)remainder << word_len) + rep_[i - 1];
|
||||
usingle quo = (usingle)(dividend / divisor);
|
||||
remainder = (usingle)(dividend % divisor);
|
||||
if (quo > 0 || i < rep_.size())
|
||||
quotient.rep_.push_back(quo);
|
||||
}
|
||||
reverse(quotient.rep_.begin(), quotient.rep_.end());
|
||||
}
|
||||
};
|
||||
|
||||
ostream& operator<<(ostream& os, const bignum& x);
|
||||
|
||||
ostream& operator<<(ostream& os, const bignum& x) {
|
||||
string rep;
|
||||
bignum dividend = x;
|
||||
bignum quotient;
|
||||
usingle remainder;
|
||||
while (true) {
|
||||
dividend.divide(10, quotient, remainder);
|
||||
rep += (char)('0' + remainder);
|
||||
if (quotient.equals(0)) break;
|
||||
dividend = quotient;
|
||||
}
|
||||
reverse(rep.begin(), rep.end());
|
||||
os << rep;
|
||||
return os;
|
||||
}
|
||||
|
||||
bignum lfact(usingle n);
|
||||
|
||||
bignum lfact(usingle n) {
|
||||
bignum result(0);
|
||||
bignum f(1);
|
||||
for (usingle k = 1; k <= n; ++k) {
|
||||
result = result.add(f);
|
||||
f = f.multiply(k);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main() {
|
||||
for (usingle i = 0; i <= 10; ++i) {
|
||||
cout << "!" << i << " = " << lfact(i) << endl;
|
||||
}
|
||||
|
||||
for (usingle i = 20; i <= 110; i += 10) {
|
||||
cout << "!" << i << " = " << lfact(i) << endl;
|
||||
}
|
||||
|
||||
for (usingle i = 1000; i <= 10000; i += 1000) {
|
||||
stringstream ss;
|
||||
ss << lfact(i);
|
||||
cout << "!" << i << " has " << ss.str().size()
|
||||
<< " digits." << endl;
|
||||
}
|
||||
}
|
||||
19
Task/Left-factorials/Clojure/left-factorials.clj
Normal file
19
Task/Left-factorials/Clojure/left-factorials.clj
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
(ns left-factorial
|
||||
(:gen-class))
|
||||
|
||||
(defn left-factorial [n]
|
||||
" Compute by updating the state [fact summ] for each k, where k equals 1 to n
|
||||
Update is next state is [k*fact (summ+k)"
|
||||
(second
|
||||
(reduce (fn [[fact summ] k]
|
||||
[(*' fact k) (+ summ fact)])
|
||||
[1 0] (range 1 (inc n)))))
|
||||
|
||||
(doseq [n (range 11)]
|
||||
(println (format "!%-3d = %5d" n (left-factorial n))))
|
||||
|
||||
(doseq [n (range 20 111 10)]
|
||||
(println (format "!%-3d = %5d" n (biginteger (left-factorial n)))))
|
||||
|
||||
(doseq [n (range 1000 10001 1000)]
|
||||
(println (format "!%-5d has %5d digits" n (count (str (biginteger (left-factorial n)))))))
|
||||
28
Task/Left-factorials/Lua/left-factorials.lua
Normal file
28
Task/Left-factorials/Lua/left-factorials.lua
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
-- Lua bindings for GNU bc
|
||||
require("bc")
|
||||
|
||||
-- Return table of factorials from 0 to n
|
||||
function facsUpTo (n)
|
||||
local f, fList = bc.number(1), {}
|
||||
fList[0] = 1
|
||||
for i = 1, n do
|
||||
f = bc.mul(f, i)
|
||||
fList[i] = f
|
||||
end
|
||||
return fList
|
||||
end
|
||||
|
||||
-- Return left factorial of n
|
||||
function leftFac (n)
|
||||
local sum = bc.number(0)
|
||||
for k = 0, n - 1 do sum = bc.add(sum, facList[k]) end
|
||||
return bc.tostring(sum)
|
||||
end
|
||||
|
||||
-- Main procedure
|
||||
facList = facsUpTo(10000)
|
||||
for i = 0, 10 do print("!" .. i .. " = " .. leftFac(i)) end
|
||||
for i = 20, 110, 10 do print("!" .. i .. " = " .. leftFac(i)) end
|
||||
for i = 1000, 10000, 1000 do
|
||||
print("!" .. i .. " contains " .. #leftFac(i) .. " digits")
|
||||
end
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
/*REXX pgm computes/shows the left factorial (or width) of N (or range).*/
|
||||
parse arg bot top inc . /*obtain optional args from C.L. */
|
||||
if bot=='' then bot=1 /*BOT defined? Then use default.*/
|
||||
td= bot<0 /*if BOT < 0, only show # digs.*/
|
||||
bot=abs(bot) /*use the |bot| for the DO loop.*/
|
||||
if top=='' then top=bot /* " " top " " " " */
|
||||
if inc='' then inc=1 /* " " inc " " " " */
|
||||
@='left ! of ' /*a literal used in the display. */
|
||||
w=length(H) /*width of largest number request*/
|
||||
do j=bot to top by inc /*traipse through #'s requested.*/
|
||||
if td then say @ right(j,w) " ───► " length(L!(j)) ' digits'
|
||||
else say @ right(j,w) " ───► " L!(j)
|
||||
end /*j*/ /* [↑] show either L! or #digits*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────L! subroutine───────────────────────*/
|
||||
L!: procedure; parse arg x .; if x<3 then return x; s=4 /*shortcuts.*/
|
||||
!=2; do f=3 to x-1 /*compute L! for all numbers───►X*/
|
||||
!=!*f /*compute intermediate factorial.*/
|
||||
if pos(.,!)\==0 then numeric digits digits()*1.5%1 /*bump digs.*/
|
||||
s=s+! /*add the factorial ───► L! sum.*/
|
||||
end /*f*/ /* [↑] handles gi-hugeic numbers*/
|
||||
return s /*return the sum (L!) to invoker.*/
|
||||
/*REXX program computes/display the left factorial (or its width) of N (or range). */
|
||||
parse arg bot top inc . /*obtain optional argumenst from the CL*/
|
||||
if bot=='' | bot=="," then bot= 1 /*Not specified: Then use the default.*/
|
||||
if top=='' | top=="," then top=bot /* " " " " " " */
|
||||
if inc='' | inc=="," then inc= 1 /* " " " " " " */
|
||||
tellDigs= (bot<0) /*if BOT < 0, only show # of digits. */
|
||||
bot=abs(bot) /*use the │bot│ for the DO loop. */
|
||||
@= 'left ! of ' /*a handy literal used in the display. */
|
||||
w=length(H) /*width of the largest number request. */
|
||||
do j=bot to top by inc /*traipse through the numbers requested*/
|
||||
if tellDigs then say @ right(j,w) " ───► " length(L!(j)) ' digits'
|
||||
else say @ right(j,w) " ───► " L!(j)
|
||||
end /*j*/ /* [↑] show either L! or # of digits*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
L!: procedure; parse arg x .; if x<3 then return x; s=4 /*some shortcuts. */
|
||||
!=2; do f=3 to x-1 /*compute L! for all numbers ─── ► X.*/
|
||||
!=!*f /*compute intermediate factorial. */
|
||||
if pos(.,!)\==0 then numeric digits digits()*1.5%1 /*bump decimal digits.*/
|
||||
s=s+! /*add the factorial ───► L! sum. */
|
||||
end /*f*/ /* [↑] handles gihugeic numbers. */
|
||||
return s /*return the sum (L!) to the invoker.*/
|
||||
|
|
|
|||
123
Task/Left-factorials/Rust/left-factorials.rust
Normal file
123
Task/Left-factorials/Rust/left-factorials.rust
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
#[cfg(target_pointer_width = "64")]
|
||||
type USingle = u32;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
type UDouble = u64;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const WORD_LEN: i32 = 32;
|
||||
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
type USingle = u16;
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
type UDouble = u32;
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
const WORD_LEN: i32 = 16;
|
||||
|
||||
use std::cmp;
|
||||
|
||||
#[derive(Debug,Clone)]
|
||||
struct BigNum {
|
||||
// rep_.size() == 0 if and only if the value is zero.
|
||||
// Otherwise, the word rep_[0] keeps the least significant bits.
|
||||
rep_: Vec<USingle>,
|
||||
}
|
||||
|
||||
impl BigNum {
|
||||
pub fn new(n: USingle) -> BigNum {
|
||||
let mut result = BigNum { rep_: vec![] };
|
||||
if n > 0 { result.rep_.push(n); }
|
||||
result
|
||||
}
|
||||
pub fn equals(&self, n: USingle) -> bool {
|
||||
if n == 0 { return self.rep_.is_empty() }
|
||||
if self.rep_.len() > 1 { return false }
|
||||
self.rep_[0] == n
|
||||
}
|
||||
pub fn add_big(&self, addend: &BigNum) -> BigNum {
|
||||
let mut result = BigNum::new(0);
|
||||
let mut sum = 0 as UDouble;
|
||||
let sz1 = self.rep_.len();
|
||||
let sz2 = addend.rep_.len();
|
||||
for i in 0..cmp::max(sz1, sz2) {
|
||||
if i < sz1 { sum += self.rep_[i] as UDouble }
|
||||
if i < sz2 { sum += addend.rep_[i] as UDouble }
|
||||
result.rep_.push(sum as USingle);
|
||||
sum >>= WORD_LEN;
|
||||
}
|
||||
if sum > 0 { result.rep_.push(sum as USingle) }
|
||||
result
|
||||
}
|
||||
pub fn multiply(&self, factor: USingle) -> BigNum {
|
||||
let mut result = BigNum::new(0);
|
||||
let mut product = 0 as UDouble;
|
||||
for i in 0..self.rep_.len() {
|
||||
product += self.rep_[i] as UDouble * factor as UDouble;
|
||||
result.rep_.push(product as USingle);
|
||||
product >>= WORD_LEN;
|
||||
}
|
||||
if product > 0 {
|
||||
result.rep_.push(product as USingle);
|
||||
}
|
||||
result
|
||||
}
|
||||
pub fn divide(&self, divisor: USingle, quotient: &mut BigNum,
|
||||
remainder: &mut USingle) {
|
||||
quotient.rep_.truncate(0);
|
||||
let mut dividend: UDouble;
|
||||
*remainder = 0;
|
||||
for i in 0..self.rep_.len() {
|
||||
let j = self.rep_.len() - 1 - i;
|
||||
dividend = ((*remainder as UDouble) << WORD_LEN)
|
||||
+ self.rep_[j] as UDouble;
|
||||
let quo = (dividend / divisor as UDouble) as USingle;
|
||||
*remainder = (dividend % divisor as UDouble) as USingle;
|
||||
if quo > 0 || j < self.rep_.len() - 1 {
|
||||
quotient.rep_.push(quo);
|
||||
}
|
||||
}
|
||||
quotient.rep_.reverse();
|
||||
}
|
||||
fn to_string(&self) -> String {
|
||||
let mut rep = String::new();
|
||||
let mut dividend = (*self).clone();
|
||||
let mut remainder = 0 as USingle;
|
||||
let mut quotient = BigNum::new(0);
|
||||
loop {
|
||||
dividend.divide(10, &mut quotient, &mut remainder);
|
||||
rep.push(('0' as USingle + remainder) as u8 as char);
|
||||
if quotient.equals(0) { break; }
|
||||
dividend = quotient.clone();
|
||||
}
|
||||
rep.chars().rev().collect::<String>()
|
||||
}
|
||||
}
|
||||
|
||||
use std::fmt;
|
||||
impl fmt::Display for BigNum {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn lfact(n: USingle) -> BigNum {
|
||||
let mut result = BigNum::new(0);
|
||||
let mut f = BigNum::new(1);
|
||||
for k in 1 as USingle..n + 1 {
|
||||
result = result.add_big(&f);
|
||||
f = f.multiply(k);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for i in 0..11 {
|
||||
println!("!{} = {}", i, lfact(i));
|
||||
}
|
||||
for i in 2..12 {
|
||||
let j = i * 10;
|
||||
println!("!{} = {}", j, lfact(j));
|
||||
}
|
||||
for i in 1..11 {
|
||||
let j = i * 1000;
|
||||
println!("!{} has {} digits.", j, lfact(j).to_string().len());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue