vexpr and finding the closest number in a list

Aug 13, 2013 at 9:55am

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

#258783
Aug 13, 2013 at 12:10pm

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?

#258802
Aug 13, 2013 at 1:35pm

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 :)

#258808
Aug 13, 2013 at 4:24pm

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.

– Pasted Max Patch, click to expand. –
#258821
Aug 13, 2013 at 4:28pm

to share your patch:

Max window:
edit -> select all
edit -> copy compressed

Forum window:
edit -> paste
(don’t use the code button)

#258822
Aug 13, 2013 at 8:18pm

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?

#258841
Aug 13, 2013 at 11:46pm

reverse the filtered list with [zl rev].

-

– Pasted Max Patch, click to expand. –
#258850
Aug 14, 2013 at 8:25am

dear metamax,

somehow its not working for me, the returned number alternates between nearest high and low…

– Pasted Max Patch, click to expand. –
#258880
Aug 14, 2013 at 5:54pm

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.

-

– Pasted Max Patch, click to expand. –

-

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.

-

– Pasted Max Patch, click to expand. –
#258922
Aug 14, 2013 at 10:19pm

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.

#258929
Aug 20, 2013 at 1:21pm

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!

Attachments:
  1. triad.zip
#259464
Aug 22, 2013 at 8:12pm

anyone?

#259676
Aug 22, 2013 at 9:47pm

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.

#259678

You must be logged in to reply to this topic.