1
$\begingroup$

I am trying to create a module that allows users to cycle lists to look for a pattern and need a way to programmatically establish the number of controllers depending on the number of lists being used. As a small example, I am trying to do something like this:

 testModule[___] := 
 Module[{disks = {{"a", "b", "c"}, {"d", "e", "f"}, {"g", "h", 
      "i"}}},
  Manipulate[
   Row[{Column[RotateRight[disks[[1]], Disk1], Spacings -> 1],
     Column[RotateRight[disks[[2]],  Disk2], Spacings -> 1],
     Column[RotateRight[disks[[3]], Disk3], Spacings -> 1]}],
   {{Disk1, 0}, -3, 3, 1},
   {{Disk2, 0}, -3, 3, 1},
   {{Disk3, 0}, -3, 3, 1}]]

What I would like to do is be able to set up the controller command programmatically because there are in some examples 32 lists (called disks) but I am also wanting a way to make the number of lists variable.

Looking through the StackExchange, I think it is a some combination of using With and setting the initial values, but I cannot get it to work.

$\endgroup$
1

2 Answers 2

1
$\begingroup$

You CAN programmatically create controls for Manipulate, but it's actually more involved that it would be to just change your model. I can show you later if you want, but what you might try in the meantime is something like this:

DiskData[diskCount_, diskLength_] := 
  ArrayReshape[Alphabet[], {diskCount, diskLength}, Alphabet[]];
DiskManipulate[diskCount_, diskLength_] :=
  Module[
    {offsets = ConstantArray[0, diskCount],
     currentDisk = 1,
     initData = DiskData[diskCount, diskLength]},
    Manipulate[
      offsets[[currentDisk]] = offset;
      currentDisk = disk;
      offset = offsets[[disk]];
      TableForm[Transpose[MapThread[RotateRight, {initData, offsets}]]],
      {{disk, 1}, Range[diskCount]},
      {{offset, 0}, -diskLength, diskLength, 1, Appearance -> "Labeled"}]]

Try it with

DiskManipulate[3, 5]

enter image description here

$\endgroup$
1
  • $\begingroup$ It throws several red flags when I enter it, but it appears to work. $\endgroup$ Commented Apr 29 at 15:54
1
$\begingroup$

I've done it like this, with an array controlled by a set of sliders in the case of a matrix. Here all we need is a vector for the rotations.

test // ClearAll;
test[disks_?MatrixQ] := 
  With[{$rot = Table[0, Length@disks], (* need to initialize rot to be a vector *)
     dim = Dimensions@disks},
   Manipulate[
    Grid[Transpose@MapThread[RotateRight, {disks, rot}]],
    {{rot, $rot, "rotate"}, (* the initial value is the vector $rot *)
     Row[Table[With[{i = i}, (* inject the Part index *)
         Labeled[VerticalSlider[
           Dynamic@rot[[i]], (* each slider changes one part *)
           {-Last@dim + 1, Last@dim - 1, 1}, 
           ImageSize -> Small], Style[i, Italic]]
         ], {i, First@dim}]
       ] &}
    ]
   ];

SeedRandom[0];
disks = Partition[CharacterRange["a", "z"], 4];
disks = ReplacePart[#, 
    RandomInteger[{1, 4}] -> Style["X", Magenta]] & /@ disks

list of letters

test[disks]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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