Logical Reasoning and Problem Solving With Ruby-Kickstarter

Posted on Posted in Ruby, Software Engineering

For those of you who aren’t regular readers of my blog, aka everyone but my mum and dad, allow me to set the scene:

I have enrolled on the intensive computer programming bootcamp at the Makers Academy. Before starting the full-time, on-campus, course you complete 4 weeks of pre-course. In this 4 weeks you get a real feel of how coders go about problem solving while learning some of the basics of Ruby, git & command line.

On week two we are given the choice of working through one of two Ruby tutorials:

Chris Pines Book, Learn to Programme. Chapter 8–End (since we did up to 8 for the interview).

Josh Cheeks Ruby Kickstarter, Session 1–3

Reading the reviews I saw past students had said the Kickstarter was more challenging and had video tutorials, so I decided I would go with that one.

I am not going to lie, I found it very challenging. Having got stuck on many of the challenges throughout sessions 1, 2 and 3 I thought I would write a post on one I am still struggling on, to show how I worked through this problem and hopefully expose where I am still going wrong.

Cue Session 3:2.

The Challenge:

Given a nonnegative integer, return a hash whose keys are all the odd nonnegative integers up to it and each key’s value is an array containing all the even non negative integers up to it.

Examples:

staircase 1 # => {1 => []}
staircase 2 # => {1 => []}
staircase 3 # => {1 => [], 3 => [2]}
staircase 4 # => {1 => [], 3 => [2]}
staircase 5 # => {1 => [], 3 => [2], 5 =>[2, 4]}

My Solution

How I broke the problem down and tried to solve the challenge. The steps I took:

Breaking the challenge down into smaller more manageable pieces:

Step 1

Check out possible examples and theory which may help, using ruby documents on hashes, google and Josh Cheeks cheatsheets:

The information I decided may be useful:

Hash.new { |this_hash, key| this_hash[key] = Array.new }
hash = Hash[ *[ Array(‘a’..’j’) , Array(1..10) ].transpose.flatten ] # populating
hash # => {“a”=>1, “b”=>2, “c”=>3, “d”=>4, “e”=>5, “f”=>6, “g”=>7, “h”=>8, “i”=>9, “j”=>10}
hash.values_at ‘j’ , ‘e’ , ‘i’ , 😡 # => [10, 5, 9, nil]

Step 2

Breaking the problem down into sudo code:

(nr_given)
integer_hash = [*[Array(starting from 0 increment numbers which   are odd up to the nr_given) , Array(starting from 0 increment numbers which are odd up to the nr_given).transpose.flattern]]
key array upto(nr_given)
value array up_to(nr_given) next if (i %2) != 0
#need to work out how to increment values and if up_to is method

Step 3

Deciding which bit to tackle first:

Incrementing the arrays seems like a good place to start as I can isolate my code for that part and test it with irb.

This was my first attempt:

Array(0..nr_given).map! {|x| puts x next if(x.even?)}

Next attempt:

Array(0..nr_given).map! {|x| if x.even? puts “x”}

Then:

Array(0..nr_given).map {|x| if x.even? puts “x”}

When I ran this in the irb it returned nothing even when I input a number, 77, in place of nr_given.

So I tried:

Array(0..nr_given).select do |x|
  if x.even?
end

When I run these in irb I still get no output even when I put a number in ‘nr_given’. I thought it may be something wrong with the way I created a new array so I tried to fix that:

a = *(1..77)

and that worked.

Then I tried setting a to that array. Checking it was definitely set by typing in a again, then playing with the .select method.

a.select { |x| return x if (x%2)==0 }

I got the following error:

unexpected return
from (irb):8:in `block in irb_binding’
from (irb):8:in `select’
from (irb):8

I looked up the select method in Ruby docs and it states the following:

[1,2,3,4,5].select { |num| num.even? } #=> [2, 4]

I therefore changed my code to:

#keys are:
a = *(0..nr_given)
a.select {|x| x.odd?}
And tested it doing:
a = *(0..77)
a.select {|x| x.odd?}

And it worked!! I changed it to a shorter version and checked that also worked:

a = *(0..77).select {|x| x.odd?}

Step 4

Joining these to the rest of the code to solve the whole challenge.

My first attempt to put these arrays into the rest of my code:

def staircase(nr_given)
integer_hash = [*[*(0..nr_given).select {|x| x.odd?} , *(0..nr_given).select {|x| x.even?}.transpose.flattern]]
end

This failed the rake test. I got the following error message from it:

Failure/Error: expect(method :staircase).to be
NameError:
undefined method `staircase’ for class

So I referred back to my notes on how to set a hash out :

character_counts = Hash.new { |this_hash, key| this_hash[key] = 0 }
character_counts[“a”] # => 0
character_counts # => {“a”=>0}

Looking at this I changed my code to:

def staircase(nr_given)
   return_hash = Hash.new
   *(0..nr_given).select {|x| x.odd?}
   return_hash[x] = *(0..nr_given).select {|x| x.even?}.transpose.flattern
   end
 end
return_hash
end

It failed the rake test so I decided the get rid of the part I didn’t feel was necessary ‘.transpose.flattern’.

def staircase(nr_given)
   return_hash = Hash.new
   *(0..nr_given).select {|x| x.odd?}
   return_hash[x] = *(0..nr_given).select {|x| x.even?}
   end
 end
return_hash
end

This was still failing on the line starting with ‘*’. So I changed this round a bit:

def staircase(nr_given)
   return_hash = Hash.new
   (0..nr_given).to_a.select {|x| x.odd?}
   return_hash[x] = (0..nr_given).to_a.select {|x| x.even?}
  end
 end
return_hash
end

I realised I was missing an if statement in the .select method:

def staircase(nr_given)
   return_hash = Hash.new
   (0..nr_given).to_a.select {|x| if x.odd?}
   return_hash[x] = (0..nr_given).to_a.select {|x| x.even?}
  end
 end
return_hash
end

I was getting an error because I had closed the statement off too early . The ‘}’ after the odd meant that it was not finishing off the if statement. It was not putting this newly created array into the return_hash[x] — the keys of the hash. This statement could not accept the x as I had closed off the select method too early. I was saying if x.odd? then not telling it what to do with x.

def staircase(nr_given)
   return_hash = Hash.new
   (0..nr_given).to_a.select do |x|
   if x.odd?
   return_hash[x] = (0..nr_given).to_a.select {|x| x.even?}
   end
  end
return_hash
end

I was now getting an error about the .select method. I noticed a few errors here, first I had forgotten to ask if the x was even then I had forgotten to tell it to return the value if it was.

def staircase(nr_given)
   return_hash = Hash.new
  (0..nr_given).to_a.select do |x|
  if x.odd?
  return_hash[x] = (0..nr_given).to_a.select {|x| return x if   x.even?}
  end
 end
return_hash
end

This is still failing. If anyone reading this can see where I am going wrong I would love to hear from you.

For now, I am parking this to move onto the next challenge in the hope a fresh head will shed some light on the problem and I will magically stumble upon the solution.

Leave a Reply

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