Logical Reasoning and Problem Solving With Ruby-Kickstarter

Abi Travers
6 min readJul 26, 2017

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’ , :x # => [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. So I changed it:

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. So:

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.

(This was originally posted on my blog : http://lebrunblack.com/index.php/2017/07/15/ruby-challenges/)

--

--