Skip to content

Instantly share code, notes, and snippets.

@eregon
Created September 28, 2010 19:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eregon/601607 to your computer and use it in GitHub Desktop.
Save eregon/601607 to your computer and use it in GitHub Desktop.
This is my solution to RPCFN #13: Economics 101
http://rubylearning.com/blog/2010/08/31/rpcfn-economics-101-13
I used 3 ways to solve it:
- using Hpricot and Nokogiri
- using RegExp
- parsing the questions (and even write them in pure Ruby (no String))
# 1 What is the population of the country with the most people? Yes, we know it’s China, but just how many people lived there in 1996?
# 2 What are the five countries with the highest inflation rates, and what were those rates in 1996?
# 3 What are the six continents in the file and which countries belong to which continent? Can you also produce them in alphabetical order?
# Idea: parse these sentences to make the search :p
require 'rubygems'
require 'hpricot'
doc = open('cia-1996.xml') { |f| Hpricot(f) }
# Countries without population (25/260)
# p countries.select { |country| country['population'].nil? }.map { |country| country['name'] }
# 1 What is the population of the country with the most people? Yes, we know it’s China, but just how many people lived there in 1996?
# China
# 1 210 004 956
countries = doc / :country # or doc.xpath('/cia/country')
china = countries.max_by { |country| country[:population].to_i }
puts china[:name]
puts china[:population].reverse.chars.each_slice(3).map(&:join).join(' ').reverse
puts
# 2 What are the five countries with the highest inflation rates, and what were those rates in 1996?
# {"Belarus"=>244.0, "Turkey"=>94.0, "Azerbaijan"=>85.0, "Malawi"=>83.3, "Yemen"=>71.3}
cc = countries.dup
p 5.times.inject({}) { |h,_|
c = cc.delete cc.max_by { |c| c[:inflation].to_f }
h[c[:name]] = c[:inflation].to_f
h
}
p countries.sort_by { |country| - country[:inflation].to_f }[0...5].inject({}) { |h,c| h[c[:name]] = c[:inflation].to_f and h }
puts
# 3 What are the six continents in the file and which countries belong to which continent? Can you also produce them in alphabetical order?
# ["Europe", "Asia", "North America", "Australia/Oceania", "South America", "Africa"]
p continents = (doc / :continent).map { |continent| continent[:name] }
puts
countries_by_continent = countries.inject(Hash.new { |h,k| h[k] = [] }) { |h,country|
h[country[:continent]] << country[:name]
h
}
p Hash[countries_by_continent.sort_by { |continent, countries| countries.sort and continent }]
# 1 What is the population of the country with the most people? Yes, we know it’s China, but just how many people lived there in 1996?
# 2 What are the five countries with the highest inflation rates, and what were those rates in 1996?
# 3 What are the six continents in the file and which countries belong to which continent? Can you also produce them in alphabetical order?
# Idea: parse these sentences to make the search :p
require 'nokogiri'
doc = Nokogiri open 'cia-1996.xml'
# Countries without population (25/260)
# p countries.select { |country| country['population'].nil? }.map { |country| country['name'] }
# 1 What is the population of the country with the most people? Yes, we know it’s China, but just how many people lived there in 1996?
# China
# 1 210 004 956
countries = (doc / :country)
china = countries.max_by { |country| country[:population].to_i }
puts china[:name]
puts china[:population].reverse.chars.each_slice(3).map(&:join).join(' ').reverse
puts
# 2 What are the five countries with the highest inflation rates, and what were those rates in 1996?
# {"Belarus"=>244.0, "Turkey"=>94.0, "Azerbaijan"=>85.0, "Malawi"=>83.3, "Yemen"=>71.3}
cc = countries.dup
p 5.times.with_object({}) { |_,h|
c = cc.delete cc.max_by { |c| c[:inflation].to_f }
h[c[:name]] = c[:inflation].to_f
}
p countries.sort_by { |country| - country[:inflation].to_f }[0...5].each_with_object({}) { |c,h| h[c[:name]] = c[:inflation].to_f }
#max = Float::INFINITY
#countries.inject([]) { |best, country|
#}
puts
# 3 What are the six continents in the file and which countries belong to which continent? Can you also produce them in alphabetical order?
# ["Europe", "Asia", "North America", "Australia/Oceania", "South America", "Africa"]
p continents = (doc / :continent).map { |continent| continent[:name] }
puts
countries_by_continent = countries.each_with_object(Hash.new { |h,k| h[k] = [] }) { |country,h|
h[country[:continent]] << country[:name]
}
#p Hash[countries_by_continent.sort_by { |continent, countries| countries.sort and continent }]
puts
p Hash[countries.group_by { |country| country[:continent] }.map { |continent,countries| [continent,countries.map { |c| c[:name] }] }.sort_by { |continent, countries| countries.sort and continent }]
# encoding: utf-8
# 1 What is the population of the country with the most people? Yes, we know it’s China, but just how many people lived there in 1996?
# 2 What are the five countries with the highest inflation rates, and what were those rates in 1996?
# 3 What are the six continents in the file and which countries belong to which continent? Can you also produce them in alphabetical order?
require 'nokogiri'
require 'ap'
class String
PLURALS = { "country" => "countries" }
NUMBERS = { "three" => 3, "four" => 4, "five" => 5 }
def singularize
PLURALS.key self
end
def convert
case self
when /\A-?\d+\z/; to_i
when /\A-?\d+\.\d+\z/; to_f
when /\A\d{2} \d{2} \d{4}\z/; Time.new *split.reverse
end
end
alias _to_i to_i
def to_i
NUMBERS[self] || _to_i
end
def === node
node[self]
end
def inspect
dup
end
end
class Time
def inspect
strftime('%d %B %Y')
end
end
class Integer
def inspect
to_s.reverse.chars.each_slice(3).map(&:join).join(' ').reverse
end
end
POS_SUPERLATIVES, NEG_SUPERLATIVES = %w[most biggest highest newest], %w[oldest]
SUPERLATIVES = (POS_SUPERLATIVES+NEG_SUPERLATIVES).join '|'
def read question, doc
puts question
case question
when /What is the (?<attribute>[\w ]+) of the (?<element>\w+) with the (?:#{SUPERLATIVES})/
attribute, element = $~[:attribute].tr(' ','_'), $~[:element]
best = (doc / element).grep(attribute).max_by { |e| e[attribute].convert }
puts best[:name]
ap best[attribute].convert
when /What are the (?<n>\w+) (?<elements>\w+) with the (?<sup>#{SUPERLATIVES}) (?<attribute>[\w ]+(?=\?)|\w+)/
n, elements, attribute = $~[:n], $~[:elements], $~[:attribute].tr(' ','_')
ap (doc / elements.singularize)
.grep(attribute)
.sort_by { |e| e[attribute].convert }
.tap { |a| a.reverse! if POS_SUPERLATIVES.include?($~[:sup]) }
.take(n.to_i)
.each_with_object({}) { |e,h| h[e[:name]] = e[attribute].convert }
when /What are the \w+ \w+ .+ which (?<elements>\w+) (belong to|has) which (?<group>\w+)/
_ = (doc / $~[:elements].singularize)
. grep($~[:group])
. each_with_object(Hash.new { |h,k| h[k] = [] }) { |e,h| h[e[$~[:group]]] << e[:name] }
_ = Hash[_.sort_by { |group, elements| elements.sort and group }] if question =~ /in alphabetical order/
_.each_pair { |group, elements|
puts " \e[34m#{group.inspect}:\e[0m #{elements.join ', '}"
}
end
puts
end
if __FILE__ == $0
doc = Nokogiri open 'cia-1996.xml'
read "What is the population of the country with the most people? Yes, we know it’s China, but just how many people lived there in 1996?", doc
read "What are the five countries with the highest inflation rates, and what were those rates in 1996?", doc
#read "What are the six continents in the file and which countries belong to which continent? Can you also produce them in alphabetical order?", doc
read "What is the total area of the country with the biggest territory?", doc
read "What is the infant mortality of the country with the highest infant mortality?", doc
read "What are the three countries with the highest population growth?", doc
read "What are the three countries with the newest indep date?", doc
read "What are the three countries with the oldest indep date?", doc
read "What are the five countries with the biggest gdp total?", doc
#read "What are the different governments and which countries has which government?", doc
end
# This heavily use method_missing to not have any String
require './parse'
class Question
def initialize(&block)
@question = []
instance_exec(&block)
end
def method_missing(meth, *args)
@question << meth
end
def to_s
@question.reverse.join ' '
end
def inspect
"#<Question: #{to_s}>"
end
def ask doc
read to_s, doc
end
end
def ask(&block)
Question.new(&block).ask(@doc)
end
@doc = Nokogiri open 'cia-1996.xml'
ask { What is the population of the country with the most people? }
ask { What are the five countries with the highest inflation rates }
ask { What are the six continents within the file _and which countries belong to which continent? }
doc = open 'cia-1996.xml', &:read
class Array
def to_h
Hash[self]
end
end
# 1 What is the population of the country with the most people? Yes, we know it’s China, but just how many people lived there in 1996?
puts doc.scan(/<country.+? name='(.+?)'.+? population='(\d+)'/m).max_by { |country, population| population.to_i }.join ' '
puts
# 2 What are the five countries with the highest inflation rates, and what were those rates in 1996?
# p countries.sort_by { |country| - country[:inflation].to_f }[0...5].map.with_object({}) { |c,h| h[c[:name]] = c[:inflation].to_f }
p doc.scan(/<country.+? name='(.+?)'.+? inflation='([\d.]+)'/m).sort_by { |country,inflation| -inflation.to_f }[0...5].to_h
puts
# 3 What are the six continents in the file and which countries belong to which continent? Can you also produce them in alphabetical order?
p doc.scan(/<country.+? continent='(.+?)'.+? name='(.+?)'/m)
.group_by(&:first)
.map { |continent,countries| [continent, countries.map(&:last)] }
.sort_by { |continent, countries| countries.sort and continent }.to_h
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment