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: