Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I've been trying to work out how to create a Nearest function programmatically. My goal is to produce something similar to this, a hand-assembled function:

nf = Nearest[{0.0 -> "B", 0.05 -> "W", 0.1 -> "H", 0.15 -> "h", 
    0.2 -> "e", 0.3 -> "c",  0.4 -> "o", 0.5 -> "'", 0.6 -> "-", 
    0.7 -> ":", 0.8 -> ".", 0.9 -> "-", 0.95 -> " "}];

But instead of making it by hand, and editing the values, I want to pass a string and get all the letters allocated automatically to values between 0 and 1. (This is for producing ASCII-art type versions of images.)

For example, a function that looks a bit like this:

makeNearestFunction[string_] :=
 nf = Nearest[
  Riffle[
   Range[0, 1, N[1/StringLength[string]]], Characters[string]]
   ...
   (* returns a nearest function *)

could be called like this:

nf = makeNearestFunction["Mathematica!:- "]

I've got as far as producing a list of data like this:

{0., "M", 0.0666667, "a", 0.133333, "t", 0.2, "h", 0.266667, "e", 
 0.333333, "m", 0.4, "a", 0.466667, "t", 0.533333, "i", 0.6, "c", 
 0.666667, "a", 0.733333, "!", 0.8, ":", 0.866667, "-", 0.933333, " ", 
 1.}

but the pairs need to be assembled as rules.

share|improve this question

2 Answers 2

up vote 4 down vote accepted

The threading shown in my original answer below is unnecessary as Nearest accepts this form:

Mathematica graphics

Therefore you may use:

makeNearestFunction[string_] := 
  Nearest[Rescale@Range@Length@# -> #] & @ Characters@string

Perhaps this?

makeNearestFunction[string_] :=
 MapThread[Rule,
   {
    Most @ Range[0, 1, N[1 / StringLength@string]],
    Characters @ string
   }
 ] // Nearest

Or this?

makeNearestFunction[string_] :=
  With[{len = StringLength @ string},
    Nearest @ Thread[Range[0`, len - 1]/len -> Characters @ string]
  ]

This doesn't include 1. in the function, but neither does your hand-assembled function.

share|improve this answer
    
You make it look easy! :) I couldn't work out how to use the Rule function, but I see that it isn't essential. Nice one, sir! –  cormullion Aug 11 '12 at 12:53
    
@cormullion Thanks. I'm not sure which numeric value you want the last character to map to: 1 or one increment before 1, e.g. 0.95/0.933. What is your intent? –  Mr.Wizard Aug 11 '12 at 13:06
    
The 1.0 value will correspond to pure white in the original image, so it will occur rarely anyway. Or, in other words, I don't yet know... :) –  cormullion Aug 11 '12 at 13:46
makeNearestFunc1[string_String] := Nearest[Rule @@@ 
     Transpose@{Rescale@Range@StringLength@#, Characters@#}&@string]

or, a slight variation of Mr.W's second function,

makeNearestFunc2[string_String] :=
   Nearest@Thread[Rescale@Range@StringLength@# -> Characters@#] &@string

EDIT: To change the range to which the characters are mapped, use

Rescale[Range@#, {1, #}, {0, (-1 + #)/#}] &@StringLength@#

instead of

Rescale@Range@StringLength@#
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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