App Academy Prep Training - Women Who Code.
51672
post-template-default,single,single-post,postid-51672,single-format-standard,qode-core-1.0.1,ajax_fade,page_not_loaded,,capri child-child-ver-1.0.0,capri-ver-1.6, vertical_menu_with_scroll,smooth_scroll,grid_1200,blog_installed,wpb-js-composer js-comp-ver-4.12.1,vc_responsive
 

App Academy Prep Training

App Academy Prep Training

App Academy Practice Problems I
http://prepwork.appacademy.io/coding-test-1/practice-problems/

What you need to know to work on this set:
1. Access to array elements:
arr[0] — get the first item of the array arr
2. Nested indexing in two dimensional arrays:
arr[0][0] — if in arr[0] the [0] is also an array (you have a two-dimentional array), then you access it’s items like this: arr[0][0]. The expanded form of arr[0][0] is:

arr = [["item1", "item2"], "lastitem"]
external_array_item = arr[0] # get the first item of the external array
inner_array_item = external_array_item[0] # get the first item of the inner array

2 dimensional arrays of strings work like this:

arr = ["Aa", "Bb", "Cc"]
arr[0] # => "Aa"
arr[0][0] # => "A"
arr[1][0] # => "B"

3. while true and break
We use «break» to exit a loop prematurely (usually while true loops), usually depending of some if condition.
http://prepwork.appacademy.io/coding-test-1/introduction-to-programming-3/
Example: we want to execute a «while true» loop until it gives us the result we want (normally while true is infinite). So once we get the correct result, we want to stop the loop. We use break to stop the loop once we get the result we want.

while true
  input = gets.chomp
  if input == "GIZMO"
    break
  end

  puts("Try typing GIZMO again!")
end

puts("THANKS FOR TYPING GIZMO")

4. next

Hello friends,
If you are new to coding, and aim to master App Academy’s Problems and pass their interviews, this post will help you to practice.
For beginners understanding code and writing down own solutions can be a huge challenge. In fact, I think that some intermediate step should exist between reading the theory and actually writing code yourself. If you often find yourself stuck with writing solutions to App Academy problems, try to work through them with this post, that provides simple text description of general steps that your code should hanlde. This way, you can:
Match code pieces to text description
Get hints how to solve the problem instead of looking at the solution
On to practice!

General notes:

All problems use while loops (and their typical syntaxis)
Don’t forget all necessary elements of while loops (where to start, condition, step, end)
Don’t forget to state types of objects and their initial state
Don’t forget steps in the loops
Don’t forget to put end at the end of blocks
Don’t forget to return the result where necessary
Read the instructions very carefully.
Break your problem into the smallest steps possible, and methodically go through them.
Take a problem and don’t give up until it’s done.

1. Reverse String

Write a method that takes a string as input, and returns a new<br /> string with the same letters in reverse order. Don't use String's reverse method. Difficulty: easy.

Instructions:

Create an empty variable «reversed_string».
Write a loop that puts current elements in this empty string one-by-one in the reversed order 1 at a time starting from the last one.

Reverse String (A/a’s Solution):

def reverse(string)
    reversed_string = ""

  i = 0
  while i < string.length
    reversed_string = string[i] + reversed_string

    i += 1
  end

  return reversed_string
end

Reverse String Solution 2:

  # 1. we .split the string into an array of characters, ex.: ['c','a','t']
  # 2. we .reverse this array 
  # 3. we .join the reversed array back into a string 

def reverse(string)
return string.split('').reverse().join('');
end

Takeaway:

We can take string element string[i], add reversed string to it and have the loop adding each element to our variable in reversed order.
It will add each element to the beginning of the new string.

Q: why it adds elements to the beginning, not the end?

http://stackoverflow.com/questions/3057967/reverse-a-string-in-ruby
http://stackoverflow.com/questions/31171424/reversing-a-ruby-string-without-reverse-method

2. Factorial

Write a method that takes an integer `n` and returns n*(n-1)*(n-2)*...*2*1. Assume n >= 0. Special case: factorial(0) == 1. Difficulty: easy.

Instructions:

The Factorial of a non-negative integer n is the result of multiplying of all positive integers less than or equal to n:
5! = 5 * 4 * 3 * 2 * 1 = 120
0! = 1 (special case)
Identify the limits of function: write a statement that returns nil if n < 0 (that means the function doesn't work if n < 0). Start a loop with 1 and make it work down (multiply the result and substruct 1 to get the next number).

Factorial (A/a's Solution):

def factorial(n)
  if n < 0
    return nil
  end

  result = 1
  while n > 0
    result = result * n

    n -= 1
  end

  return result
end

Factorial (My Solution):


Takeaway:

How this code works:
n = 5
1
1 * 5 = 5
5 * 4 = 20
20 * 3 = 60
60 * 2 = 120

http://stackoverflow.com/questions/39883483/why-in-this-factorial-code-no-recursion-the-step-is-1-instead-of-1

3. Longest Word in a String

Write a method that takes a string and returns the longest word in the string. Assume that the string contains only letters and spaces. you can use the .split method. Difficulty: easy.

Instructions:

Break down the sentence into words and store this array in a new variable.
Create a variable that stores the longest word and set it to nothing.
Inside a loop set that variable equal to the current item of the loop.
Write a statement that makes the current item the longest word if it is empty, then iterates comparing each current item to the currently stored longest item and if the latter is longer, replaces the current longest word with it.
Your loop should take the current item, compare it with the longest word and make sure that the longest of them goes to the var on each round.

Longest Word (A/a's Solution):

def longest_word(sentence)
  words = sentence.split(" ")

  longest_word = nil

  word_idx = 0
  while word_idx < words.length
    current_word = words[word_idx]

    if longest_word == nil
      longest_word = current_word
    elsif longest_word.length < current_word.length
      longest_word = current_word
    end

    word_idx += 1
  end

  return longest_word
end

Longest Word (My Solution):


Takeaway:

"now is the time".split(' ') => ["now", "is", "the", "time"]

4. Sum Nums

Write a method that takes in an integer `num` and returns the sum of all integers between zero and num, up to and including `num`. Difficulty: easy.

Instructions:

Ex.: sum_num(5) = 5 + 4 + 3 + 2 + 1 = 15
Create a variable that will store the sum, set it to 0.
Write a loop that adds current number to the result.

Sum Nums (A/a's Solution):

def sum_nums(num)
  result = 0

  i = 0
  while i <= num
    result += i
    i += 1
  end

  return result
end

How the code works:

num = 5
0
0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15

Takeaway:

The loop is given a start number (0) and an end number (5) and sums all numbers in between with the step 1.
Результат (сумма чисел) прирастает на i (каждое следующее число), шаг - на 1.

Reading:

http://stackoverflow.com/questions/22818637/sum-array-of-numbers

5. Time Conversion

Write a method that will take in a number of minutes, and returns a string that formats this number into `hours:minutes` - 'x:xx'. Difficulty: easy.

Instructions:

Write a loop that adds 1 hour and substructs 60 mins on each step while mins are >= 60.
Write an if/else statement that turns resulting mins to a string and adds 0 before it if it is < 10. Get the whole string of hours and minutes in the x:xx format.

Time Conversion (A/a's Solution):

def time_conversion(minutes)
  hours = 0

  while minutes >= 60
    hours += 1
    minutes -= 60
  end

  if minutes < 10
    minutes_s = "0" + minutes.to_s
  else
    minutes_s = minutes.to_s
  end

  return hours.to_s + ":" + minutes_s
end

Time Conversion Solution 2:

def time_conversion(minutes)
return (minutes / 60).to_s + ":" + (minutes % 60).to_s
end
puts time_conversion(15)
puts time_conversion(150)
puts time_conversion(360)

# => 0:15
# => 2:30
# => 6:0

This one-liner returns time, but withought additional 0s before hours and after mins when they are < 10.

Takeaway:

Here we use a loop to convert units of measurement from one to another and also get the reminder without using %.

6. Count Vowels

Count Vowels (A/a's Solution):

def count_vowels(string)
  num_vowels = 0

  i = 0
  while i < string.length
    if (string[i] == "a" || string[i] == "e" || string[i] == "i" || string[i] == "o" || string[i] == "u")
      num_vowels += 1
    end

    i += 1
  end

  return num_vowels
end

Count Vowels (My Solution):


Takeaway:

7. Palindrome

Write a method that takes a string and returns true if it is a palindrome. A palindrome is a string that is the same whether written backward or forward. Assume that there are no spaces; only lowercase letters will be given. Difficulty: easy.

Instructions:

Write a loop that checks if a pair of first and last letters are equal, moving inward and returns false if not.
In other words: take the 1st item, compare to the last item, return true if false, take next 1st and last items to compare, proceed.
The tricky part is the expression for the last item of the string.

Palindrome (A/a's Solution):

def palindrome?(string)
  i = 0
  while i < string.length
    if string[i] != string[(string.length - 1) - i]
      return false
    end

    i += 1
  end

  return true
end

How the code works:

string = hzgmlgzh
h vs h => equal, proceed
z vs z => equal, proceed
q vs q => equal, proceed
m vs l => false => not a palindrome!

Palindrome (My Solution):


Takeaway:

We can use an expression string[(string.length - 1) - i] to point at the last item of a string and switch it to the next left one on each step.
Additional reading:
http://stackoverflow.com/questions/29183294/trouble-to-understand-why-this-palindrome-method-works

8. Nearby AZ

Write a method that takes an array of numbers. If a pair of numbers in the array sums to zero, return the positions of those two numbers. If no pair of numbers sums to zero, return `nil`. Difficulty: medium.

It separates loops in seeking string[idx] == “a” and string[idx] == “z”.
Next syntax: If string[idx] != “a” then jump out of the loop and move on. This skips looking for “z” when string[idx] != “a”
while (idx2 < string.length) && (idx2 <= idx1 + 3) – > This is a cleaner way of asking the follow up questions. If the string doesn’t go any longer, it’s smarter to not ask if that blank space is “z”.
Another note is that we need to list idx += 1 twice in this method because the next breaks us out. If we don’t do it outside of the next sub-loop, then we get an infinite loop.
idx2 then loops through the next 3 letters to check to see if they are “z”

Additional reading:
http://stackoverflow.com/questions/39408634/ruby-app-academy-practice-exercise-about-condition-in-while-loop

Nearby AZ (A/a's Solution):

def nearby_az(string)
  idx1 = 0
  while idx1 < string.length
    if string[idx1] != "a"
      idx1 += 1
      next
    end

    idx2 = idx1 + 1
    while (idx2 < string.length) && (idx2 <= idx1 + 3)
      if string[idx2] == "z"
        return true
      end

      idx2 += 1
    end

    idx1 += 1
  end

  return false
end

Nearby AZ (My Solution):


Takeaway:

Here we use to loops because we are looking for 2 things at the same time in the same string.
The "next" word is used to skip over some steps of the loop.

9. Two Sum

Write a method that takes an array of numbers. If a pair of numbers in the array sums to zero, return the positions of those two numbers. If no pair of numbers sums to zero, return `nil`. Difficulty: medium.

Two Sum (A/a's Solution):

def two_sum(nums)
  idx1 = 0
  while idx1 < nums.length
    idx2 = idx1 + 1
    while idx2 < nums.length
      if nums[idx1] + nums[idx2] == 0
        return [idx1, idx2]
      end

      idx2 += 1
    end

    idx1 += 1
  end

  return nil
end

Two Sum (My Solution):


Takeaway:

10. Is Power of 2?

Write a method that takes in a number and returns true if it is a power of 2. Otherwise, return false. You may want to use the `%` modulo operation. `5 % 2` returns the remainder when dividing 5 by 2; therefore, `5 % 2 == 1`. In the case of `6 % 2`, since 2 evenly divides 6 with no remainder, `6 % 2 == 0`. Difficulty: medium.

Is Power of 2? (A/a's Solution):

def is_power_of_two?(num)
  if num < 1
    return false
  end

  while true
    if num == 1
      return true
    elsif num % 2 == 0
      num = num / 2
    else
      return false
    end
  end
end

Is Power of 2? (My Solution):


Takeaway:

11. Third Greatest

Write a method that takes an array of numbers in. Your method should return the third greatest number in the array. You may assume that the array has at least three numbers in it. Difficulty: medium.

Third Greatest (A/a's Solution):

def third_greatest(nums)
  first = nil
  second = nil
  third = nil

  idx = 0
  while idx < nums.length
    value = nums[idx]
    if first == nil || value > first
      third = second
      second = first
      first = value
    elsif second == nil || value > second
      third = second
      second = value
    elsif third == nil || value > third
      third = value
    end

    idx += 1
  end

  return third
end

Third Greatest (My Solution):


Takeaway:

12. Most Common Letter

Write a method that takes in a string. Your method should return the most common letter in the string, and a count of how many times it appears. Difficulty: medium.

Most Common Letter (A/a's Solution):

def most_common_letter(string)
  most_common_letter = nil
  most_common_letter_count = nil

  idx1 = 0
  while idx1 < string.length
    letter = string[idx1]
    count = 0

    idx2 = 0
    while idx2 < string.length
      if string[idx2] == letter
        count += 1
      end
      idx2 += 1
    end

    if (most_common_letter_count == nil) || (count > most_common_letter_count)
      most_common_letter = letter
      most_common_letter_count = count
    end

    idx1 += 1
  end

  return [most_common_letter, most_common_letter_count]
end

Most Common Letter (My Solution):


Takeaway:

13. Dasherize Number

Write a method that takes in a number and returns a string, placing a single dash before and after each odd digit. There is one exception: don't start or end the string with a dash. You may wish to use the `%` modulo operation; you can see if a number is even if it has zero remainder when divided by two. Difficulty: medium.

Dasherize Number (A/a's Solution):

def dasherize_number(num)
  num_s = num.to_s

  result = ""

  idx = 0
  while idx < num_s.length
    digit = num_s[idx].to_i

    if (idx > 0)
      prev_digit = num_s[idx - 1].to_i
      if (prev_digit % 2 == 1) || (digit % 2 == 1)
        result += "-"
      end
    end
    result += num_s[idx]

    idx += 1
  end

  return result
end

Dasherize Number (My Solution):


Takeaway:

14. Capitalize Words

Write a method that takes in a string of lowercase letters and spaces, producing a new string that capitalizes the first letter of each word. You'll want to use the `split` and `join` methods. Also, the .upcase string method, which converts a string to all upper case will be helpful. Difficulty: medium.

Capitalize Words (A/a's Solution):

def capitalize_words(string)
  words = string.split(" ")

  idx = 0
  while idx < words.length
    word = words[idx]

    word[0] = word[0].upcase

    idx += 1
  end

  return words.join(" ")
end

Capitalize Words (My Solution):


Takeaway:

15. Scramble String

Write a method that takes in a string and an array of indices in the string. Produce a new string, which contains letters from the input string in the order specified by the indices of the array of indices. Difficulty: medium.

Scramble String (A/a's Solution):

def scramble_string(string, positions)
  result = ""

  i = 0
  while i < positions.length
    result = result + string[positions[i]]
    i += 1
  end

  return result
end

Scramble String (My Solution):


Takeaway:

16. Is Prime?

Write a method that takes in an integer (greater than one) and returns true if it is prime; otherwise return false. You may want to use the `%` modulo operation. `5 % 2` returns the remainder when dividing 5 by 2; therefore, `5 % 2 == 1`. In the case of `6 % 2`, since 2 evenly divides 6 with no remainder, `6 % 2 == 0`. More generally, if `m` and `n` are integers, `m % n == 0` if and only if `n` divides `m` evenly. You would not be expected to already know about modulo for the challenge. Difficulty: medium.

Is Prime? (A/a's Solution):

def is_prime?(number)
  if number <= 1
    # only numbers > 1 can be prime.
    return false
  end

  idx = 2
  while idx < number
    if (number % idx) == 0
      return false
    end

    idx += 1
  end

  return true
end

Is Prime? (My Solution):


Takeaway:

17. Nth Prime

Write a method that returns the `n`th prime number. Recall that only numbers greater than 1 can be prime. Difficulty: medium.

Nth Prime (A/a's Solution):

def is_prime?(number)
  if number <= 1
    # only numbers > 1 can be prime.
    return false
  end

  idx = 2
  while idx < number
    if (number % idx) == 0
      return false
    end

    idx += 1
  end

  return true
end

def nth_prime(n)
  prime_num = 0

  i = 2
  while true
    if is_prime?(i)
      prime_num += 1
      if prime_num == n
        return i
      end
    end

    i += 1
  end
end

Nth Prime (My Solution):


Takeaway:

18. Longest Palindrome

Longest Palindrome (A/a's Solution):


Longest Palindrome (My Solution):

def palindrome?(string)
  i = 0
  while i < string.length
    if string[i] != string[(string.length - 1) - i]
      return false
    end

    i += 1
  end

  return true
end

def longest_palindrome(string)
  best_palindrome = nil

  idx1 = 0
  while idx1 < string.length
    length = 1
    while (idx1 + length) <= string.length
      substring = string.slice(idx1, length)

      if palindrome?(substring) && (best_palindrome == nil || substring.length > best_palindrome.length)
        best_palindrome = substring
      end

      length += 1
    end

    idx1 += 1
  end

  return best_palindrome
end

Takeaway:

19. Greatest Common Factor

Write a method that takes in two numbers. Return the greatest integer that evenly divides both numbers. You may wish to use the `%` modulo operation. Difficulty: medium.

Greatest Common Factor (A/a's Solution):

def greatest_common_factor(number1, number2)
  # start i at smaller of number1, number2
  i = nil
  if number1 <= number2
    i = number1
  else
    i = number2
  end

  while true
    if (number1 % i == 0) && (number2 % i == 0)
      return i
    end

    i -= 1
  end
end

Greatest Common Factor (My Solution):


Takeaway:

20. Caesar Cipher

Caesar Cipher (A/a's Solution):

def caesar_cipher(offset, string)
  words = string.split(" ")

  word_idx = 0
  while word_idx < words.length
    word = words[word_idx]

    letter_idx = 0
    while letter_idx < word.length
      char_i = word[letter_idx].ord - "a".ord

      new_char_i = (char_i + offset) % 26
      word[letter_idx] = ("a".ord + new_char_i).chr

      letter_idx += 1
    end

    word_idx += 1
  end

  return words.join(" ")
end

Caesar Cipher (My Solution):


Takeaway:

21. Number of Repeated Letters

Write a method that takes in a string and returns the number of letters that appear more than once in the string. Assume the string contains only lowercase letters. Count the number of letters that repeat, not the number of times they repeat in the string. Difficulty: hard.

Number of Repeated Letters (A/a's Solution):

def num_repeats(string)
  counts = []

  str_idx = 0
  while str_idx < string.length
    letter = string[str_idx]

    counts_idx = 0
    while counts_idx < counts.length
      if counts[counts_idx][0] == letter
        counts[counts_idx][1] += 1
        break
      end
      counts_idx += 1
    end

    if counts_idx == counts.length
      # didn't find this letter in the counts array; count it for the
      # first time
      counts.push([letter, 1])
    end

    str_idx += 1
  end

  num_repeats = 0
  counts_idx = 0
  while counts_idx < counts.length
    if counts[counts_idx][1] > 1
      num_repeats += 1
    end

    counts_idx += 1
  end

  return num_repeats
end

Number of Repeated Letters Solution 2 (previous a/a's?):

def num_repeats(array)
  repeats = 0

  idx1 = 0
  while idx1 < array.length
    is_repeat = false
    idx2 = 0
    while idx2 < array.length
      if array[idx1] != array[idx2]
        idx2 += 1
        next
      elsif idx2 < idx1
        # will have previously counted this repeat
        break
      elsif idx2 > idx1
        is_repeat = true
      end

      idx2 += 1
    end

    if is_repeat
      repeats += 1
    end

    idx1 += 1
  end

  return repeats
end

Number of Repeated Letters Solution 3:

'sldhelanlaskjkajksda'.each_char.group_by(&:itself).count{|_, v| v.length > 1}
# => 6

or

'sldhelanlaskjkajksda'.chars.group_by(&:itself).count{|_, v| v.length > 1}
# => 6

Here we use just 3 methods: .each_char (.chars), .group_by and .count. We say: group and count characters.
.group_by returns a hash, where key is a letter, value is an array of that letters:

'sldhelanlaskjkajksda'.char.group_by(&:itself) 
=> {"s"=>["s", "s", "s"], "l"=>["l", "l", "l"], "d"=>["d", "d"], "h"=>["h"], "e"=>["e"], "a"=>["a", "a", "a", "a"], "n"=>["n"], "k"=>["k", "k", "k"], "j"=>["j", "j"]}

How .group_by works:
.group_by { |obj| block } → a_hash
.group_by → an_enumerator
.group_by groups a collection by result of a block. It returns a hash where the keys are the evaluated result from the block and the values are arrays of elements in the collection that correspond to the key. If no block is given an enumerator is returned. In newer versions of Ruby (2.2.0+) the Kernel#itself method that returns the object it was called on was implemented, so the new notation group_by(&:itself) is similar to older version .group_by { |x| x }.

'sldhelanlaskjkajksda'.chars 

returns

=> ["s", "l", "d", "h", "e", "l", "a", "n", "l", "a", "s", "k", "j", "k", "a", "j", "k", "s", "d", "a"]

how .count method with block works:
count { |item| block } → int

ary = [1, 2, 4, 2]
ary.count { |x| x%2 == 0 } #=> 3

I can also count the number of repeats for each letter with a hash:

"qgeq3sdg13h5hjtgfgge".split("").each_with_object(Hash.new(0)) { |o, h| h[o] += 1 }
=> {"q"=>2, "g"=>5, "e"=>2, "3"=>2, "s"=>1, "d"=>1, "1"=>1, "h"=>2, "5"=>1, "j"=>1, "t"=>1, "f"=>1}

Reading:
Enumerable group_by
https://ruby-doc.org/core-2.2.3/Enumerable.html
Is there a short way to write `{|x| x}`?
http://stackoverflow.com/questions/16932711/is-there-a-short-way-to-write-x-x
Group by identity in Ruby
http://stackoverflow.com/questions/33887596/group-by-identity-in-ruby
How to find the number of times in which the symbol is duplicated in a string Ruby
http://stackoverflow.com/questions/40706430/how-to-find-the-number-of-times-in-which-the-symbol-is-duplicated-in-a-string-ru
count method
https://ruby-doc.org/core-2.2.0/Array.html#method-i-count
Count duplicate elements in ruby array (Ruby 1.9+)
https://coderwall.com/p/layvtw/count-duplicate-elements-in-ruby-array-ruby-1-9

Takeaway:

FizzBuzz

Write a method that takes in an array of numbers and prints them, replacing numbers divisible by 3 with Fizz, numbers divisible by 5 with Buzz, and number divisible by both 3 and 5 with FizzBuzz.

FizzBuzz (Solution 1):

def fizzbuzz(max=100)
  1.upto(max) do |n|
    fizz = (n % 3 == 0) ? 'Fizz' : nil
    buzz = (n % 5 == 0) ? 'Buzz' : nil
    yield (fizz || buzz) ? "#{fizz}#{buzz}" : n
  end
end

fizzbuzz { |fb| puts fb }

FizzBuzz (Solution 2):

def fizzbuzz(num)
  1.upto(num).each do |i| 
    if i % 3 == 0 && i % 5 == 0 
      p "FizzBuzz"
    elsif i % 5 == 0 
      p "Buzz"
    elsif i % 3 == 0 
      p "Fizz"
    else
      p i
    end
  end
end
puts fizzbuzz(50)

FizzBuzz (Solution 3):

(1..100).each{|n|p n%15==0?"FizzBuzz":n%5==0?"Buzz":n%3==0?"Fizz":n}

def fizzbuzz(max)
arr = []
(1..max).each do |n|
if ((n % 3 == 0) && (n % 5 == 0))
arr << "FizzBuzz" elsif (n % 3 == 0) arr << "Fizz" elsif (n % 5 == 0) arr << "Buzz" else arr << n end end return arr end puts fizzbuzz(50)

def fizzbuzz(max)
  arr = []
  (1..max).each do |n|
    text = ""
    if (n % 3 == 0)
      text << "Fizz"
    end
    if (n % 5 == 0)
      text << "Buzz"
    end
    if !((n % 3 == 0) || (n % 5 == 0))
      text = n
    end
    arr << text
  end
  return arr
end
puts fizzbuzz(50)
1.upto(100) do |i|
str = "fizz" if (i % 3).zero?
str = str ? "fizzbuzz" : 'buzz' if (i % 5).zero?
str = i unless str
puts str
end
1.upto(100) do |n|
  fizz = (n % 3 == 0) ? 'Fizz' : nil
  buzz = (n % 5 == 0) ? 'Buzz' : nil
  puts (fizz || buzz) ? "#{fizz}#{buzz}" : n
end

Takeaway:

No Comments

Post a Comment