Friday, August 1, 2014

Problem 95 - Ruby

After solving problem 56 in Linotte, I freed up Ruby, a language plenty of people have good things to say about but which I have only used in my life for solving the Project Euler problems for this challenge I have used it for. Problem 95 was a pretty fun problem, involving a lot of kind of neat techniques for making sure you find all "amicable chains" and trying to repeat as little computation as possible. Ruby was a pretty solid language for solving this problem, though my solution runs in a not-terribly fast time. I am deciding to be ok with this because I don't think Ruby is really the fastest of languages, and my run time is still within reasonable bounds. I may come back later and fix things up a bit, but for now the below solution works without being too flashy and runs in about 4min on my machine.

def divisorsum(x)
    ret = 1
    (2..x).each {|i|
        if (i * i > x)
            break
        end
        if (x % i == 0)
            ret += i + (x / i)
        end
    }
    return ret
end

amChainLength = Array.new(size = 1000001, obj = 0)
maxCLength = 0
ans = 0
(4..1000000).each {|i|
    chain = [i]
    nextElem = i
    while (nextElem < 1000000 and amChainLength[nextElem] == 0)
        nextElem = divisorsum(nextElem)
        if (chain.include? nextElem)
            atIndex = chain.index(nextElem)
            (0..(atIndex - 1)).each{ |ind|
                amChainLength[chain[ind]] = 1
            }
            subl = chain.length - atIndex
            minElem = nextElem
            (atIndex..(chain.length - 1)).each{ |ind|
                amChainLength[chain[ind]] = 1
                minElem = [minElem, chain[ind]].min
            }
            if (subl > maxCLength)
                maxCLength = subl
                ans = minElem
            end
        elsif (nextElem > 1000000)
            chain.each {|elem| amChainLength[elem] = 1}
        end
      
        chain <<= nextElem
    end
    # If we hit something that made us end prematurely:
    if (amChainLength[i] == 0)
        chain.each {|elem| amChainLength[elem] = 1}
    end
}
printf("%d\n", ans)



No comments:

Post a Comment