Talking Through a Logical Ruby Challenge

Posted on Posted in Ruby, Software Engineering

As part of the Makers Academy  pre-course week 2 we have been tasked with working through the Ruby-Kickstarter github tutorials by Josh Cheek.

I decided to go through my thought process on one of the challenges I got stuck on, 1:6, in the hope that this may help me discover the solution. This post is about how I went about trying to understand the challenge and what I am still confused about. I have ordered this post as the way I looked at the information, worked through it in a lineal time format.

So hold tight as we ride through the waves of my mind … and apologizes if i stray off on a visual tangent ..

 

Question Asked:

 

You'll get a string and a boolean.

When the boolean is true, return a new string containing all the odd characters.

When the boolean is false, return a new string containing all the even characters.

If you have no idea where to begin, remember to check out the cheatsheets for string and logic/control

# odds_and_evens("abcdefg",true)    # => "bdf"

# odds_and_evens("abcdefg",false)   # => "aceg"

 

So two things that are seemingly unrelated are now bound together by a method I am to create …

My solution:

def odds_and_evens(string, return_odds)

  if return_odds

   string.size.times do |n|

   next if n % 2 == 0

   print 'n'

  end

   else

    string.size.times do |n|

    next if n % 2 != 0

   print 'n'

  end

end




odds_and_evens("abcdefg",true)

odds_and_evens("abcdefg",false)

Initial Issues:

  1. I don’t understand why this does not ‘print’ the answer to the screen when I call the method odds_and_evens(“abcdefg”,true).
  2. When I run the rake test on the file I get the following error messages.:

 

syntax error, unexpected end-of-input, expecting keyword_end

rake aborted!

Command failed with status (1):

 

The Given Solution:

 

def odds_and_evens(string, return_odds)

to_return = ""

string.size.times do |index|

next if return_odds && index.even?

next if !return_odds && index.odd?

to_return << string[index]

end

to_return

end

 

My thought process, the steps it went through:

We want to design a method which takes two arguments, one is a string of characters the other is a true or false statement.

The first step is therefore to create this method name it ‘odds_and_evens’ and pass it two arguments ‘string’ and ‘return_odds’.

def odds_and_evens(string, return_odds)

We want this method to return the string, given to it, in an altered way.

We need some mechanism to return the string at the end.

We will have to split this string into an array of it’s characters in order to count which index number each character sits at. So we need something which converts it back to a string.

By putting a variable set as ‘to_retrun’ then assigning it a value of an empty string we can then push the characters of the original string which has passed through our if argument, back into it.

to_return = ""
to_return << string[index]

We want it to split up this string into its characters. So the string is now an array of it’s characters.

 

The index number of the character in a string is what will determine if it is odd or even. Index numbering starts at 0. All the characters with an odd index number are add, all the characters with an even index number are even.

The method .size returns the character length of a string.

string.size

.times do is a loop. What this does is say ‘for’ a certain amount of times (we have assigned this number with the .size method) ‘do’ the following block of code.

string.size.times do |index|

What I am still confused about here:

Does .times do or .size split a string into an array? I Have tried to look for this answer but cannot find it.

Potential answer:

We not need to split the string into its characters, do we simply need to assign a number to each character in the string depending on it’s place and act on those numbers … drawing the string back according to those numbers.

We need to do something different to the string depending on weather the returns_odd variable, is true or false.

We need an if statement which looks at the returns_odd varaibale and the split string. We need a Boolean here.

&& index.even?
&& index.odd?

If it is true then we need to return only the characters at the odd index number.

If returns_odd is not an object, i.e. it is false, we need to return only the characters at the even index numbering.

The string is passed through the loop block of code.

string.size.times do |index|

next if return_odds && index.even?

next if !return_odds && index.odd?

The name  ‘index’ is given to the block of code as a placeholder for every character in the string. So on the first loop around the code it represents the character at index 0, then on the next, the character at index 1 and so on.

The block of code then assesses if the character which is now the ‘index’ has an odd or even index number.

 

I need to go through the loop again:

When the string is split up into its characters, an index number is assigned to each character according to it’s original string, starting with 0:

string.size.times do |index|

next if return_odds && index.even?

next if !return_odds && index.odd?

 

So for size(the arrays’ length or size) number of times each character is assigned to the ‘index’ placeholder.

The character at the ‘index’ placeholder is then put through the argument;

Is the returns_odd object true? If so pass over all those characters whose index number is even.

If retruns_odd is not an object, give me back all the characters which appear at an even index number. Do not give me back any characters which have been assigned an odd index number.

At the moment these characters are still an index number.

We need to return the string which has been through the the argument.

We push this new ‘string’  into the empty string variable we set at the beginning.

to_return << string[index]

The string is now an array which has the elements assigned to ‘index’. As it is displayed as string[index].

 

Walking through this solution in depth, explaining the coding solution to myself in english has allowed me to really understand what is going on with it. As a beginner looking at a seemingly difficult logical problem can seem very daunting if you don’t understand what it is saying. I highly recommend talking, (or writing), yourself through some code. It helped to understand the logic and hopefully apply it in future. Ruby seems like a game of cards, or musical instrument, the more you play the better you get but this only comes with practice …

(Apologize to those who are simply trying to learn ruby and are not interested in the shameless plug of my photographs).

 

Leave a Reply

Your email address will not be published. Required fields are marked *