Categories
Code challenges Programming

30 Days of Code #4

In which I give my brain a break and the solution appears like magic. Plus a rubocop-based refactor.

I finished up the problem from yesterday that I couldn’t solve by starting out reviewing the problem one more time, the notes I made from the day before, and starting to fix things. My hunch from yesterday was correct: for the rounding up #ceil method to work properly, I needed to make sure my numbers were roundable in the first place. They needed to be changed to floats with a little #to_f method. This was the heart of the problem.

Then I gave myself a new mini-challenge that, of course, ended up taking a lot longer than I thought: rubocop.

First I picked off the “low hanging fruit” and removed the trailing whitespace, etc. I got it down to three “Method has too many lines” offenses. For times’ sake, I decided to just tackle one of these today.

This:

  def normalize_ciphertext
    word_size = (normalize_plaintext.size / size).ceil
    number_of_lines = (normalize_plaintext.size / word_size).ceil

    results = []
    old_text = ciphertext
    number_of_lines.downto(1) do |line|
      if line == 1
        results.push(old_text)
      elsif line > 1
        word_size = old_text/number_of_lines if old_text % number_of_lines == 0
        results.push(old_text.slice!(0..(word_size - 1)))
      end
    end
    results.join(' ')
  end

Became this:

def remove_front_letters(arr, text, word_size)
  arr.push(text.slice!(0..(word_size - 1)))
end  

def create_words_array(word_size, number_of_lines)
  arr = []
  text = ciphertext

  number_of_lines.downto(1) do |line|
    word_size = text.size / line if text.size % line == 0
    line == 1 ? arr.push(text) : remove_front_letters(arr, text, word_size)
  end

  arr
end

def normalize_ciphertext
  word_size = (normalize_plaintext.size.to_f / size).ceil
  number_of_lines = (normalize_plaintext.size.to_f / word_size).ceil
  create_words_array(word_size, number_of_lines).join(' ')
end

Still not perfect, but at least Rubocop likes it. It is still a little too much happening in every method. It would be better to pull out more lines of code and make new helper methods, like calculate_word_size, perhaps. Gosh darn it, might as well try it:

  def remove_front_letters(arr, text, word_size)
    arr.push(text.slice!(0..(word_size - 1)))
  end

  def calculate_word_size
    (normalize_plaintext.size.to_f / size).ceil
  end

  def calculate_number_of_lines(word_size)
    (normalize_plaintext.size.to_f / word_size).ceil
  end

  def create_words_array
    arr = []
    text = ciphertext
    word_size = calculate_word_size
    number_of_lines = calculate_number_of_lines(word_size)

    number_of_lines.downto(1) do |line|
      word_size = text.size / line if text.size % line == 0
      line == 1 ? arr.push(text) : remove_front_letters(arr, text, word_size)
    end

    arr
  end

  def normalize_ciphertext
    create_words_array.join(' ')
  end