# Perhaps another way to shuffle lerped colors in an array?

**URL:** <https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597>\
**Category:** Coding Questions\
**Created:** [February 6, 2020, 10:38pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597 "2020-02-06T22:38:21Z")\
**Posts on this page:** 19\
**Page:** 2

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [February 10, 2020, 10:51pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/21 "2020-02-10T22:51:33Z")

</div>

> [@debxyz](#):
>
> **This returns error message mixing active and static.**  
> The colorList function works, the grid function does not…

Did you solve this?

The error message mostly is displayed when there is a misplaced } or { lines of code are outside any function which is not allowed

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [February 10, 2020, 10:52pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/22 "2020-02-10T22:52:41Z")

</div>

> [@debxyz](#):
>
> makeOneRowGrid() {

I think that you forgot to say void here

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 10, 2020, 10:53pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/23 "2020-02-10T22:53:46Z")

</div>

Yes, I did. You can see in the most recent code examples above that include both the grid and colorList functions.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [February 10, 2020, 10:54pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/24 "2020-02-10T22:54:42Z")

</div>

Gotoloop was referring to me saying that the function is portable/ re-usable in another sketch. It’s not because it uses variables from the sketch (from its global level). (The array size)

To make it portable we need to pass this information as a parameter to the function

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 10, 2020, 10:56pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/25 "2020-02-10T22:56:33Z")

</div>

Yes. That was the problem. Along with placing the color[]listColors = getColorList() in the function for void makeOneRow(). Once I did those two things it worked!

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 10, 2020, 10:57pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/26 "2020-02-10T22:57:48Z")

</div>

Ah. Okay, now I understand.

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 10, 2020, 11:01pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/27 "2020-02-10T23:01:04Z")

</div>

Thank you very much for all of your help with this!  
Will be applying all I learned in this thread to my next project.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [February 10, 2020, 11:01pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/28 "2020-02-10T23:01:55Z")

</div>

Yeah, you really make fast progress!

Proud!

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 10, 2020, 11:09pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/29 "2020-02-10T23:09:20Z")

</div>

@Chrisir  
Well, I appreciate your saying that but I could only get so far with books and youtube videos (as good as they are). The catalyst has been this forum. And your very clear explanations have been extremely helpful.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [February 11, 2020, 10:36am UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/30 "2020-02-11T10:36:51Z")

</div>

here is a version where the grid is returned as a result of the function

```auto
/* !!! grid made with a grid function AND listColors function !!!*/

// global array 
Cell[] cellsGlobal;

void setup() {
  size (1400, 800);

  cellsGlobal = getGrid(16);
}//func

void draw() {
  background (51);

  for (Cell currentCell : cellsGlobal) {
    currentCell.display();
  }//for
}//func 

//-----------------------------------------------------------------------------------------
// Tools 

Cell[] getGrid(int howMany) {

  Cell[] cellsLocal = new Cell[howMany];

  color[] listColors = getColorList(cellsLocal.length);

  int x = 20, y = x;
  int w = (width-40) / cellsLocal.length, h = height-40;

  for (int i = 0; i < cellsLocal.length; i++) {
    cellsLocal[i] = new Cell(x+i*w, y, 
      w, h, listColors[i]);
  }
  return cellsLocal;
}//func

color[] getColorList( int howMany ) {

  // for the command lerpColor: 
  color from = color(random(255), random(255), random(255)); // Start  
  color to = color(random(255), random(255), random(255)); // End 
  float step = 1.0f / (howMany-1); // **must use a float number to return a float number**

  // stores list of colors
  IntList colorIntList = new IntList(howMany); 

  // for loop to generate an IntList of lerped colors in order
  for (int k = 0; k < howMany; k++) {
    colorIntList.set(k, lerpColor (from, to, k*step));
  }

  // this step randomly shuffles the list inventory
  colorIntList.shuffle(); 

  // returns the shuffled colors 
  // as an array  
  return colorIntList.array();
}//func

//////////////////// CLASS ////////////////////

class Cell {
  float x, y, 
    w, h;
  color clr;

  // constr
  Cell ( 
    float tempX, float tempY, 
    float tempW, float tempH, 
    color tempClr) {

    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    clr = tempClr;
  }// constr

  void display() {
    stroke(255); 
    fill(clr);
    rect(x, y, 
      w, h);
  }//method 
  //
}//class
//

```

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 11, 2020, 7:20pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/31 "2020-02-11T19:20:40Z")

</div>

I’ll have a chance to look at this more closely this evening. But at first glance looks like it’ll be fun to parse.  
Thank you! 🤓

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 12, 2020, 12:50am UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/32 "2020-02-12T00:50:37Z")

