Categories
Code challenges Programming

30 Days of Code #9

In which I help a Russian folk hero defeat a multi-headed dragon.

I love the real-life coding problems, but I also enjoy the occasional story-based problems. If I’m in a hurry, I don’t like reading everything, but today I had fun looking up the characters of Mighty Heroes, a 6 kyu Codewars problem.

By Ivan Bilibin – http://vcat-skaz.narod.ru/04skazky/skazky6.htm, Public Domain, https://commons.wikimedia.org/w/index.php?curid=459187

In today’s problem, Alyosha Popovich needs help defeating a multi-headed dragon called Zmey Gorynych. He has to figure out how many heads the dragon has so the Mage can help him cut them all off. While I don’t usually condone violence towards dragons, this particular dragon is not a normal dragon, but rather an evil spirit. Our hero learned this the hard way.

Every time he cuts off one head of the dragon, more heads grow. The multiplier stays the same, but the dragon’s body remembers the insult and shores up defenses. In fact, every time our hero makes a swipe, the dragon’s body remembers that previous amount of swipes and multiplies it by the new number of swipes.

So for every swipe, the number of heads reduces by 1, but increments by the multiplier times the remembered number of swipes times the new swipe number. If the dragon starts with 3 heads and the multiplier is 3, in the first swipe one head is cut off, but 3 multiply, leaving 3 – 1 + 3 * 1, which equals 5. The next swipe, one more head is cut but 6 multiply, because it is the second swipe (1 * 2), 5 – 1 + 3 * 1 * 2, which equals 10. The next swipe, one more head is cut but the anti-swipe defense is now (1 * 2 * 3), 10 – 1 + 3 * 3 * 2 * 1 = 27.

I solved this in two different ways, but essentially using the same algorithmic premise of reassigning the local variable heads to its new value every round, which is the return value of the equation.

Here is my first version. I incremented the value of swing until it surpassed the given value swings.

def count_of_heads(heads, n, swings)
  swing = 1
  until swing > swings
    s = (1..swing).reduce(:*)
    heads = heads - 1 + (n * s)
    swing += 1
  end
  heads
end

For my second version, I combined everything into one line. The same premise, just written differently. The #upto method plays the same role as my swing-incrementor above.

def count_of_heads(heads, n, swings)
  1.upto(swings) { |s| heads = heads - 1 + ((1..s).reduce(:*) * n) }
  heads
end

Plus, it seems easier to read. Hopefully, Alyosha Popovich thinks so.

By Unknown author – This file has been extracted from another file: Сильный богатырь Алёша Попович.jpg, Public Domain, https://commons.wikimedia.org/w/index.php?curid=35331226