vexpr and finding the closest number in a list
hi
somewhere on this forum i found a great way to find a number in a list closest to x.
lets say i have a list of the numbers [3 10 30 100] and my integer is 25, the output will be 30.
it looks like this::
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 6,
"minor" : 1,
"revision" : 2,
"architecture" : "x86"
}
,
"rect" : [ 75.0, 119.0, 640.0, 480.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 9.0,
"default_fontface" : 0,
"default_fontname" : "Helvetica Neue",
"gridonopen" : 0,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 0,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"boxes" : [ {
"box" : {
"fontname" : "Helvetica Neue",
"fontsize" : 9.0,
"frgb" : 0.0,
"id" : "obj-34",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 49.0, 22.0, 150.0, 17.0 ],
"text" : "compare"
}
}
, {
"box" : {
"fontname" : "Helvetica Neue",
"fontsize" : 9.0,
"frgb" : 0.0,
"id" : "obj-32",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 128.0, 22.0, 150.0, 17.0 ],
"text" : "list"
}
}
, {
"box" : {
"comment" : "",
"id" : "obj-7",
"maxclass" : "outlet",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 78.0, 219.0, 25.0, 25.0 ]
}
}
, {
"box" : {
"fontname" : "Helvetica Neue",
"fontsize" : 9.0,
"id" : "obj-6",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "", "" ],
"patching_rect" : [ 78.0, 192.0, 69.0, 17.0 ],
"text" : "zl 1000 lookup"
}
}
, {
"box" : {
"fontname" : "Helvetica Neue",
"fontsize" : 9.0,
"id" : "obj-5",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "int", "int" ],
"patching_rect" : [ 49.0, 135.0, 48.0, 17.0 ],
"text" : "minimum"
}
}
, {
"box" : {
"fontname" : "Helvetica Neue",
"fontsize" : 9.0,
"id" : "obj-4",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "" ],
"patching_rect" : [ 128.0, 72.0, 69.0, 17.0 ],
"text" : "t l l"
}
}
, {
"box" : {
"fontname" : "Helvetica Neue",
"fontsize" : 9.0,
"id" : "obj-3",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 49.0, 99.0, 148.0, 17.0 ],
"text" : "vexpr abs($f2-$f1) @scalarmode 1"
}
}
, {
"box" : {
"comment" : "",
"id" : "obj-2",
"maxclass" : "inlet",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 128.0, 39.0, 25.0, 25.0 ]
}
}
, {
"box" : {
"comment" : "",
"id" : "obj-1",
"maxclass" : "inlet",
"numinlets" : 0,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 49.0, 39.0, 25.0, 25.0 ]
}
}
],
"lines" : [ {
"patchline" : {
"destination" : [ "obj-3", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-1", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-4", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-2", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-5", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-3", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-3", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-4", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-6", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-4", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-6", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-5", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-7", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-6", 0 ]
}
}
],
"dependency_cache" : [ ]
}
}
however - what i need to do is have the output find the nearest number in the list, OTHER than x (itself). say i would have the list [3 10 30 100] and my integer is 30, the output would be 10 rather than 30 (i am making chords, thats why i dont need two of the same numbers).
any thoughts on this would be greatly appreciated! and you will receive 350 EXP.
thanks!
úlfur
basically, i need something that can find the number larger than x and closest to x. similarily, find the number smaller than xand closest to x.
im not good with code, but maybe a js object could do the math?
for experience points i´d do almost everything.
i would probably
1.
check if X is contained in the incoming chord (expr $f1==$f2 @scalar)
2.
and if yes, remove the 30 from the chord (using zl union or zl nth or something like that)
3. then do what you already have
p.s. using copy compressed when posting patches to the forum will help to get more answers
whoa, level up :)
All you need is one extra object at top. Use [zl filter].
Keep in mind, this solution will chose the first nearest non-match in the list if the high and low have the same abs value. i.e. (10, 20, 30) chose 20 returns 10.
to share your patch:
Max window:
edit -> select all
edit -> copy compressed
Forum window:
edit -> paste
(don't use the code button)
thanks guys! metamax, your solution works beautifully.
now - if i wanted to get the abstraction to return only larger than numbers and closest to the input - how would i go about doing that?
reverse the filtered list with [zl rev].
-
dear metamax,
somehow its not working for me, the returned number alternates between nearest high and low...
I think I misunderstood you. The last patch I posted works exactly as intended. If the nearest high and low numbers have the same absolute value.. i.e. the same distance from the input - then you can choose which one to output. Otherwise, if there is no input match, it works exactly the same, outputting the nearest number in the list.
-
-
If you only want higher values returned, that's even easier.. but there are a few different ways to handle input values that don't match any list elements.
-
simple and beautiful. wish I had seen the original thread a month ago before I drove myself crazy doing the same thing for a sequencer.
dear metamax
my patch is almost working right now...
i am able to make triads with your function - and it works perfectly if i slide my mouse up and down the keyboard.
however - i cannot for the life of me figure out why it doesn't work if i "jump" between notes (make leaps with random intervals) . it very often gives me the wrong harmonic notes (they seem to stay put).
please have a look at my patch if you are interested, any help would be greatly appreciated!
anyone?
oolfur, you didn't reply to my last post so it's not clear what you originally wanted. Your question morphed from finding the closest number in a list to I honestly don't know what. The patch you just attached doesn't resemble anything I posted.. including [p closest].. so I don't know what you are comparing. I also don't know what you are trying to achieve in the bigger picture.
Perhaps if you strip your patch down to bare bones.. no unnecessary elements.. the problem will be more apparent. I did notice that you have 3 ksliders stacked on one another with one of them outputing values to two separate subpatchers that are returning values back to all three ksliders.. which are in turn are outputting values to three separate oscillators. Aside from the logic problems within the sub patchers, you might consider setting the two ksliders that are not sending values to the subpatchers to 'ignore click'. As it is now, you are sending output data from all three sliders to the oscillators before the subpatchers are returning values back to the ksliders.
There are other problems as well, but I'm not going to sit here and deconstruct it all for you. You are the man for that job.. Like I said, start by simplifying everything. It will make it all easier for you.. and if you can't figure it out, more people will be inclined to respond to your question.
Also.. you don't need to attach a .txt file for your coll values. You can select 'save data in patcher' in the coll inspector. That way, you don't need to attach anything... which likely will invite more people to look at your patch.
Good luck.
HI MetaMax,
How would you go about this?
if there is a match output the match
if there is no match output the closest value whether its lower or higher
Thanks
This seems to do the trick.
Hi METAMAX,
Neat and simple.
Thanks again!
Hi METAMAX,
I am trying to achieve something similar but with a jit.matrix and jit.expr. I am stuck at first level expression with the @expr. Any tips?
Best,
Sébastien, [jit.expr] is similar to [expr] but standard [zl] objects don't really have an equivalent in jitter. You'll need to play with some other approaches to get everything working. Be sure to check out [jit.bsort], [jit.planeop] and [jit.op]. If you have any mathematical formulas you want to translate into [jit.expr] or [expr], I'll be glad to help. You may also want to look into [jit.gen] or [jit.pix] for even more options.
In the mean time, if you are trying to find 'nearest numbers' to figure out 'closest colors', there may be an easier approach. Colors can be described as coordinates in 3d space. The shorter the distance between two colors, the more similar they should be. The simplest formula to calculate color difference can be found here: https://en.wikipedia.org/wiki/Color_difference#CIE76
Here is a working example using [jit.expr]. Hope this helps. Good luck with your project!
Hi METAMAX,
That is elegant!
Thanks