Looking for insights to suppress some redundancy in a "long" formula

Hi there Fellow Makers :blush: !

As the title of this topic says, I’m looking for ideas/insights :bulb: to potentially “simplify” a somewhat long formula.

The formula does exactly what I need but I have the feeling it contains some redundancy which could be removed :blush: … The only problem is that I just don’t see how, for some reasons :woman_shrugging: .

As I tend to naturally overcomplicate things, maybe there are “better” ways to get to my desired results too :innocent:

Any ideas or help will be deeply appreciated :grin: !

PS: Sorry if everything is not really clear :sweat_smile: … This was pretty hard to explain :innocent:.


Ok, so here’s my “problem” :blush: .

Let’s say I have 2 lists containing a set of 3 numbers (each number is entered through sliders) :

  • List_1(value 1, value 2, value 3)
  • List_2(value 1, value 2, value 3)

In between those 2 lists, I want to be able to create a precise amount of lists so the total matches a user defined quantity of lists (i.e.: List_1 + Lists_in_between + List_2 = user defined quantity x).

The Lists_in_between should contain sets of incremental or decremental values, going from each values in List_1 to each values in List_2 (not sure this is really clear :sweat_smile: ).

Trying to say this differently :

If List_1(value 1, value 2, value 3) is my Start list and List_2(value 1, value 2, value 3) is the End I want to create :

  • List_1(value 1, value 2, value 3)

  • Lists_in_between (
    List_1( value 1 )List_2( value 1 ),
    List_1( value 2 )List_2( value 2 ),
    List_1( value 3 )List_2( value 3 )
    )

  • List_2(value 1, value 2, value 3)

And the Total of lists needs to be precisely equal to the user defined input :blush: .

To do this, as you’ll see in the sample doc below, I first calculate the Increment or Decrement for each “set” of values so I could use it with Sequence().FormulaMap(...) to create “sub-list” for each values 1, values 2 and values 3.

I do this with this formula :

Sequence(1,3).FormulaMap(
  (List_2.Nth(CurrentValue) - List_1.Nth(CurrentValue))/(Total_Lists - 1)
)

Then as I was hoping to use this simple formula to create my desired lists :

Sequence(1,3).FormulaMap(
  Sequence(
    List_1.Nth(CurrentValue),
    List_2.Nth(CurrentValue),
    [Values_Inc-Dec].Nth(CurrentValue)
  )
)

I discovered it was returning an imprecise number of values, often less than what’s needed (and I really need that number to be the exact same number of values for each values 1, values 2, values 3 so I can create the exact total number of lists determined by the user)…

So, trying to solve that imprecision trouble, I count (for each values 1, values 2, values 3) the values returned by the formula just above and use these counts to compare them to the desired total.

For each values 1, values 2, values 3, if the count is less than the desired total, I ListCombine() the appropriate values + the missing one (as the missing value is just the last value… so the value in List_2).

I do this for each “set” of values 1, values 2 and values 3 with a formula looking like this :

If(
  [Values_Inc-Dec].Nth(1) = 0,
  Sequence(1,Total_Lists).FormulaMap(List_1.Nth(1)),
    ListCombine(
      Sequence(
        List_1.Nth(1),
        List_2.Nth(1),
        [Values_Inc-Dec].Nth(1)
        ).FormulaMap(
          Round(CurrentValue,1)
          ),
      If(
        Values_Count.Nth(1) < Total_Lists,
        List_2.Nth(1),
        "")
 ).Filter(CurrentValue.IsNotBlank()))

The last step just consist to put everything together with this formula (see the Result part in my sample) :

Sequence(1,Total_Lists).FormulaMap(
    List(
      Values_1.Nth(CurrentValue),
      Values_2.Nth(CurrentValue),
      Values_3.Nth(CurrentValue)
  )
).BulletedList()

Now, for the sake of playing around with WithName() and because I’m still unsure about the direction I’m going to take with this doc (:innocent:), I wanted to put everything into one formula :blush: :
(See Result All-in-one at the bottom of the doc :blush: )

Sequence(1,3).FormulaMap(
  (List_2.Nth(CurrentValue) - List_1.Nth(CurrentValue))/(Total_Lists-1)
    ).WithName(Values_Inc_Dec,
      Sequence(1,3).FormulaMap(
        Sequence(
          List_1.Nth(CurrentValue),
          List_2.Nth(CurrentValue),
          Values_Inc_Dec.Nth(CurrentValue)).Count()
          ).WithName(Values_Count,
            If(
              Values_Inc_Dec.Nth(1) = 0,
                Sequence(1,Total_Lists).FormulaMap(
                  List_1.Nth(1)
                  ),
                ListCombine(
                  Sequence(
                    List_1.Nth(1),
                    List_2.Nth(1),
                    Values_Inc_Dec.Nth(1)
                    ).FormulaMap(
                      Round(CurrentValue,1)
                      ),
                  If(
                    Values_Count.Nth(1) < Total_Lists,
                    List_2.Nth(1),
                    ""
                    )
                  ).Filter(CurrentValue.IsNotBlank())
                ).WithName(Values_1,
            If(
              Values_Inc_Dec.Nth(2) = 0,
                Sequence(1,Total_Lists).FormulaMap(
                  List_1.Nth(2)
                  ),
                ListCombine(
                  Sequence(
                    List_1.Nth(2),
                    List_2.Nth(2),
                    Values_Inc_Dec.Nth(2)
                    ).FormulaMap(
                      Round(CurrentValue,1)
                      ),
                  If(
                    Values_Count.Nth(2) < Total_Lists,
                    List_2.Nth(2),
                    ""
                    )
                  ).Filter(CurrentValue.IsNotBlank())
                ).WithName(Values_2,
            If(
              Values_Inc_Dec.Nth(3) = 0,
                Sequence(1,Total_Lists).FormulaMap(
                  List_1.Nth(3)
                ),
                ListCombine(
                  Sequence(
                    List_1.Nth(3),
                    List_2.Nth(3),
                    Values_Inc_Dec.Nth(3)
                    ).FormulaMap(
                      Round(CurrentValue,1)
                      ),
                  If(
                    Values_Count.Nth(3) < Total_Lists,
                    List_2.Nth(3),
                    ""
                    )
                  ).Filter(CurrentValue.IsNotBlank())
                ).WithName(Values_3,
            Sequence(1,Total_Lists).FormulaMap(
              List(
                Values_1.Nth(CurrentValue),
                Values_2.Nth(CurrentValue),
                Values_3.Nth(CurrentValue)
                )
              )
            )
          )
        )
      )
    ).BulletedList()

But the parts where I define my Values_1, Values_2 and Values_3 is bothering me a little. This is the part I see as redundant and I would like to optimize but just seem enable to do :blush: .

Here’s the sample :blush:

If anyone has any (better) ideas to get to my desired results or remove the redundant part, I’m all eyes and ears :grin: !

Thank you very much in advance :raised_hands: !

I am thoroughly baffled as to what you plan to use this for in real life :joy:
(…oh, colour gradients?)

But anyway. Your initial hunch makes sense to me too. Can you say more about why it was failing? Do you know where this imprecise value count was coming from? Rounding errors or…?

If I understand the All-in-one code, you’re repeating the same loop just with Nth(1) Nth(2) Nth(3), and the various names for WithName. It definitely seems like there should be a way to pack it all into a 3-count Values sequence, rather than 3 separate variables (Values_1 etc), and just loop. Hmm…

If I got it right, you’re looking to linearly interpolate between ValueStart and ValueEnd to get X values, but get your result in a “transposed” way (i.e. not a list of sequences for many start-end pairs, but a sequence of lists)

Wouldn’t it be easier (mentally at least) to calculate interpolations in a straightforward way and then transpose?

I’m not at my computer right now. I can test it out a bit later today.

P.S. Also why do you need it transposed? Let’s say you had just:

List(
  Sequence(Start1, End1, Step1),
  Sequence(Start2, End2, Step2),
  Sequence(Start3, End3, Step3)
)

would it be a problem to get what you need from it?

(this is just for illustration — of course you don’t want to use incremental steps because of rounding errors)

:joy: … and you’re pretty close :wink: !
I recently found myself in the middle of a colorful “SVG in Coda” rabbit hole :rabbit2:.
Never wrote a SVG in my life until few weeks ago and what I wanted here was to build a gradient “per se” but extract x numbers of colors in between 2 colors to reproduce something like this :
(with a bit more dynamism :blush: )


→ [Source]

My doc, so far, is just a giant “SVG in Coda” playground and I’m not sure about its future but I still want to explore its possibilities (it’s also still a wonderful way for me to exercise myself at Coda and get better at it :blush: )

