11using Open . Disposable ;
22using System ;
3+ using System . Buffers ;
34using System . Collections . Concurrent ;
45using System . Collections . Generic ;
56using System . Collections . Immutable ;
7+ using System . Linq ;
68
79namespace Open . Collections . Numeric
810{
@@ -44,16 +46,18 @@ public IEnumerable<IReadOnlyList<int>> GetUniqueAddends(int sum, int count)
4446
4547 {
4648 int i = 2 ;
49+ var c1 = count - 1 ;
50+ var c2 = c1 - 1 ;
4751 var builder = ImmutableArray . CreateBuilder < int > ( ) ;
4852
4953 while ( ++ i < sum )
5054 {
5155 var next = sum - i ;
52- var addends = UniqueAddendsFor ( i , count - 1 ) ;
56+ var addends = UniqueAddendsFor ( i , c1 ) ;
5357 foreach ( var a in addends )
5458 {
5559 builder . Capacity = count ;
56- if ( a [ a . Count - 1 ] >= next ) continue ;
60+ if ( a [ c2 ] >= next ) continue ;
5761 builder . AddRange ( a ) ;
5862 builder . Add ( next ) ;
5963 yield return builder . MoveToImmutable ( ) ;
@@ -73,5 +77,59 @@ protected override void OnDispose()
7377 }
7478 Cache . Clear ( ) ;
7579 }
80+
81+
82+ public static IEnumerable < int [ ] > GetUniqueAddendsBuffered ( int sum , int count )
83+ {
84+ if ( count > int . MaxValue )
85+ throw new ArgumentOutOfRangeException ( nameof ( count ) , count , "Cannot be greater than signed 32 bit integer maximum." ) ;
86+ if ( count < 2 || sum < 3 )
87+ yield break ;
88+
89+ var pool = ArrayPool < int > . Shared ;
90+ var result = pool . Rent ( count ) ;
91+
92+ try
93+ {
94+ if ( count == 2 )
95+ {
96+ int i = 0 ;
97+ loop2 :
98+ i ++ ;
99+ if ( i * 2 >= sum ) yield break ;
100+ result [ 0 ] = i ;
101+ result [ 1 ] = sum - i ;
102+ yield return result ;
103+
104+ goto loop2 ;
105+ }
106+
107+ {
108+ int i = 2 ;
109+ var c1 = count - 1 ;
110+ var c2 = c1 - 1 ;
111+
112+ while ( ++ i < sum )
113+ {
114+ var next = sum - i ;
115+ var addends = GetUniqueAddendsBuffered ( i , c1 ) ;
116+ foreach ( var a in addends )
117+ {
118+ if ( a [ c2 ] >= next ) continue ;
119+ a . CopyTo ( result , 0 ) ;
120+ result [ c1 ] = next ;
121+ yield return result ;
122+ }
123+ }
124+ }
125+ }
126+ finally
127+ {
128+ pool . Return ( result ) ;
129+ }
130+ }
131+
132+ public static IEnumerable < IEnumerable < int > > GetUniqueAddendsEnumerable ( int sum , int count )
133+ => GetUniqueAddendsBuffered ( sum , count ) . Select ( a => a . Take ( count ) ) ;
76134 }
77135}
0 commit comments