Forum: Ruby variable from array to function to array

Posted by Dave Castellano (dcastellano1)
on 2012-08-17 02:39
anyone know if it is possible to pass elements from an array (eg 20,50 )
to the function
number_range(min,max) and have the returned value used in the variable
|age| below...


def number_range(min,max)         # Chooses a random number within
specified range.
  num = min + rand(max - min)
end

array = [ lambda { |age| "An #{age} year old..."}, 20, 50 ]

puts array[0][age returned from number_range method]


>>  An 18 year old...
Posted by "Jesús Gabriel y Galán" <jgabrielygalan@gmail.com> (Guest)
on 2012-08-17 08:19
(Received via mailing list)
On Fri, Aug 17, 2012 at 2:39 AM, Dave Castellano <lists@ruby-forum.com> 
wrote:
>
> array = [ lambda { |age| "An #{age} year old..."}, 20, 50 ]
>
> puts array[0][age returned from number_range method]
>
>
>>>  An 18 year old...

The obvious thing would be:

puts array[0][number_range(array[1], array[2])]

but this data structure starts to be too complicated. Why is it an
array? Will you have some (many) more entries (lambda + range)? If so,
you could be better off with a class to represent that information:

RangedInterpolation = Struct.new :lambda, :min, :max

array = [ RangedInterpolation.new(lambda { |age| "An #{age} year
old..."}, 20, 50) ]
array.each {|interpolation| puts
interpolation.lambda(number_range(interpolation.min,
interpolation.max))}

You could go one step further and make the pair min,max a Range
object, and even include the number_range method inside the class.

Jesus.
Posted by unknown (Guest)
on 2012-08-17 10:06
(Received via mailing list)
Am 17.08.2012 02:39, schrieb Dave Castellano:
> anyone know if it is possible to pass elements from an array (eg 20,50 )
> to the function
> number_range(min,max) and have the returned value used in the variable
> |age| below...
>
>
> def number_range(min,max)         # Chooses a random number within
> specified range.
>    num = min + rand(max - min)
> end

This will never return max!

Use   min + rand(max - min + 1)   or simply   rand(min..max)

> array = [ lambda { |age| "An #{age} year old..."}, 20, 50 ]
>
> puts array[0][age returned from number_range method]

This would work:

array = [lambda { |age| "An #{age} year old..."}, 20, 50]
puts array[0][rand(array[1]..array[2])]

But this approach seems very odd to me. What are you trying to do?
Why not do it like this:


def random_age_string(range)
   "A #{rand(range)} year old"
end

puts random_age_string(20..40)


But it is rather impossible to provide useful help
unless you give us the bigger picture.
Posted by Dave Castellano (dcastellano1)
on 2012-08-17 14:15
The bigger picture...  I am saving multiple question templates in a 
array and need to store all the info (the question, the min and max 
ranges, the units of measure etc assoc with each question.  The 
associated info is used to build the question ... eg in question one, 
need to pass 20,40 to number_range(min,max)  and use the returned value 
as u.

def number_range(min,max)
  min + rand(max - min + 1)  **Thanks!
end

array =[
[ lambda {|u,u_unit| "A slide is placed #{u} #{u_unit} to the left of a 
lens...", 20, 40, "cm"],
[ lambda {|v,v_unit| "An image is in focus #{v} #{v_unit} to the right 
of a...", 10, 25, "mm],
[....
]


puts array[n][variable returned from number_range method]


>>  A slide is placed 25 cm...


Also,
def random_age_string(range)
   "A #{rand(range)} year old"
end

puts random_age_string(20..40)

Does not work as I am not able to embed "#{}" in a string in an array... 
it just returns the string without evaluating...
Posted by unknown (Guest)
on 2012-08-17 16:03
(Received via mailing list)
Am 17.08.2012 14:15, schrieb Dave Castellano:
> The bigger picture...  I am saving multiple question templates in a
> array and need to store all the info (the question, the min and max
> ranges, the units of measure etc assoc with each question.  The
> associated info is used to build the question ... eg in question one,
> need to pass 20,40 to number_range(min,max)  and use the returned value
> as u.

Ok... :)

First: did you consider using a templating system for your
"question templates"? You could avoid the lambdas;
instead, you provide a template as a simple string that gets
evaluated later when the needed values are known.

Second: Instead of using nested arrays I would put all the
question-generating functionality into a class.

Assuming the structure of your questions is always the same,
below is one possible way to do it:


require 'erb'

class Question

   attr_reader :unit

   def initialize(text, range, unit)
     @text = ERB.new(text)
     @range = range
     @unit = unit
   end

   def val
     rand(@range)
   end

   def to_s
     @text.result(binding)
   end
end

questions = [
   Question.new('A slide is placed <%= val %> <%= unit %>...',
                20..40, 'cm'),
   Question.new('An image is in focus <%= val %> <%= unit %>...',
                10..15, 'mm')
]

questions.each {|q| puts q }
questions.each {|q| puts q }  # results in different values


*BUT:*

- Can't you simply include the unit in the text part?
- Do you really need to have the same question with
   different values in the same run of your program?

How about:

questions = [
   "A slide is placed #{rand(20..40)} cm...",
   "An image is in focus #{rand(10..15)} mm..."
]
questions.each {|q| puts q }
Posted by Sean O'halpin (sean)
on 2012-08-18 01:16
(Received via mailing list)
On Fri, Aug 17, 2012 at 1:15 PM, Dave Castellano <lists@ruby-forum.com> 
wrote:
> The bigger picture...  I am saving multiple question templates in a
> array and need to store all the info (the question, the min and max
> ranges, the units of measure etc assoc with each question.  The
> associated info is used to build the question ... eg in question one,
> need to pass 20,40 to number_range(min,max)  and use the returned value
> as u.

If you're using ruby 1.9, you can use the new hash interpolation syntax:

  puts "Hello %{who}" % { :who => "world" }

outputs

  Hello world

For example:

  def number_range(min,max)
    min + rand(max - min + 1)
  end

  array =[
          [ "A slide is placed %{value} %{unit} to the left of a
lens...", 20, 40, "cm"],
          [ "An image is in focus %{value} %{unit} to the right of
a...",  10, 25, "mm" ],
         ]

  array.each do |item|
    text, min, max, unit = item
    puts text % { :value => number_range(min, max), :unit => unit }
  end

  puts "Hello %{who}" % { :who => "world" }

Regards,
Sean
Posted by unknown (Guest)
on 2012-08-18 07:14
(Received via mailing list)
Here an improved version that allows you to use an arbitrary,
possible different set of properties for each question.
Random values are returned if you provide a Range or an Array.

(And it now uses the hash interpolation pointed out by Sean
instead of erb,)


class Question

   def initialize(text, substitutions)
     @text = text
     @substitutions = substitutions
   end

   def to_s
     subst = {}
     @substitutions.each do |k, v|
       if v.class == Range
         subst[k] = rand(v)
       elsif v.class == Array
         subst[k] = v.sample
       else
         subst[k] = v
       end
     end
     @text % subst
   end
end

# You can use arbitrary keys.
# For ranges or arrays a random number / element is used.
questions = [
   Question.new('A slide is placed %{val} %{unit} %{side} of...',
                {:val => 20..40, :unit => 'cm',
                :side => ['left', 'right']}),
   Question.new('An image is ... %{val} mm ... and %{factor} times...',
                {:val => 10..15, :factor => 2..9})
]

questions.each {|q| puts q }
questions.each {|q| puts q }  # gives different values
Posted by unknown (Guest)
on 2012-08-18 07:19
(Received via mailing list)
Am 18.08.2012 01:15, schrieb Sean O'Halpin:
>
> If you're using ruby 1.9, you can use the new hash interpolation syntax:
>
>    puts "Hello %{who}" % { :who => "world" }
>

Nice, thanks!
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.