# Binomial Expansion
# https://www.codewars.com/kata/540d0fdd3b6532e5c3000b5b

def get_the_terms(expression)
  return expression.scan(/\(([+-]*\d*)([a-z]*)([+-]*\d*)([a-z]*)\)\^(\d*)/).flatten
end

def correct_coeficient(coef)
  if coef.empty?
    return 1
  elsif coef == "-"
    return -1
  else
    return coef.to_i
  end
end

def factorial(num)
  (1..num).inject(1){ |prod, i| prod * i }
end

def get_combination(num1, num2)
  factorial(num1) / (factorial(num2) * factorial(num1 - num2))
end

def var_to_power(var, power)
  if power == 0 || var.empty?
    return ""
  elsif power == 1
    return var
  else
    return "#{var}^#{power}"
  end
end

def coef_with_sign(coef, k)
  if k == 0
    if coef == 1
      return ""
    elsif coef == -1
      return "-"
    end
  else
    if coef > 0
      return "+#{coef}"
    end
  end
  return coef
end

def expand(expression)
  coefA, varA, coefB, varB, power = get_the_terms(expression)

  power = power.to_i
  return "1" if power == 0

  coefA = correct_coeficient(coefA)
  coefB = correct_coeficient(coefB)

  expansion_result = []

  (0..power).each do |k|

    coef = get_combination(power, k)

    power_of_varA = power-k
    power_of_varB = k

    coefA_to_power = coefA ** power_of_varA
    coefB_to_power = coefB ** power_of_varB

    coef = coef * coefA_to_power * coefB_to_power
    coef = coef_with_sign(coef, k)
    next if coef == 0

    varA_to_power = var_to_power(varA, power_of_varA)
    varB_to_power = var_to_power(varB, power_of_varB)

    expansion_result.push("#{coef}#{varA_to_power}#{varB_to_power}")
  end
  return expansion_result.join()
end

require "minitest/autorun"

class ExpandTest < Minitest::Test
  def test_it_resolves_binomial_expansion
    assert_equal "x^2+2x+1", expand("(x+1)^2")
    assert_equal "p^3-3p^2+3p-1", expand("(p-1)^3")
    assert_equal "64f^6+768f^5+3840f^4+10240f^3+15360f^2+12288f+4096", expand("(2f+4)^6")
    assert_equal "1", expand("(-2a-4)^0")
    assert_equal "144t^2-1032t+1849", expand("(-12t+43)^2")
    assert_equal "r^203", expand("(r+0)^203")
    assert_equal "x^2+2x+1", expand("(-x-1)^2")
    assert_equal "-8k^3-36k^2-54k-27", expand('(-2k-3)^3')
  end
end