App Academy Prep Training - Women Who Code.
51672 What you need to know to work on this set:
arr – get the first item of the array arr
2. Nested indexing in two dimensional arrays:
arr – if in arr the  is also an array (you have a two-dimentional array), then you access it’s items like this: arr. The expanded form of arr is:

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

2 dimensional arrays of strings work like this:

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

3. while true and break
We use “break” to exit a loop prematurely (usually while true loops), usually depending of some if condition.
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
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

#### 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

#### 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
```

#### Takeaway:

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

## 3. Longest Word in a String

#### 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
```

#### Takeaway:

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

## 4. Sum Nums

#### 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.

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

## 5. Time Conversion

#### 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
```

## 7. Palindrome

#### 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!

#### 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.
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”

#### 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
```

#### 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

#### 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
```

## 10. Is Power of 2?

#### 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
```

## 11. Third Greatest

#### 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
```

## 12. Most Common Letter

#### 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
```

## 13. Dasherize Number

#### 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
```

## 14. Capitalize Words

#### Capitalize Words (A/a's Solution):

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

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

word = word.upcase

idx += 1
end

return words.join(" ")
end
```

## 15. Scramble String

#### 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
```

## 16. Is Prime?

#### 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
```

## 17. Nth Prime

#### 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
```

## 18. Longest Palindrome

#### 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

```

## 19. Greatest Common Factor

#### 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
```

## 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
```

## 21. Number of Repeated Letters

#### 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] == letter
counts[counts_idx] += 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
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}
```

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

## 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:

```