Partition function P: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(7 intermediate revisions by 3 users not shown)
Line 3:
 
 
The [https://mathworld.wolfram.com/PartitionFunctionP.html Partition Function P], oftenis the notatedfunction P(n), iswhere n∈ℤ, defined as the number of solutionsdistinct whereways n∈ℤin which n can be expressed as the sum of a set ofnon-increasing positive integers.
 
 
Line 15:
The successive numbers in the above equation have the differences:   1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8 ...
 
This task may be of popular interest because [https://www.youtube.com/channel/UC1_uAIS3r8Vu6JjXWvastJg Mathologer] made the video, [https://www.youtube.com/watch?v=iJ8pnCO0nTY The hardest "What comes next?" (Euler's pentagonal formula)], where he asks the programmers among his viewers to calculate P(666). The video has beenwas viewed more than 100,000 times in the first couple of weeks sinceafter its release.
 
In Wolfram Language, this function has been implemented as PartitionsP.
Line 41:
{{trans|Python: Alternative}}
 
<langsyntaxhighlight lang="11l">F partitions(n)
V p = [BigInt(1)] [+] [BigInt(0)] * n
L(i) 1 .. n
Line 67:
V start = time:perf_counter()
print(partitions(6666))
print(time:perf_counter() - start)</langsyntaxhighlight>
 
{{out}}
Line 78:
=={{header|C}}==
{{libheader|GMP}}
<langsyntaxhighlight lang="c">#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
Line 114:
(double)(clock() - start) / (double)CLOCKS_PER_SEC);
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 124:
=={{header|C#|CSharp}}==
This can also be done using BigIntegers, but will take around five times longer. Since only adding and subtracting are required, some simple routines can be created to handle the tabulations. Also note that detecting odd and even numbers on each loop iteration is avoided by coding four increments per loop.
<langsyntaxhighlight lang="csharp">using System;
 
class Program {
Line 182:
Console.Write("{0} {1} ms", fmt(res), sw.Elapsed.TotalMilliseconds);
}
}</langsyntaxhighlight>
{{out}}
<pre>193655306161707661080005073394486091998480950338405932486880600467114423441282418165863 12.9365 ms</pre>
Line 190:
===GMP version===
{{libheader|GMP}}
<langsyntaxhighlight lang="cpp">#include <chrono>
#include <iostream>
#include <vector>
Line 228:
std::cout << result << '\n';
std::cout << "elapsed time: " << ms.count() << " milliseconds\n";
}</langsyntaxhighlight>
 
{{out}}
Line 238:
===Non GMP version===
{{trans|C#}}
<langsyntaxhighlight lang="cpp">#include <chrono>
#include <iostream>
 
Line 299:
duration<double, milli> ms(end - start);
cout << fmt(result) << " " << ms.count() << " ms";
}</langsyntaxhighlight>
{{out}}
Timing from Tio.run, but execution time can't be directly compared to the GMP version, as GMP isn't accessible at Tio.run.
Line 309:
{{libheader| System.Diagnostics}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program Partition_function_P;
 
Line 378:
writeln('Took ', stopwatch.ElapsedMilliseconds, 'ms');
Readln;
end.</langsyntaxhighlight>
{{out}}
<pre>p[6666] = 193655306161707661080005073394486091998480950338405932486880600467114423441282418165863
Line 385:
=={{header|Elixir}}==
Loosely based on the Erlang version.
<syntaxhighlight lang="elixir">
<lang Elixir>
use Bitwise, skip_operators: true
 
Line 424:
Partition.init
IO.puts Partition.p 6666
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 436:
 
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
<lang Erlang>
-mode(compile).
 
Line 473:
true -> gpentagonals(M + 1, Max, [GP|Ps])
end.
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 486:
=={{header|F_Sharp|F#}}==
An implementation of the formula in the task description. P(123456) is included for comparison with the largest value in the related task.
<langsyntaxhighlight lang="fsharp">
// PartionP: Nigel Galloway. April 12th., 2021
let pP g=let rec fN i g e l=seq{yield(l,e+i);yield(-l,e+i+g);yield! fN(i+1)(g+2)(e+i+g)(-l)}
Line 492:
seq{2..g}|>Seq.iter(fun p->N.[p]<-G|>List.takeWhile(fun(_,n)->n<=p)|>Seq.fold(fun Σ (n,g)->Σ+n*N.[p-g]) 0I); N.[g]
printfn "666->%A\n\n6666->%A\n\n123456->%A" (pP 666) (pP 6666) (pP 123456)
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 505:
=={{header|Factor}}==
{{works with|Factor|0.99 2020-08-14}}
<langsyntaxhighlight lang="factor">USING: kernel lists lists.lazy math sequences sequences.extras ;
 
! Compute the nth pentagonal number.
Line 527:
: partitions ( m -- n )
[ seq swap [ <= ] curry lwhile list>array ]
[ V{ 1 } clone swap [ step ] times last nip ] bi ;</langsyntaxhighlight>
{{out}}
<pre>
Line 541:
===Unsiged 64bit version===
{{trans|Python}}
<langsyntaxhighlight lang="freebasic">Function PartitionsP(n As UInteger) As ULongInt
' if n > 416, the result becomes to large for a unsigned 64bit integer
Dim As ULongInt p(n)
Line 577:
 
Print !"\n\ndone"
Sleep</langsyntaxhighlight>
{{out}}
<pre>PartitionsP: 1 1 2 3 5 7 11 15 22 30 42 56 77</pre>
Line 584:
{{libheader|GMP}}
[https://rosettacode.org/wiki/9_billion_names_of_God_the_integer#FreeBASIC From the 9_billion_names_of_God_the_integer entry]
<langsyntaxhighlight lang="freebasic">' version 26-06-2021
' compile with: fbc -s console
 
Line 646:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
{{out}}
<pre>PartitionsP(6666) = 193655306161707661080005073394486091998480950338405932486880600467114423441282418165863
Line 653:
=={{header|Frink}}==
Frink has a built-in function for counting partitions that uses Euler's pentagonal method. It works for arbitrarily-large integers and caches results.
<syntaxhighlight lang ="frink">println[partitionCount[6666]]</langsyntaxhighlight>
{{out}}
<pre>
Line 662:
{{trans|Julia}}
I also tried using Euler's generating function but it was about 20 times slower than this version.
<langsyntaxhighlight lang="go">package main
 
import (
Line 720:
fmt.Printf("p[%d)] = %d\n", N, p[N])
fmt.Printf("Took %s\n", time.Since(start))
}</langsyntaxhighlight>
 
{{out}}
Line 729:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.math.BigInteger;
 
public class PartitionFunction {
Line 764:
return p[n];
}
}</langsyntaxhighlight>
 
{{out}}
Line 774:
=={{header|JavaScript}}==
 
<langsyntaxhighlight lang="javascript">
function p(n){
var a = new Array(n+1)
Line 793:
console.log("p(6666) = " + p(6666))
console.log("Computation time in ms: ", Date.now() - t)
</syntaxhighlight>
</lang>
 
{{out}}
Line 803:
=={{header|Haskell}}==
 
<langsyntaxhighlight lang="haskell">{-# LANGUAGE DeriveFunctor #-}
 
------------------------------------------------------------
Line 847:
 
main :: IO ()
main = print $ partitionP 6666</langsyntaxhighlight>
 
<pre>*Main> partitionP <$> [1..10]
Line 864:
Solution stolen [https://code.jsoftware.com/wiki/Essays/Partitions#The_Number_of_Partitions verbatim from the J Wiki]. Note the use of memoization (M.) for efficiency:
 
<langsyntaxhighlight lang="j"> pn =: -/@(+/)@:($:"0)@rec ` (x:@(0&=)) @. (0>:]) M.
rec=: - (-: (*"1) _1 1 +/ 3 * ]) @ (>:@i.@>.@%:@((2%3)&*))</langsyntaxhighlight>
 
{{out}}
Line 881:
Translation of: Python:Alternative
 
<langsyntaxhighlight lang="jq">def partitions($n):
def div2: (. - (.%2)) / 2;
reduce range(1; $n + 1) as $i ( {p: ([1] + [range(0;$n)|0])};
Line 902:
| .p[$n] ;
 
[partitions(range(1;15))]</langsyntaxhighlight>
{{out}}
<pre>[1,2,3,5,7,11,15,22,30,42,56,77,101,135]</pre>
 
Using gojq 0.12.11, `partitions(6666)` yields (in about 12 minutes (u+s) on a 3GHz machine):
jq's built-in integer precision is insufficient for computing ``partitions(6666)``, but more as a test
 
of the BigInt.jq library for jq than anything else, here are the results of using it in conjunction
193655306161707661080005073394486091998480950338405932486880600467114423441282418165863
 
jq's built-inThe integer precision of the C implementation of jq is insufficient for computing ``partitions(6666)``, but more as a test
of the BigInt.jq library for jq than anything else, here are the results of using it in conjunction
with a trivially-modified version of the ''partitions'' implementation above. That is, after
modifying the lines that refer to "p" (or ".p"), we see that ''partitions(6666)'' yields:
Line 913 ⟶ 917:
"193655306161707661080005073394486091998480950338405932486880600467114423441282418165863"
 
TheCuriously, userthe u+syss time is 7m3s, which is significantly less than the above-mentioned gojq time, even asthough the BigInt.jq library is written in jq.
 
=== Recursive ===
{{trans|Julia}} with memoization
<langsyntaxhighlight lang="jq">def partDiffDiff($n):
if ($n % 2) == 1 then ($n+1) / 2 else $n+1 end;
 
Line 966 ⟶ 970:
# Stretch goal:
6666 | partitionsP
</syntaxhighlight>
</lang>
Using gojq, the above program takes 41.35 seconds (u+s) on a 3GHz Mac Mini to produce:<pre>
193655306161707661080005073394486091998480950338405932486880600467114423441282418165863</pre>
Line 972 ⟶ 976:
=={{header|Julia}}==
===Recursive===
<langsyntaxhighlight Julialang="julia">using Memoize
 
function partDiffDiff(n::Int)::Int
Line 1,004 ⟶ 1,008:
 
n=6666
@time println("p($n) = ", partitionsP(n))</langsyntaxhighlight>
{{out}}
<pre>p(6666) = 193655306161707661080005073394486091998480950338405932486880600467114423441282418165863
Line 1,011 ⟶ 1,015:
=={{header|Lingo}}==
Lingo natively only supports 32 bit integers, so P(6666) would be way too big.
<langsyntaxhighlight lang="lingo">-- returns number of partitions of n
on partitions(n, res_table)
if n < 2 then return 1
Line 1,038 ⟶ 1,042:
res_table[n] = res
return res
end</langsyntaxhighlight>
{{out}}
<pre>
Line 1,049 ⟶ 1,053:
 
=={{header|Maple}}==
<langsyntaxhighlight lang="maple">p:=proc(n)
option remember;
local k,s:=0,m;
Line 1,078 ⟶ 1,082:
 
combinat[numbpart](1000);
# 24061467864032622473692149727991</langsyntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">PartitionsP /@ Range[15]
PartitionsP[666]
PartitionsP[6666]</langsyntaxhighlight>
{{out}}
<pre>{1,2,3,5,7,11,15,22,30,42,56,77,101,135,176}
Line 1,092 ⟶ 1,096:
{{trans|C++}}
{{libheader|bignum}}
<langsyntaxhighlight Nimlang="nim">import sequtils, strformat, times
import bignum
 
Line 1,118 ⟶ 1,122:
let t0 = cpuTime()
echo partitions(6666)
echo &"Elapsed time: {(cpuTime() - t0) * 1000:.2f} ms"</langsyntaxhighlight>
 
{{out}}
Line 1,125 ⟶ 1,129:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use warnings;
no warnings qw(recursion);
Line 1,153 ⟶ 1,157:
 
print partitionsP($_) . ' ' for 0..25; print "\n";
print partitionsP(6666) . "\n";</langsyntaxhighlight>
{{out}}
<pre>1 1 2 3 5 7 11 15 22 30 42 56 77 101 135 176 231 297 385 490 627 792 1002 1255 1575 1958
Line 1,162 ⟶ 1,166:
{{libheader|Phix/mpfr}}
Not exactly super-fast, but this sort of stuff is not really what Phix does best.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">partDiffDiff</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
Line 1,203 ⟶ 1,207:
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">6666</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"p(%d) = %s (%s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">partitionsP</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)),</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)})</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 1,210 ⟶ 1,214:
 
=={{header|Picat}}==
<langsyntaxhighlight lang="picat">
/* Picat 3.0#5 */
/* Author: Hakan Kjellerstrand */
Line 1,237 ⟶ 1,241:
 
CPU time 0.206 seconds.
</syntaxhighlight>
</lang>
 
=={{header|PicoLisp}}==
Based on the Erlang implementation.
<syntaxhighlight lang="picolisp">
<lang PicoLisp>
(de gpentagonals (Max)
(make
Line 1,260 ⟶ 1,264:
(setq Sgn (& 3 (inc Sgn))))
Sum))))
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 1,269 ⟶ 1,273:
 
=={{header|Prolog}}==
<langsyntaxhighlight lang="prolog">
/* SWI-Prolog 8.3.21 */
/* Author: Jan Burse */
Line 1,285 ⟶ 1,289:
X = 1936553061617076610800050733944860919984809503384
05932486880600467114423441282418165863.
</syntaxhighlight>
</lang>
 
=={{header|Python}}==
Line 1,291 ⟶ 1,295:
This follows the algorithm from the Mathloger video closely
 
<langsyntaxhighlight lang="python">from itertools import islice
 
def posd():
Line 1,341 ⟶ 1,345:
print(" pos_gen:", list(islice(pos_gen(), 10)))
print(" plus_minus:", list(islice(plus_minus(), 15)))
print("\nPartitions:", [part(x) for x in range(15)])</langsyntaxhighlight>
 
{{out}}
Line 1,362 ⟶ 1,366:
====Python: Mathloger video prime generator====
Add the following code after that above
<langsyntaxhighlight lang="python">def par_primes():
"Prime number generator from the partition machine"
p = [1]
Line 1,379 ⟶ 1,383:
yield p
 
print("\nPrimes:", list(islice(par_primes(), 15)))</langsyntaxhighlight>
 
{{Out}}
Line 1,386 ⟶ 1,390:
===Python: Alternative===
{{trans|C++}}
<langsyntaxhighlight lang="python">from typing import List
 
 
Line 1,415 ⟶ 1,419:
 
if __name__ == '__main__':
print("\nPartitions:", [partitions(x) for x in range(15)])</langsyntaxhighlight>
 
{{out}}
Line 1,427 ⟶ 1,431:
In [4]: %timeit partitions(6666)
215 ms ± 1.84 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
</langpre>
 
=={{header|Quackery}}==
 
<code>0 partitions</code> returns <code>1</code> as per [https://oeis.org/A000041 oeis.org/A000041 (Partitions of n)].
 
This is a naive recursive solution, so computing the partitions of 6666 would take a hideously long time.
 
<syntaxhighlight lang="Quackery"> [ 1 swap
dup 0 = iff drop done
[ 2dup = iff [ 2drop 1 ] done
2dup > iff [ 2drop 0 ] done
2dup dip 1+ recurse
unrot over - recurse + ] ] is partitions ( n --> n )
say "Partitions of 0 to 29" cr
30 times [ i^ partitions echo sp ]
</syntaxhighlight>
 
{{out}}
 
<pre>Partitions of 0 to 29
1 1 2 3 5 7 11 15 22 30 42 56 77 101 135 176 231 297 385 490 627 792 1002 1255 1575 1958 2436 3010 3718 4565
</pre>
 
Line 1,433 ⟶ 1,460:
Backwards range was used to get responsive feedback for progress.
 
<langsyntaxhighlight lang="racket">#lang racket
 
(require math/number-theory)
Line 1,460 ⟶ 1,487:
(p 666)
(p 1000)
(p 10000)</langsyntaxhighlight>
 
{{out}}
Line 1,482 ⟶ 1,509:
{{works with|Rakudo|2020.09}}
Not the fastest, but it gets the job done.
<syntaxhighlight lang="raku" perl6line>my @P = 1, { p(++$) } … *;
my @i = lazy [\+] flat 1, ( (1 .. *) Z (1 .. *).map: * × 2 + 1 );
sub p ($n) { sum @P[$n X- @i[^(@i.first: * > $n, :k)]] Z× (flat (1, 1, -1, -1) xx *) }
 
put @P[^26];
put @P[6666];</langsyntaxhighlight>
{{out}}
<pre>1 1 2 3 5 7 11 15 22 30 42 56 77 101 135 176 231 297 385 490 627 792 1002 1255 1575 1958
Line 1,495 ⟶ 1,522:
These three REXX versions are recursive.
=== version 1 ===
<langsyntaxhighlight lang="rexx">/*REXX program calculates and displays a specific value (or a range of) partitionsP(N).*/
numeric digits 1000 /*able to handle some ginormous numbers*/
parse arg lo hi . /*obtain optional arguments from the CL*/
Line 1,525 ⟶ 1,552:
else #= # - (x + y) /*Even? " subtract " " " */
end /*k*/
@.n= #; return # /*define and return partitionsP of N. */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the input of: &nbsp; &nbsp; <tt> 6666 </tt>}}
<pre>
Line 1,539 ⟶ 1,566:
 
The biggest part of the improvement was using the expression &nbsp; &nbsp; '''k+k+k''' &nbsp; &nbsp; instead of &nbsp; &nbsp; '''k*3'''.
<langsyntaxhighlight lang="rexx">/*REXX program calculates and displays a specific value (or a range of) partitionsP(N).*/
numeric digits 1000 /*able to handle some ginormous numbers*/
parse arg lo hi . /*obtain optional arguments from the CL*/
Line 1,570 ⟶ 1,597:
else #= # - (x + y) /*Even? " subtract " " " */
end /*k*/
@.n= #; return # /*define and return partitionsP of N. */</langsyntaxhighlight>
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}}
 
Line 1,577 ⟶ 1,604:
 
The biggest part of the improvement was using memoization of the expressions &nbsp; &nbsp; ('''k+k+k - 1) * k % 2''' &nbsp; &nbsp; for all values of (positive) &nbsp; '''k''' &nbsp; up to &nbsp; '''hi'''.
<langsyntaxhighlight lang="rexx">/*REXX program calculates and displays a specific value (or a range of) partitionsP(N).*/
numeric digits 1000 /*able to handle some ginormous numbers*/
parse arg lo hi . /*obtain optional arguments from the CL*/
Line 1,610 ⟶ 1,637:
else #= # - (x + y) /*Even? " subtract " " " */
end /*k*/
@.n= #; return # /*define and return partitionsP of N. */</langsyntaxhighlight>
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}} <br><br>
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">// [dependencies]
// rug = "1.11"
 
Line 1,659 ⟶ 1,686:
println!("P({}) = {}", n, result);
println!("elapsed time: {} microseconds", time.as_micros());
}</langsyntaxhighlight>
 
{{out}}
Line 1,670 ⟶ 1,697:
 
Built-in:
<langsyntaxhighlight lang="ruby">say partitions(6666) # very fast</langsyntaxhighlight>
 
User-defined:
<langsyntaxhighlight lang="ruby">func partitionsP(n) {
func (n) is cached {
 
Line 1,695 ⟶ 1,722:
say partitionsP(6666)
 
say ("Took %.4f seconds" % Time.micro-t)</langsyntaxhighlight>
 
{{out}}
Line 1,711 ⟶ 1,738:
Using AttaSwift's BigInt library.
 
<langsyntaxhighlight lang="swift">import BigInt
 
func partitions(n: Int) -> BigInt {
Line 1,754 ⟶ 1,781:
}
 
print("partitions(6666) = \(partitions(n: 6666))")</langsyntaxhighlight>
 
{{out}}
Line 1,764 ⟶ 1,791:
{{libheader|Wren-big}}
Although it may not look like it, this is actually a decent time for Wren which is interpreted and the above module is written entirely in Wren itself.
<langsyntaxhighlight ecmascriptlang="wren">import "./big" for BigInt
 
var p = []
Line 1,799 ⟶ 1,826:
for (n in 2..N) partitionsP.call(n)
System.print("p[%(N)] = %(p[N])")
System.print("Took %(System.clock - start) seconds")</langsyntaxhighlight>
 
{{out}}
9,477

edits