Kaiton
Kaiton

Reputation: 33

Give an if statement a variable in Ruby

I have this if statement:

  if value_n_in_f > 0 && value_m_in_f != 1
    puts "I: f(x)=#{value_m_in_f}x+#{value_n_in_f}"
  elsif value_n_in_f == 0 && value_m_in_f != 1
    puts "I: f(x)=#{value_m_in_f}x"
  elsif value_n_in_f < 0 && value_m_in_f != 1
   puts "I: f(x)=#{value_m_in_f}x#{value_n_in_f}"
  elsif value_n_in_f > 0 && value_m_in_f == 1
    puts "I: f(x)=x+#{value_n_in_f}"
  elsif value_n_in_f == 0 && value_m_in_f == 1
    puts "I: f(x)=x"
  elsif value_n_in_f < 0 && value_m_in_f == 1
    puts "I: f(x)=x#{value_n_in_f}"
  end`

I have to use this statement really often in other statements and it makes my code unnecessarily long. Obviously if_for_f=if ....... end won't work. Is there any other way? Here's an example what I want it to look like:

puts "Now we insert #{value_of_x} in #{if_for_f}"

Is there any way I can do something like this? Note that I am absolutly new to this.

Thanks in advance, Kaiton

Upvotes: 2

Views: 124

Answers (3)

J-Dizzle
J-Dizzle

Reputation: 3191

A couple of things here: you can put "puts" before the whole if/elsif block and avoid having puts on every line, like so:

puts case 
  when (value_n_in_f > 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x+#{value_n_in_f}"
  when (value_n_in_f == 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x"
end

Second, a case statement would be much more readable, like so:

def big_compare(value_n_in_f, value_m_in_f)
  msg = case
    when (value_n_in_f > 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x+#{value_n_in_f}"
    when (value_n_in_f == 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x"
    when (value_n_in_f < 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x#{value_n_in_f}"
    when (value_n_in_f > 0 && value_m_in_f == 1) then "I: f(x)=x+#{value_n_in_f}"
    when (value_n_in_f == 0 && value_m_in_f == 1) then "I: f(x)=x"
    when (value_n_in_f < 0 && value_m_in_f == 1) then "I: f(x)=x#{value_n_in_f}"
  end
end
puts big_compare(0, 0)

Upvotes: 2

7stud
7stud

Reputation: 48649

can't I just def a function with its function to run this case statement and call it then when I need it it?

Of course:

def do_stuff(m, n)
  if m == 1
    if n > 0      then "I: f(x)=x+#{n}"
    elsif n == 0  then "I: f(x)=x"
    elsif n < 0   then "I: f(x)=x#{n}"
    end
  else
    if n > 0      then "I: f(x)=#{m}x+#{n}"
    elsif n == 0  then "I: f(x)=#{m}x"
    elsif n < 0   then "I: f(x)=#{m}x#{n}"
    end
  end
end

puts do_stuff(1, 1)  #I: f(x)=x+1

Or, if compactness is the goal, we can get to this:

def do_stuff(m, n)
  if m == 1
    n == 0  ? "I: f(x)=x"     : "I: f(x)=x#{sprintf("%+d", n)}" 
  else
    n == 0  ? "I: f(x)=#{m}x" : "I: f(x)=#{m}x#{sprintf("%+d", n)}" 
  end
end

...and then a one liner:

def do_stuff(m, n)
  (m == 1) ? (n == 0  ? "I: f(x)=x" :  "I: f(x)=x#{sprintf("%+d", n)}") : (n == 0  ? "I: f(x)=#{m}x" : "I: f(x)=#{m}x#{sprintf("%+d", n)}")
end
end

But your methodology has some problems with zeros and -1:

def do_stuff(value_m_in_f, value_n_in_f)
 if value_n_in_f > 0 && value_m_in_f != 1
    puts "I: f(x)=#{value_m_in_f}x+#{value_n_in_f}"
  elsif value_n_in_f == 0 && value_m_in_f != 1
    puts "I: f(x)=#{value_m_in_f}x"
  elsif value_n_in_f < 0 && value_m_in_f != 1
   puts "I: f(x)=#{value_m_in_f}x#{value_n_in_f}"
  elsif value_n_in_f > 0 && value_m_in_f == 1
    puts "I: f(x)=x+#{value_n_in_f}"
  elsif value_n_in_f == 0 && value_m_in_f == 1
    puts "I: f(x)=x"
  elsif value_n_in_f < 0 && value_m_in_f == 1
    puts "I: f(x)=x#{value_n_in_f}"
  end
end

do_stuff(1, 0)
do_stuff(1,-1)
do_stuff(1, 1)
do_stuff(0,-1)
do_stuff(0, 0)
do_stuff(-1, 1)

--output:--
I: f(x)=x
I: f(x)=x-1
I: f(x)=x+1
I: f(x)=0x-1   #<---HERE
I: f(x)=0x     #<---HERE
I: f(x)=-1x+1  #<---HERE

So let's fix that:

def get_line_equ(m, b)
  constant = (b == 0) ? "" : sprintf("%+d", b) # 2 => "+2"

  case m
  when 0 
    xterm = ""
    constant = b
  when 1 
    xterm = "x"
  when -1 
    xterm = "-x"
  else 
    xterm = "#{m}x"
  end

  "I: f(x)=#{xterm}#{constant}"
end

puts get_line_equ(0, 0)
puts get_line_equ(0, -1)
puts get_line_equ(0, 1)

puts get_line_equ(1, 0)
puts get_line_equ(1,-1)
puts get_line_equ(1, 1)

puts get_line_equ(-1, 0)
puts get_line_equ(-1, -1)
puts get_line_equ(-1, 1)

puts get_line_equ(2, 0)
puts get_line_equ(2, -1)
puts get_line_equ(2, 1)

--output:--
I: f(x)=0
I: f(x)=-1
I: f(x)=1
I: f(x)=x
I: f(x)=x-1
I: f(x)=x+1
I: f(x)=-x
I: f(x)=-x-1
I: f(x)=-x+1
I: f(x)=2x
I: f(x)=2x-1
I: f(x)=2x+1

Better?

spoiler:

The final def is not as efficient as it could be: the first line should be removed and copied to each of the when branches--except for the first.

In response to comment:

def my_sprintf(str, *numbers)
  str.gsub(/% .*? [df]/x) do |match|  #Looks for %...d or %...f sequences
    puts match
  end
end

my_sprintf("The answer is: %+d or %+d", -2, 3)


--output:--
%+d
%+d

Next:

def my_sprintf(str, *numbers)

  str.gsub(/% .*? [df]/x) do |format_sequ|
    number_as_str = numbers.shift.to_s
    p number_as_str

    if format_sequ[1] == "+" and number_as_str[0] != "-"
      "+#{number_as_str}"
    else
      number_as_str
    end

  end
end

puts my_sprintf("The answer is: %+d or %+d.", -2, 3)

--output:--
"-2"
"3"
The answer is: -2 or +3.

Upvotes: 4

Cary Swoveland
Cary Swoveland

Reputation: 110755

Here's a more compact way to write your case statement. Recall that a <=> b => -1 if a < b, a <=> b => 0 if a == b and a <=> b => -1 if a > b.

"I: f(x)=" +
case [value_n_in_f <=> 0, value_m_in_f == 1]
when [ 1,false] then "#{value_m_in_f}x+#{value_n_in_f}"
when [ 0,false] then "#{value_m_in_f}x"
when [-1,false] then "#{value_m_in_f}x#{value_n_in_f}"
when [ 1,true]  then "x+#{value_n_in_f}"
when [ 0,true]  then "x"
when [-1,true]  then "x#{value_n_in_f}"
end

If you wish to demonstrate how the string is built, you could do something like this (with value_n_in_f and value_m_in_f renamed intercept and slope, respectively):

"I: f(x)=" +
case
when slope.zero?
  intercept.zero? ? "0" : "#{intercept}"
else
  case slope.to_f
  when  1.0 then ""
  when -1.0 then "-"
  else "#{slope}"
  end + "x" +
  case intercept <=> 0
  when  0 then ""
  when -1 then "#{intercept}"
  else "+#{intercept}"    
  end
end

Note that this permits slope < 0, which is not part of the specification. I tested this for various combinations of intercept and slope:

   intercept slope    string
       -2.1   4      I: f(x)=4x-2.1
       -2.1   -2.2   I: f(x)=-2.2x-2.1
       -2.1   0      I: f(x)=-2.1
       -2.1   0.0    I: f(x)=-2.1
       -2.1   -1     I: f(x)=-x-2.1
       -2.1   1.0    I: f(x)=x-2.1
       0      4      I: f(x)=4x
       0      -2.2   I: f(x)=-2.2x
       0      0      I: f(x)=0
       0      0.0    I: f(x)=0
       0      -1     I: f(x)=-x
       0      1.0    I: f(x)=x
       0.0    4      I: f(x)=4x
       0.0    -2.2   I: f(x)=-2.2x
       0.0    0      I: f(x)=0
       0.0    0.0    I: f(x)=0
       0.0    -1     I: f(x)=-x
       0.0    1.0    I: f(x)=x
       3      4      I: f(x)=4x+3
       3      -2.2   I: f(x)=-2.2x+3
       3      0      I: f(x)=3
       3      0.0    I: f(x)=3
       3      -1     I: f(x)=-x+3
       3      1.0    I: f(x)=x+3

Upvotes: 4

Related Questions