{- It depends on what is the "smallest". But here is the solution for the concept of "least" if tuples were compared first to their max. number, and then by their total amount. (You can simply copy and paste my entire answer into a file when I write the text in the comments.)
We will need a nub later. -}
import Data.List (nub)
{- just to illustrate: a simple case with 2 tuples. -}
-- all the two-tuples where 'snd' is 'n' tuples n = [(i, n) | i <- [1..n]] -- all the two-tuples where 'snd' is in '1..n' tuplesUpTo n = concat [tuples i | i <- [1..n]]
{- To get all the results, you will need to insert a flip of each tuple into the stream. But do it later and generalize first.
Building tuples of arbitrary length is somewhat complicated, so we will work on lists. I call them "kList" if they have a length of "k". -}
-- just copied from the tuples case, only we need a base case for k=1 and -- we can combine all results utilizing the list monad. kLists 1 n = [[n]] kLists kn = do rest <- kLists (k-1) n add <- [1..head rest] return (add:rest) -- same as above. all the klists with length k and max number of n kListsUpTo kn = concat [kLists ki | i <- [1..n]] -- we can do that unbounded as well, creating an infinite list. kListsInf k = concat [kLists ki | i <- [1..]]
{- The next step is to rotate these lists, because so far the largest number is always in last place. Therefore, we just look at all the turns to get all the results. Using nub here is admittedly inconvenient, you can improve it. But without this, lists in which all elements are the same repeat k times. -}
rotate nl = let (init, end) = splitAt nl in end ++ init rotations kl = nub [rotate il | i <- [0..k-1]] rotatedKListsInf k = concatMap (rotations k) $ kListsInf k
{- It remains to convert these lists into tuples. This is a bit inconvenient because each n-tuple is a separate type. But it is simple, of course. -}
kListToTuple2 [x,y] = (x,y) kListToTuple3 [x,y,z] = (x,y,z) kListToTuple4 [x,y,z,t] = (x,y,z,t) kListToTuple5 [x,y,z,t,u] = (x,y,z,t,u) kListToTuple6 [x,y,z,t,u,v] = (x,y,z,t,u,v)
{- Some tests:
*Main> take 30 . map kListToTuple2 $ rotatedKListsInf 2 [(1,1),(1,2),(2,1),(2,2),(1,3),(3,1),(2,3),(3,2),(3,3),(1,4),(4,1),(2,4),(4,2),(3,4), (4,3),(4,4),(1,5),(5,1),(2,5),(5,2),(3,5),(5,3),(4,5),(5,4),(5,5),(1,6),(6,1), (2,6), (6,2), (3,6)] *Main> take 30 . map kListToTuple3 $ rotatedKListsInf 3 [(1,1,1),(1,1,2),(1,2,1),(2,1,1),(1,2,2),(2,2,1),(2,1,2),(2,2,2),(1,1,3),(1,3,1), (3,1,1),(1,2,3),(2,3,1),(3,1,2),(2,2,3),(2,3,2),(3,2,2),(1,3,3),(3,3,1),(3,1,3), (2,3,3),(3,3,2),(3,2,3),(3,3,3),(1,1,4),(1,4,1),(4,1,1),(1,2,4),(2,4,1),(4,1,2)]
Edit: I realized that there is a mistake: just turning the ordered lists, of course, is not enough. The solution should be somewhere close to what
rest <- concat . map (rotations (k-1)) $ kLists (k-1) n
in kLists , but then there are some problems with repetitive exits. I suppose you can figure it out. ;-) -}