But yes, here, all my Values_1 are the Reds, Values_2, the Greens and Values_3, the blues :blush:

Rounding errors …
I already ran into those while building my Capstone project for the Coda Doctorate.
Fortunately, I got some help to work around this issue :grin: … But it was just impossible to have a simple Sequence(start, end, 0.01) without having values repeating themselves or being skipped…

The problem seems similar here :blush: .

Yes, that’s it :blush: .
It’s really just an exercise (I had trouble to grasp WithName() so each time I encounter a situation where I could use it, I go for it…even if I don’t use it or keep it :blush: ).
In this case, here, if I keep each step separated, it makes sense to calculate each set of Values independently but within one formula, it just feels wrong… hence my topic :blush:.

Yes, I think so :blush:

I would love to, just can’t see how :innocent: !
(I’ve been going in circles for few days with this and I’m pretty sure, there’s something I don’t see :thinking: … I just can’t find what :sweat_smile: )

I think, in all my diverse tests, I tried something similar but I couldn’t make it work (I don’t remember exactly why though…)

Wait, are you trying to interpolate RGB components of a color independently?

Because doing that won’t give you the best-looking gradients. A more natural way to blend colors is to use HSL or HSV model. Or I imagine there should be even better models where luminance of different colors are normalized in some way (a quick googling gave me HCL. The problem with regular linear RGB transitions is that different components have different perceived lightness, as well as transitions e.g. from green to blue won’t pass through cyan but rather dark cyan (#00FF00 to #0000FF would pass through #008080)

IIRC @Phil_Hamilton did some work in this area:

You could also just have SVG gradients, no need to calculate intermediate colors yourself :slight_smile:


But for general case here’s my take at the algorithm.

The formula:

List(0, 255, 0).WithName(StartList,
List(255, 0, 0).WithName(EndList,
ToNumber(16).WithName(DataStops,
  Min(StartList.Count(), EndList.Count()).WithName(VectorDim,
    
    Sequence(1, VectorDim).FormulaMap(
      StartList.Nth(CurrentValue).WithName(CurrentStart,
      EndList.Nth(CurrentValue).WithName(CurrentEnd,
        Sequence(0, DataStops - 1).FormulaMap(
          CurrentStart + (CurrentEnd - CurrentStart) * (CurrentValue / (DataStops - 1))
        )
      ))
    ).WithName(InterpolatedSequences,
      Sequence(1, DataStops).FormulaMap(CurrentValue.WithName(DataStop,
        Sequence(1, VectorDim).FormulaMap(CurrentValue.WithName(I,
          InterpolatedSequences.Nth(I).Nth(DataStop)
        ))
      ))
    )
    
  )
)))

Note: you only need the inner part if you already have your three lists and the number of data stops, and feel free to replace VectorDim with a literal number 3 if you don’t need this to work with any sized lists.

Video:

2 Likes

Thank you so so so very much @Paul_Danyliuk for helping me with this :raised_hands: :partying_face: !!!

At some point, while testing, I think I managed to get a similar interpolation to yours, but then I couldn’t see how to transpose that to get my desired result :sweat_smile: (maybe I was just too tired… I don’t know…)

I’m sorry this distracted you from your client’s work though :sweat: … But I’m more than grateful that you took that time to help me :partying_face: :raised_hands:

As for w3schools…, I agree… It’s not source I would recommend either but yes, they do end up a lot in search results. I just stumbled on that page when I was searching for other svg ideas I could explore within Coda :blush: . Given my “Coda skills” and the limits I’m trying to push this one seemed like a good exercise to me :blush: !

Yes, I know :innocent:. I actually began with HSL(A) (kept the HCL for later…) as I used this post from @Phil_Hamilton as a starting point to explore SVG in Coda :blush:

But I took a step back from HSL after a while, when I began exploring color conversions and just decided to get back to “a source”: RGB(A) :blush: .

I was testing all this on RGB because that’s where I currently stand in my exploration :blush: but it doesn’t mean I’ll keep going into that direction :wink: .

So, yes, I know it’s a bad idea (:sweat_smile:) but I was still interested by knowing and understanding how to do it, why I couldn’t make it work in the first place and ended up hitting that wall… so I could escape my tunnel vision and improve myself :grin: !

Thank you so so so very much @Paul_Danyliuk :raised_hands: !
I can see things clearly again :wink: :raised_hands: !!!

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.