2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -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''', &nbsp; <big><big>!n</big></big>, &nbsp; may refer to either &nbsp; ''subfactorials'' &nbsp; or to &nbsp; ''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:
:::::::* &nbsp; <big> <span style="font-family:serif">!''n''`</span> </big>
:::::::* &nbsp; <big> <math>!n'</math> </big>
:::::::* &nbsp; <big> <span style="font-family:serif">''n''¡</span> </big>
Sometimes, &nbsp; ''subfactorials'' &nbsp; (also known as ''derangements'') &nbsp; may use any of the notations:
:::::::* &nbsp; <big><big> <span style="font-family:serif">!''n''`</span> </big></big>
:::::::* &nbsp; <big><big> <span style="font-family:serif">!''n''</span> </big></big>
:::::::* &nbsp; <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>
::: &nbsp; <math> !n = \sum_{k=0}^{n-1} k! </math>
</big></big>
where
:<math>!0 = 0</math>
<big><big>
::: &nbsp; <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, &nbsp; 2,000 &nbsp; through &nbsp; 10,000 &nbsp; (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)]
* &nbsp; The OEIS entry: [http://oeis.org/A003422 A003422 left factorials]
* &nbsp; The MathWorld entry: [http://mathworld.wolfram.com/LeftFactorial.html left factorial]
* &nbsp; The MathWorld entry: [http://mathworld.wolfram.com/FactorialSums.html factorial sums]
* &nbsp; The MathWorld entry: [http://mathworld.wolfram.com/Subfactorial.html subfactorial]
;Related task:
* &nbsp; [http://rosettacode.org/wiki/Permutations/Derangements permutations/derangements (subfactorials)]
<br><br>

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

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

View 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

View file

@ -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.*/

View 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());
}
}