Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I wrote the following to generate a multiset with the same number of items over a fixed range:

ConstantArray[#, 3]& /@ Range[9] // Flatten
{1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9} 

This approach uses four named functions (Range, Flatten, ConstantArray and Map (/@)) and one pure function (ending with &).
Is there a way to do the same thing with fewer functions?

Also, if I wanted to have variable numbers of items in my multiset how would I do that?
For example, let's say I wanted a multiset like { 1, 1, 1, 1, 2, 2, 3, 4, 4, 4, 6, 6, 7, 8, 8, 8 }.

By a "variable number of items" I do not mean random, I mean a specified variable number.

share|improve this question
add comment

7 Answers

up vote 4 down vote accepted
   f[n_, k_] := Table[ConstantArray[i, n], {i, k}]

Now you can vary the number of items of each:

f[3, 9] // Flatten

{1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9}

f[4, 10] // Flatten

{1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10}

for random Situation:

fRandom[n_, k_] := Table[ConstantArray[i, RandomInteger[{1, n}]], {i, k}]

For your second situation try this;

Inner[ConstantArray, Range[8], {4, 2, 1, 3, 0, 2, 1, 3}, List] // Flatten

{1, 1, 1, 1, 2, 2, 3, 4, 4, 4, 6, 6, 7, 8, 8, 8}

share|improve this answer
    
for constant k, one could also do: Flatten[Table[i, {i, 10}, {j, 3}]] –  Pinguin Dirk Oct 17 '13 at 17:05
    
@PinguinDirk. Fo shizzle :) –  RunnyKine Oct 17 '13 at 17:09
    
I do not want random numbers of items. I want specific numbers of each item in the multiset. –  Tyler Durden Oct 17 '13 at 18:11
    
@TylerDurden, Well, initially you did not specify this. How exactly do you want to specify those numbers, you need to be more specific so we know what you want. –  RunnyKine Oct 17 '13 at 18:33
    
@TylerDurden. See my update. –  RunnyKine Oct 17 '13 at 19:32
show 1 more comment

Ad. I

These should be the most efficient and tersest

Ceiling[ Range @ 27 / 3 ]

or

Array[ Ceiling[#/3] &, 27]

yield

{1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9}

they both can be tersely written in the Front End (see details of Ceiling) as:

enter image description here

or

enter image description here

Ad.II

For the second problem there are many approaches, here is a solution with a determined number of items ( Count[{1, 1, 1, 1, 2, 2, 3, 4, 4, 4, 6, 6, 7, 8, 8, 8}, #] & /@ Range[8]) as in your example:

Inner[ ConstantArray, Range @ 8, {4, 2, 1, 3, 0, 2, 1, 3}, Join]
{1, 1, 1, 1, 2, 2, 3, 4, 4, 4, 6, 6, 7, 8, 8, 8}

or

Flatten @ MapThread[ ConstantArray, {Range @ 8, {4, 2, 1, 3, 0, 2, 1, 3}}]
share|improve this answer
    
I do not want random numbers of items. I want specific numbers of each item in the multiset. –  Tyler Durden Oct 17 '13 at 18:12
    
@TylerDurden So you've got it. –  Artes Oct 17 '13 at 18:24
add comment

To me, the most straightforward way seems to be:

Flatten[ConstantArray[Range[9], 3], {2, 1}]
(* {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9} *)

i.e., instead of repeating each element in the list 3 times, you repeat the entire list 3 times and flatten it using the appropriate second argument.

share|improve this answer
    
+1 -- this is the same method I use, though usually with infix: Range@9 ~ConstantArray~ 3 ~Flatten~ {2, 1} :-) –  Mr.Wizard Dec 29 '13 at 20:08
    
@Mr.Wizard Pfft lame... 1 ~Range~ 9 ~ConstantArray~ 3 ~Flatten~ (2 ~List~ 1) :P –  rm -rf Dec 29 '13 at 20:59
    
reductio ad absurdum –  Mr.Wizard Dec 29 '13 at 22:33
add comment

No Rules?, so this is one from Szabolc's site:

 Range[9] /. n_Integer :> Sequence[n, n, n]
{1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9}

Since you haven't described how those numbers should vary for second part, maybe something like:

Sort@RandomInteger[{1, 10}, 27]
{1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 10}

Ok, let's say you have list of numbers which are referring to consecutive integers repetition:

Flatten@MapIndexed[ConstantArray[#2, #] &, {4, 3, 5, 1, 2, 3}]
{1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 5, 5, 6, 6, 6}

Or similar:

i = 0; 
Flatten[ConstantArray[++i, #] & /@ {4, 3, 5, 1, 2, 3}]
{1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 5, 5, 6, 6, 6}
share|improve this answer
    
I do not want random numbers of items. I want specific numbers of each item in the multiset. For example, in the case shown I want four 1's, two 2's, one 3, three 4's, no fives, two 6's, one 7, and three 8's. –  Tyler Durden Oct 17 '13 at 18:14
    
@TylerDurden ok :) see my edit –  Kuba Oct 17 '13 at 19:35
add comment
Flatten[ Range[ 1, 9, {1, 1, 1}], {2, 1}] 
Join @@ Table[ i, {i, 9}, {3}]
Join @@ Array[ # &, {9, 3}]
Table[ 1/9 (3 n - 2 Sqrt[3] Cos[(2 π n)/3 + π/6] + 3), {n, 27}]

{1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9}

share|improve this answer
    
This answer gets the booby prize, or the tongue-in-cheek prize, as the case may be. –  Tyler Durden Oct 29 '13 at 16:45
    
+1 for the first one; a nice way to use only two functions! –  Mr.Wizard Dec 29 '13 at 20:11
add comment

For your second question:

MapThread[ConstantArray, {Range[9], RandomInteger[{1, 3}, 9]}] // Flatten
(* {1, 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 9} *)
share|improve this answer
add comment

Yet another way, for the first part:

With[{n = 3, k = 10}, Quotient[Range[k n], n, -n+1]] (* incorporating Artes' suggestion *)

Updated:

For the second part, an approach not already covered in the other answers:

Module[{i = 1, reps = {4, 5, 1, 3}}, 
   Fold[#1~Join~ConstantArray[ i++, #2] &, {}, reps]] (* reps are variable repetition factors *)

{1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4, 4, 4}

share|improve this answer
1  
Very nice (+1) however I'd rather do this Quotient[ Range[3 9], 3, -2] to get exaclty what has been expected. Consider to answer another question in the OP. –  Artes Dec 29 '13 at 22:33
    
Oh sorry - for some reason I imagined the sequence began with zeros. I'll modify my answer. –  Aky Dec 29 '13 at 22:42
    
Why do you need With? There is no need for Range[1, k n] since it's equal to Range[k n]. And what about variable number of items? –  Artes Dec 29 '13 at 22:50
    
Oops, that was a mistake - I was really sleepy when I wrote that. Fixed now. The With is just for convenience and generalization, if someone wants to use the same method with a different range or repetition value. (I could've written it as a function.) –  Aky Dec 30 '13 at 5:59
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.