# I worked on this challenge by myself.
# This challenge took me [#] hours.

# Pseudocode
=begin

INPUT: a number (positive integer)
OUTPUT: whether the number is part of the fibonacci sequence
STEPS:

A positive integer n is a Fibonacci number if and only if one or both of 
  5x^2 + 4 or 5x^2 - 4 is a perfect square 
(i.e. the square root of its result is an integer with no fractional remainder).

Calculate 5 times the given number and store value in result
Add 4 to the result and take the square root 
IF you get an integer from the previous operation
 the number is part of the Fibonacci sequence
ELSE
 Subtract 4 from the original result and take the square root
 IF you get an integer from the previous operation
   then the number is part of the Fibonacci sequence
 ENDIF
ENDIF

=end


# Initial Solution

# require 'bigdecimal'

# def is_fibonacci?(num)
# 	return true if num == 0 || num == 1

# 	# Create a BigDecimal to handle arbitrary precision
# 	n = BigDecimal.new(num)

# 	result = 5 * (n**2)
# 	# issue: Ruby will return a floating-point number from Math.sqrt, even if
# 	#        there is no decimal part (e.g. sqrt(4) = 2.0)
# 	# another issue: it seems there is an issue with precision, so for really
# 	#                big numbers, the approach using % 1 -- or checking whether the
# 	#                square of the answer will be equal to the square of the
# 	#                truncated answer -- will fail.
# 	positive_answer = (result + 4).sqrt(0)
# 	if positive_answer == positive_answer.round
# 		return true
# 	else
# 		# try the second expression
# 		negative_answer = (result - 4).sqrt(0)
# 		if negative_answer == negative_answer.round
# 			return true
# 		else
# 			# not part of the fibonacci sequence
# 			return false
# 		end
# 	end
# end


# Refactored Solution

require 'bigdecimal'

def is_fibonacci?(num)
	# If given either 0 or 1, confirm it is part of Fibonacci sequence right away
	return true if num == 0 || num == 1

	# Create a BigDecimal to handle arbitrary precision
	n = BigDecimal.new(num)

	positive_result = (5 * (n**2) + 4).sqrt(0)
	negative_result = (5 * (n**2) - 4).sqrt(0)

	return positive_result == positive_result.round || negative_result == negative_result.round

end


# Reflection
=begin

What concepts did you review or learn in this challenge?

	This challenge was all about math. I got to review the fibonacci sequence
	and learn how to determine whether a given number is part of the sequence
	using the square root of the result of the expressions 5x^2 + 4 and 5x^2 - 4.
	Given a number x, you calculate the expressions above and check whether the
	result is a perfect square. If any of the expressions yield a result whose
	square root is an integer number (without decimal), then the given number is
	part of the fibonacci sequence. 

What is still confusing to you about Ruby?

	So far, not much confusion about the language itself. The greatest challenge
	here was translating the pseudocode into actual code. I ran into many issues
	because of the way numbers are stored in a computer. If it were just a math
	problem by hand, then it would work easily. But it is not straightforward
	for the computer to determine whether a number is an actual integer number
	(vs the computer term Integer and Floats). 

	In Ruby, the result of Math.sqrt(4) is 2.0. This is a floating point number
	and even though we might consider it in pure math to be an integer, for
	Ruby it is a float. So using is_a? Integer totally failed because the value
	is stored as a float. After that issue, I started to look for ways to determine
	whether a number had some decimal value other than 0. I found out that
	taking a number and modulo-ing it with 1 gives out the decimal part, although
	not very accurately:

		irb(main):001:0> 123213123123213 % 1 
		=> 0
		irb(main):002:0> 123213123123213.2313213 % 1 
		=> 0.234375

	I tried that, but for really big numbers, like num = 8670007398507948658051921,
	my RSpec test failed. So there was something funny about the precision of
	the numbers and how they are stored in a computer. It can never be exact:
	the numbers stored in a computer are just an approximation of the actual
	number. So somehow, for really big numbers, the decimal part just became zero
	after doing an operation like % 1:

		irb(main):003:0> 123213123112312131131323213.2313213 % 1 
		=> 0.0

	So there goes my approach. Failed again. The solution I found was using a
	BigDecimal. For that, I had to require it using

		require 'bigdecimal'

	and then converting the given number to that, so I could have access to all
	its functionalities:

		n = BigDecimal.new(num)

	BigDecimal has arbritary precision, so there was no problem using really
	big numbers. I ended up testing whether the result of the expressions after
	taking the square root matched their rounded counterpart (so there would be
	no decimal part in case of an actual integer number and thus the numbers
	would be the same):

		return positive_result == positive_result.round || negative_result == negative_result.round

What are you going to study to get more prepared for Phase 1?

	I am going to review my notes and try out some bonus challenges.

=end