</div>

@Chrisir Hello!  
I feel I have a general understanding of what is happening with this new syntax. However, I’ve placed comments next to / beneath lines where I have questions. Or notes on what I think(?) is happening at certain steps. Though am probably off the mark…  
By the way, the larger sketch size is nice!!

```auto
// ***GRID IS RETURNED via the function: Cell[] getGrid(int howMany)***

// global array 
Cell[] cellsGlobal; // declare the array

void setup() {
  size (1400, 800);

  cellsGlobal = getGrid(16); //initialize the array
}//func

void draw() {
  background (51);

  for (Cell currentCell : cellsGlobal) { // alternate syntax for for loop; currentCell is a temporary name while iterating through each element in array
    currentCell.display();
    // reference states "this structure is easier to iterate over each element of an array"
    // ??? Why is this easier? The syntax is easier to read? Or some different reason ? The program loops in a faster way?
  }//for
}//func 

//-----------------------------------------------------------------------------------------
// Tools 

Cell[] getGrid(int howMany) { // *int howMany* is the arguments for # of cells == this addresses the portability issue GoToLoop referred to

  Cell[] cellsLocal = new Cell[howMany];
  // cellsLocal = local variable for the Cell? makes the function portable
  // the number of cells to be created (16 initialized in setup)

  color[] listColors = getColorList(cellsLocal.length); 
  // number of colors matches number of cells in grid 

  int x = 20, y = x; // local variables to construct the grid
  int w = (width-40) / cellsLocal.length, h = height-40; // local variables to construct the grid

  for (int i = 0; i < cellsLocal.length; i++) { // iterative loop
    cellsLocal[i] = new Cell(x+i*w, y, 
      w, h, listColors[i]);
  }
  return cellsLocal; // returns the ?????
  // ???? How does *cellsLocal* loop back 
  // to *currentCell.display()* in draw function ?
  // Is the connection to “Cell”?
}//func

color[] getColorList(int howMany) { 
  // ??? *int howMany* argument is needed here 
  // for portability, re GoToLoop

  color from = color(random(255), random(255), random(255));  
  color to = color(random(255), random(255), random(255)); 
  float step = 1.0f / (howMany-1); 

  IntList colorIntList = new IntList(howMany); 
  // re: *colorIntList* name, previously used *inventory* as the name;
  // confirming better to use descriptive names and not the generic *inventory* ???

  for (int k = 0; k < howMany; k++) {
    colorIntList.set(k, lerpColor (from, to, k*step));
  }

  colorIntList.shuffle(); 

  return colorIntList.array();
}//func

```

///////////// CLASS /////////////

```auto
class Cell {
  float x, y, 
    w, h;
  color clr;

  // constr
  Cell ( 
    float tempX, float tempY, 
    float tempW, float tempH, 
    color tempClr) {

    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    clr = tempClr;
  }// constr

  void display() {
    stroke(255); 
    fill(clr);
    rect(x, y, 
      w, h);
  }//method 
  //
}//class
//

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [February 12, 2020, 12:00pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/33 "2020-02-12T12:00:01Z")

</div>

**What I’ve changed**

I changed only a few things:

- The function `Cell[] getGrid` is now returning the grid as a result. Accordingly the line that receives the result is `cellsGlobal = getGrid(16); ` in `setup()`.

- I used a simplified for-loop: `for (Cell currentCell : cellsGlobal) {`

**Your questions**

> [@debxyz](#):
>
> // reference states “this structure is easier to iterate over each element of an array” // ??? Why is this easier? The syntax is easier to read? Or some different reason ? The program loops in a faster way?

The for loop in draw() is simplified.  
Yes. It’s better readable. It’s not faster I guess.

> [@debxyz](#):
>
> Cell cellsLocal = new Cell[howMany];  
> // cellsLocal = local variable for the Cell?

cellsLocal = local variable/array for the **grid**.

> [@debxyz](#):
>
> int w = (width-40) / cellsLocal.length, h = height-40; // local variables to construct the grid

Please note that I use `width` and `height` here now.  
This means that the function would change the cell size automatically when you change the window size (using the size() command in the function setup()).

> [@debxyz](#):
>
> return cellsLocal; // returns the ???  
> // ??? How does _cellsLocal_ loop back  
> // to _currentCell.display()_ in draw function ?  
> // Is the connection to “Cell”?

The function `getGrid()` is now returning the grid as a result.  
So cellsLocal is made in the function and returned as a result of the function (using return command).  
In setup() the array gets copied (by the = sign) into the global grid cellsGlobal.

The line `currentCell.display()` is within the _for loop_ which reads: for each element in the array cellsGlobal copy the element into currentCell and use this in _currentCell.display()_.

So here two aspects are at work: the grid is returned and the for-loop uses the global grid.

> [@debxyz](#):
>
> color getColorList(int howMany) { // ??? _int howMany_ argument is needed here // for portability, re GoToLoop

Yes.

> [@debxyz](#):
>
> IntList colorIntList = new IntList(howMany);  
> // re: _colorIntList_ name, previously used _inventory_ as the name;  
> // confirming better to use descriptive names and not the generic _inventory_ ???

confirmed. You can choose the name freely. A correct, descriptive name is an important part of _good programming_.

**What is _good programming_?**

- A correct, descriptive name of variables, objects and arrays… is an important part of _good programming_.
- Convention: constants are ALL\_CAPITAL, classes StartWithCapital, objects startSmall, lists are in plural (containing many objects or elements)
- Using functions to modularize your code is also part of _good programming_. Good naming of functions too.
- Not too long functions. Functions longer than one screen could be considered as being too long and could be split up in 2 smaller functions.
- The idea of portability (no dependencies) is also part of _good programming_. Re-usability
- Using classes / OOP is part of _good programming_.
- Good comments are part of _good programming_. Not explaining a command but rather the _purpose_ of a section / function.
- Good programming has the goal that a co-worker of you (or yourself after 6 months) has a chance to understand the code quickly and can work from it to a new bigger project. When he reads “inventory” he wouldn’t understand as much as when reading `colorIntList`.
- good readability, good maintainability
- related : [SOLID - Wikipedia](https://en.wikipedia.org/wiki/SOLID)

Chrisir

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 12, 2020, 8:43pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/34 "2020-02-12T20:43:26Z")

</div>

> [@debxyz](#):
>
> > [@debxyz](#):
> >
> > Cell cellsLocal = new Cell[howMany];
> > 
> > > // cellsLocal = local variable for the Cell?
> 
> cellsLocal = local variable/array for the **grid**.

Ah, yes. for the grid!

> [@debxyz](#):
>
> > [@debxyz](#):
> >
> > int w = (width-40) / cellsLocal.length, h = height-40; // local variables to construct the grid
> 
> Please note that I use `width` and `height` here now.  
> This means that the function would change the cell size automatically when you change the window size (using the size() command in the function setup()).

Understood. 🙂

> [@debxyz](#):
>
> > [@debxyz](#):
> >
> > return cellsLocal; // returns the ???
> > 
> > > // ??? How does _cellsLocal_ loop back  
> > > // to _currentCell.display()_ in draw function ?  
> > > // Is the connection to “Cell”?
> 
> The function `getGrid()` is now returning the grid as a result.  
> So cellsLocal is made in the function and returned as a result of the function (using return command).  
> In setup() the array gets copied (by the = sign) into the global grid cellsGlobal.
> 
> The line `currentCell.display()` is within the _for loop_ which reads: for each element in the array cellsGlobal copy the element into currentCell and use this in _currentCell.display()_ .
> 
> So here two aspects are at work: the grid is returned and the for-loop uses the global grid.

Okay, that makes sense.

> [@debxyz](#):
>
> > [@debxyz](#):
> >
> > IntList colorIntList = new IntList(howMany);
> > 
> > > // re: _colorIntList_ name, previously used _inventory_ as the name;  
> > > // confirming better to use descriptive names and not the generic _inventory_ ???
> 
> confirmed. You can choose the name freely. A correct, descriptive name is an important part of _good programming_ .

Good to know! I guess I read the reference too literally sometimes. Still working out the language that must be used vs the generic – in this case “inventory”…

The **What is good programming?** bullet list at the end is GREAT!! Thank you!!

I have 2 more directions I’d like to explore with this sketch. So will likely post a follow up with new added code within the next couple of days, if you’re curious to take a look.

Thank you again!!!

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 14, 2020, 6:32pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/35 "2020-02-14T18:32:13Z")

</div>

Hello @Chrisir!

I have added the next steps to this sketch.

\*\*\ ***Please note comments that begin in TOOLS area** starting with the function **color[]getThreeColorLerp() {**

- As a way to add more user control over the colors generated, I’ve added a third color to the mix.

- I still need to add a step where **the end color lerps to the start color**. So that when I create a new function (see next line below) the colors will undulate seamlessly.

- I want to now build a new list array via a new function **expandColorArrayLength()** from the colors generated in **getThreeColorLerp()** function so that this core group of colors is repeated. This array index size would have at least 100 spots but could be easily increased or decreased.

- I would then apply this repeating color array to a large grid with both columns and rows.

- There are a couple of questions commented in the **expandColorArrayLength() function** section regarding how to proceed.

Thank you for this link!! I read it with interest. 🙂

> [@Chrisir](#):
>
> related : [SOLID - Wikipedia](https://en.wikipedia.org/wiki/SOLID)

**MAIN ///////////////////////////////////////**

```auto
// global array

Cell[] cellsGlobal; // declare the array

void setup() {
  size (1000, 600);

  cellsGlobal = getGrid(15); //initialize the array
}//func

void draw() {
  background (51);

  for (Cell currentCell : cellsGlobal) { 
    currentCell.display();
  }//for

  // rectangles placed for color reference 
  // to confirm target colors are hit when color is lerped 
  fill(color(12, 187, 229));
  rect(width-150, 0, 150, 50);

  fill(color (250, 200, 63));
  rect((width/2)-75, 0, 150, 50);

  fill(color (245, 17, 48));
  rect(0, 0, 150, 50);
}//func 

//-----------------------------------------------------------------------------------------
// Tools 

Cell[] getGrid(int howMany) { 

  Cell[] cellsLocal = new Cell[howMany];

  color[] listColors = getThreeColorLerp();

  // local variables to construct the grid
  int x = 25, y = x; // local variables to construct the grid
  int w = (width-40) / cellsLocal.length, h = height-50; 

  for (int i = 0; i < cellsLocal.length; i++) { // iterative loop
    cellsLocal[i] = new Cell(x+i*w, y, 
      w, h, listColors[i]);
  }
  return cellsLocal;
}//func

color[]getThreeColorLerp() { // no parameter now b/c next step 
// is to *make copies of the colorGroup_1 array and combine* to make 
// a longer array with at least 100 places 

  color start = color (245, 17, 48);
  color midpoint = color (250, 200, 63);
  //color midpoint = color (255); // test for gradation to white
  color end = color(12, 187, 229);

  int num = 15;
  float step = 1.0f / num;

  IntList colorGroup_1 = new IntList (num);

  // iterative loop for lerpColor using 3 colors
  for (int k = 0; k < num; k++) {
    
    float m = map (step, 0.0, 1.0, 0.0, 2.0);
    // used map and if and else to determine transition 
    // point from 2nd to 3rd color
    
    if (k*m <= 1.0) {
      
      colorGroup_1.set (k, lerpColor(start, midpoint, k*m));
      
    } else {
      
      colorGroup_1.set (k, lerpColor(midpoint, end, (k*m)-0.9));
    }
  }
  return colorGroup_1.array();
}

//color [] expandColorArrayLength(){
  // this function is to take IntList colorGroup_1 
  // generated in getThreeColorLerp() function and
  // copy colorGroup_1 multiple times and place in 
  // a new expanded array containing at least 100 index spots
  
  // Possible to do with a for loop using modulo to loop back to zero index? 
  // Or is there a better way?
  // Duplicate the array and use concat()? Though this seems less straightforward ...

  //color[] listColors = getThreeColorLerp();
  
//}

```

**CLASS //////////////////////////**

```auto
class Cell {
  float x, y, 
    w, h;
  color clr;

  // constr
  Cell ( 
    float tempX, float tempY, 
    float tempW, float tempH, color tempClr) 
  {

    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    clr = tempClr;
  }// constr

  void display() {
    stroke(0); 
    fill(clr);
    rect(x, y, 
      w, h);
  }//method 
  //
}//class
//

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [February 14, 2020, 8:16pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/36 "2020-02-14T20:16:42Z")

</div>

Thanks a lot for this!

At the moment I don’t have time.

Maybe somebody else can help?

---

<div class="post-metadata">

**Author:** ![debxyz](https://avatars.discourse-cdn.com/v4/letter/d/58956e/32.png) [@debxyz](https://discourse.processing.org/u/debxyz)\
**Post date:** [February 14, 2020, 8:43pm UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/37 "2020-02-14T20:43:58Z")

</div>

That’s totally fine!! 🙂  
Thanks for tagging another member.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [February 15, 2020, 4:51am UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/38 "2020-02-15T04:51:19Z")

</div>

> [@debxyz](#):
>
> I still need to add a step where **the end color lerps to the start color**.

I haven’t reviewed this entire thread, but:

One way is to use lerpColors() (search forum) and specify the first and last list color as the same value. Wrap the input with modulo.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [February 15, 2020, 11:40am UTC](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597/39 "2020-02-15T11:40:59Z")

</div>

I think you can make a new function that uses the old color function

Get 2 arrays and join them with concat() command

I didn’t have time to look at it really

[Previous page](https://discourse.processing.org/t/perhaps-another-way-to-shuffle-lerped-colors-in-an-array/17597.md?page=1)
