Skip to content

Commit d7a6f11

Browse files
author
hernanmd
committed
Add reverse binomial with tests. See https://math.stackexchange.com/a/103385/205 for details.
1 parent 473b0b0 commit d7a6f11

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

src/Math-Numerical/Integer.extension.st

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,54 @@
11
Extension { #name : #Integer }
22

3+
{ #category : #'*Math-Numerical' }
4+
Integer >> findNK [
5+
" Reverse binomial coefficient. Answer a <Collection> with all n and k such that n take: k = self. Elements in the answered Collection should be read as paired. Each pair represents (n,k) in the binomial coefficient formula.
6+
See https://math.stackexchange.com/a/103385/205 for details. "
7+
8+
| k |
9+
[ self isInteger and: [ self > 1 ] ] assert.
10+
k := 0.
11+
^ Array streamContents: [ : stream |
12+
[ true ] whileTrue: [
13+
| nmin nmax choose |
14+
k := k + 1.
15+
((2 * k + 1) * self) <= (4 ** k)
16+
ifTrue: [ ^ stream contents ].
17+
nmin := k firstOver: (k factorial * self).
18+
nmax := nmin + k + 1.
19+
nmin := nmin max: (2 * k).
20+
choose := nmin asInteger take: k.
21+
nmin to: nmax do: [ : n |
22+
choose = self
23+
ifTrue: [
24+
stream nextPutAll: { n asInteger . k asInteger }.
25+
k < (n - k)
26+
ifTrue: [ stream nextPutAll: { n asInteger . (n - k) asInteger } ] ].
27+
choose := choose * (n + 1).
28+
choose := (choose / (n + 1 - k)) ceiling ] ] ]
29+
30+
]
31+
32+
{ #category : #'*Math-Numerical' }
33+
Integer >> firstOver: c [
34+
" Binary search to find smallest value of n for which n ** self >= c "
35+
| n lo hi mid |
36+
37+
n := 1.
38+
[ (n ** self) < c ] whileTrue: [ n := n * 2 ].
39+
lo := 1.
40+
hi := n.
41+
[ (hi - lo) > 1 ] whileTrue: [
42+
mid := lo + ((hi - lo) / 2) ceiling.
43+
(mid ** self) < c
44+
ifTrue: [ lo := mid ]
45+
ifFalse: [ hi := mid ] ].
46+
[ (hi ** self) >= c ] assert.
47+
[ ((hi - 1) ** self) < c ] assert.
48+
^ hi
49+
50+
]
51+
352
{ #category : #'*Math-Numerical' }
453
Integer >> gamma [
554
self > 0
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
Extension { #name : #IntegerTest }
2+
3+
{ #category : #'*Math-Tests-Numerical' }
4+
IntegerTest >> testFindNK [
5+
6+
self assert: 6 findNK equals: #(6 1 6 5 4 2).
7+
self assert: 10 findNK equals: #(10 1 10 9 5 2 5 3).
8+
self assert: 20 findNK equals: #(20 1 20 19 6 3).
9+
self assert: 21 findNK equals: #(21 1 21 20 7 2 7 5).
10+
self assert: 55 findNK equals: #(55 1 55 54 11 2 11 9).
11+
self assert: 120 findNK equals: #(120 1 120 119 16 2 16 14 10 3 10 7).
12+
self assert: 3003 findNK equals: #(3003 1 3003 3002 78 2 78 76 15 5 15 10 14 6 14 8).
13+
self assert: 8966473191018617158916954970192684 findNK equals: #(8966473191018617158916954970192684 1 8966473191018617158916954970192684 8966473191018617158916954970192683 123 45 123 78).
14+
self assert: 116682544286207712305570174244760883486876241791210077037133735047856714594324355733933738740204795317223528882568337264611289789138133946725471443924278812277695432803500115699090641248357468388106131543801393801287657125117557432072695477147403395443757359171876874010770591355653882772562301453205472707597435095925666815012707478996454360460481159339802667334477440 findNK equals: #(116682544286207712305570174244760883486876241791210077037133735047856714594324355733933738740204795317223528882568337264611289789138133946725471443924278812277695432803500115699090641248357468388106131543801393801287657125117557432072695477147403395443757359171876874010770591355653882772562301453205472707597435095925666815012707478996454360460481159339802667334477440 1 116682544286207712305570174244760883486876241791210077037133735047856714594324355733933738740204795317223528882568337264611289789138133946725471443924278812277695432803500115699090641248357468388106131543801393801287657125117557432072695477147403395443757359171876874010770591355653882772562301453205472707597435095925666815012707478996454360460481159339802667334477440 116682544286207712305570174244760883486876241791210077037133735047856714594324355733933738740204795317223528882568337264611289789138133946725471443924278812277695432803500115699090641248357468388106131543801393801287657125117557432072695477147403395443757359171876874010770591355653882772562301453205472707597435095925666815012707478996454360460481159339802667334477439 1234 567 1234 667).
15+
self should: [ 1 findNK ] raise: Error.
16+
self should: [ 0 findNK ] raise: Error.
17+
]
18+
19+
{ #category : #'*Math-Tests-Numerical' }
20+
IntegerTest >> testFirstOver [
21+
22+
self assert: (2 firstOver: 3) equals: 2.
23+
self assert: (2 firstOver: 4) equals: 2.
24+
self assert: (2 firstOver: 5) equals: 3.
25+
self assert: (2 firstOver: 6) equals: 3.
26+
27+
self assert: (3 firstOver: 3) equals: 2.
28+
self assert: (3 firstOver: 4) equals: 2.
29+
self assert: (3 firstOver: 5) equals: 2.
30+
self assert: (3 firstOver: 6) equals: 2.
31+
32+
self assert: (4 firstOver: 2) equals: 2.
33+
self assert: (4 firstOver: 3) equals: 2.
34+
self assert: (4 firstOver: 4) equals: 2.
35+
self assert: (4 firstOver: 5) equals: 2.
36+
37+
self assert: (4 firstOver: SmallInteger maxVal) equals: 32768.
38+
self assert: (3 firstOver: SmallInteger maxVal) equals: 1048576.
39+
self assert: (2 firstOver: SmallInteger maxVal) equals: 1073741824.
40+
self assert: (1 firstOver: SmallInteger maxVal) equals: 1152921504606846975.
41+
42+
]

0 commit comments

Comments
 (0)