DEV Community

Discussion on: Code Challenge: Follow the Dirty Money

Collapse
 
rpalo profile image
Ryan Palo

I love whenever anybody posts challenges like this! Also, having the decimal separator be both . and , was tricksy.

require 'bigdecimal'  # Use decimals when money is involved
require 'json'
require 'net/http'
require 'set'

# Hunts down linked transactions without double-counting them
class TransactionFinder
  attr_reader :found

  def initialize(first_url)
    @pending = [first_url]
    @found = {
      # 'fd0d929f'... : '$1699,15'
    }
    @hit_uris = Set.new
  end

  def hunt
    until @pending.empty?
      current = @pending.pop
      next if @hit_uris.include?(current)
      @hit_uris.add(current)

      result = get(current)
      @found[result['id']] = result['content'].scan(/\$[0-9,.]+/).first
      @pending.concat(result['links'])
    end
  end

  def get(uri)
    result_string = Net::HTTP.get_response(URI(uri))
    result = JSON.parse(result_string.body)
  end

  def write_transactions(filename)
    File.open(filename, 'w') { |f| f.write(JSON.pretty_generate(@found)) }
  end

  def total
    @found.values.reduce(BigDecimal.new('0')) do |sum, current|
      dollars, cents = current.scan(/[0-9]+/)
      sum + BigDecimal.new("#{dollars}.#{cents}")
    end
  end
end

first_uri = 'https://gist.githubusercontent.com/jorinvo/6f68380dd07e5db3cf5fd48b2465bb04/raw/c02b1e0b45ecb2e54b36e4410d0631a66d474323/fd0d929f-966f-4d1a-89cd-feee5a1c5347.json'
t = TransactionFinder.new(first_uri)
t.hunt
t.write_transactions('data.json')
puts "$#{t.total.to_f}"

SPOILER

$9064.79