Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 827ceea
Showing
42 changed files
with
1,309 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
This code was generated by James Edward Gray II and Edward Livengood (Team J-Ed-I) for the 2009 ICFP programming contest: | ||
|
||
http://icfpcontest.org/ | ||
|
||
We have participated in previous years with the help of our friends: | ||
|
||
http://grayproductions.net/icfp08/ | ||
http://grayproductions.net/icfp07/ | ||
http://grayproductions.net/icfp04/ | ||
|
||
We had pretty limited time this year and less help, so this solution only works for five of the provided scenarios. You can run those with these commands from the root project directory: | ||
|
||
bin/j_ed_i 1001 | ||
bin/j_ed_i 1002 | ||
bin/j_ed_i 1003 | ||
bin/j_ed_i 1004 | ||
bin/j_ed_i 2001 | ||
|
||
Each run generates images and solutions, in the so named directories. This code requires a Ruby 1.8 install (only tested with 1.8.6). | ||
|
||
You can also see movies we have recorded of the solutions in the videos directory. These are just animated Gif files that should be viewable in most modern browsers. The two without scenario number names are our best bloopers recorded from buggy runs. | ||
|
||
Though we had limited resources this year and didn't do too well, we had a great time and enjoyed the problem. Thanks you organizers for another great challenge! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#!/usr/bin/env ruby -wKU | ||
|
||
$LOAD_PATH << File.join(File.dirname(__FILE__), *%w[.. lib]) | ||
require "j_ed_i" | ||
|
||
options = {:configuarion => nil, :svg => true, :frequency => 500} | ||
ARGV.options do |opts| | ||
opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [OPTIONS] CONFIG" | ||
opts.separator "" | ||
opts.separator "Specific Options:" | ||
opts.on( "-s", "--[no-]svg", | ||
"Used to turn off image generation." ) do |svg| | ||
options[:svg] = svg | ||
end | ||
opts.on( "-f", "--frequency TURNS", Integer, | ||
"The turn frequency of image generation." ) do |frequency| | ||
if frequency < 1 | ||
options[:svg] = false | ||
else | ||
options[:frequency] = frequency | ||
end | ||
end | ||
opts.separator "Common Options:" | ||
opts.on( "-h", "--help", | ||
"Show this message." ) do | ||
puts opts | ||
exit | ||
end | ||
begin | ||
opts.parse! | ||
raise unless configuarion = ARGV.shift | ||
options[:configuarion] = configuarion.to_i | ||
rescue | ||
puts opts | ||
exit | ||
end | ||
end | ||
|
||
if options[:svg] and (JEdI::IMAGES_DIR + "0000000000.svg").exist? | ||
system("rm #{JEdI::IMAGES_DIR + '*.svg'}") | ||
end | ||
|
||
unless program_class = JEdI::Program.for_configuration(options[:configuarion]) | ||
abort "Error: CONFIG not recognized." | ||
end | ||
program = program_class.new(options[:configuarion], options) | ||
program.run | ||
puts "\aFinal Score: #{program.score}" |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#!/usr/bin/env ruby -wKU | ||
|
||
# standarad library | ||
require "pathname" | ||
require "optparse" | ||
|
||
module JEdI | ||
DIR = Pathname.new( File.join( File.dirname(__FILE__), | ||
".." ) ) | ||
PROBLEMS_DIR = DIR + "problems" | ||
SOLUTIONS_DIR = DIR + "solutions" | ||
IMAGES_DIR = DIR + "images" | ||
PROGRAM_DIR = JEdI::DIR.join(*%w[lib j_ed_i program]) | ||
|
||
TEAM_ID = 97 | ||
|
||
X_PORT = 2 | ||
Y_PORT = 3 | ||
CONFIGURATION_INPUT_PORT = 0x3E80 | ||
SCORE_OUTPUT_PORT = 0 | ||
FUEL_OUTPUT_PORT = 1 | ||
end | ||
|
||
# vendored | ||
require JEdI::DIR.join(*%w[vendor svg_image lib svg]) | ||
|
||
# our code | ||
require "j_ed_i/vm" | ||
require "j_ed_i/opcode" | ||
require "j_ed_i/radar" | ||
require "j_ed_i/program" | ||
JEdI::PROGRAM_DIR.each_entry do |program| | ||
require JEdI::PROGRAM_DIR + program if program.extname == ".rb" | ||
end | ||
require "j_ed_i/solution" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#!/usr/bin/env ruby -wKU | ||
|
||
module JEdI | ||
class Opcode | ||
attr_reader :r1 | ||
|
||
def execute(vm) | ||
send(self.class.const_get(:OPS)[@op], vm) | ||
end | ||
|
||
private | ||
|
||
def read(opcode, pattern) | ||
("%032b" % opcode.unpack("V")).unpack(pattern).map { |n| n.to_i(2) } | ||
end | ||
end | ||
|
||
class DTypeOpcode < Opcode | ||
OPS = [nil] + %w[add sub mult div output phi] | ||
|
||
def initialize(opcode) | ||
@op, @r1, @r2 = read(opcode, "a4a14a14") | ||
raise "Unexpected DType OP %p (%p)" % [@op, opcode] \ | ||
if not @op.between? 1, 6 | ||
end | ||
|
||
attr_reader :r2 | ||
|
||
private | ||
|
||
def add(vm) | ||
vm.data[@r1] + vm.data[@r2] | ||
end | ||
|
||
def sub(vm) | ||
vm.data[@r1] - vm.data[@r2] | ||
end | ||
|
||
def mult(vm) | ||
vm.data[@r1] * vm.data[@r2] | ||
end | ||
|
||
def div(vm) | ||
return 0.0 if vm.data[@r2] == 0.0 | ||
vm.data[@r1] / vm.data[@r2] | ||
end | ||
|
||
def output(vm) | ||
vm.write_output(@r1, vm.data[@r2]) | ||
nil # don't update data | ||
end | ||
|
||
def phi(vm) | ||
vm.data[vm.status? ? @r1 : @r2] | ||
end | ||
end | ||
|
||
class STypeOpcode < Opcode | ||
OPS = %w[noop cmpz sqrt copy input] | ||
IMMS = %w[< <= == >= >] | ||
|
||
def initialize(opcode) | ||
@op, @imm, @r1 = read(opcode, "x4a4a3x7a14") | ||
raise "Unexpected SType OP %p (%p)" % [@op, opcode] if @op > 4 | ||
raise "Unexpected SType IMM %p (%p)" % [@imm, opcode] \ | ||
if @op == 1 and @imm > 4 | ||
end | ||
|
||
private | ||
|
||
def noop(vm) | ||
nil # don't update data | ||
end | ||
|
||
def cmpz(vm) | ||
vm.status = vm.data[@r1].send(IMMS[@imm], 0.0) | ||
nil # don't update data | ||
end | ||
|
||
def sqrt(vm) | ||
Math.sqrt(vm.data[@r1].abs) | ||
end | ||
|
||
def copy(vm) | ||
vm.data[@r1] | ||
end | ||
|
||
def input(vm) | ||
vm.input_ports[@r1] | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/usr/bin/env ruby -wKU | ||
|
||
module JEdI | ||
class Program | ||
G = 6.67428 * 10 ** -11 | ||
M = 6 * 10 ** 24 | ||
GM = G * M | ||
|
||
def self.subclasses | ||
@subclasses ||= Array.new | ||
end | ||
|
||
def self.inherited(program) | ||
subclasses << program | ||
end | ||
|
||
def self.for_configuration(configuration) | ||
subclasses.find { |program| | ||
configuration / 1000 == program::CONFIGURATION | ||
} | ||
end | ||
|
||
def self.binary_path | ||
PROBLEMS_DIR + "bin#{const_get(:CONFIGURATION)}.obf" | ||
end | ||
|
||
def initialize(configuration, options = Hash.new) | ||
@vm = VM.new(self.class.binary_path, options) | ||
@configuration = configuration | ||
@score = nil | ||
@fuel = nil | ||
@x = nil | ||
@y = nil | ||
|
||
@initial_radius = nil | ||
@delta_v = nil | ||
@delta_v_prime = nil | ||
@time_to_prime = nil | ||
end | ||
|
||
attr_reader :score | ||
|
||
def run | ||
@vm.configure(@configuration) | ||
loop do | ||
@vm.loop | ||
update_satellite_statistics | ||
break if @score.nonzero? | ||
adjust_actuators | ||
@vm.update | ||
end | ||
@vm.finish | ||
end | ||
|
||
private | ||
|
||
def update_satellite_statistics | ||
@score = @vm.output_ports[SCORE_OUTPUT_PORT] | ||
@fuel = @vm.output_ports[FUEL_OUTPUT_PORT] | ||
@x = @vm.output_ports[X_PORT] | ||
@y = @vm.output_ports[Y_PORT] | ||
end | ||
|
||
def thrust(x, y) | ||
@vm.write_input(X_PORT, x) | ||
@vm.write_input(Y_PORT, y) | ||
end | ||
|
||
def calculate_hohmann_transfer | ||
return if @delta_v and @delta_v_prime | ||
|
||
@initial_radius = Math.sqrt(@x ** 2 + @y ** 2) | ||
|
||
@delta_v = Math.sqrt(GM / @initial_radius) * | ||
( Math.sqrt( 2 * @target_radius / | ||
(@initial_radius + @target_radius) ) - 1 ) | ||
@delta_v_prime = Math.sqrt(GM / @target_radius) * | ||
( 1 - Math.sqrt( 2 * @initial_radius / | ||
(@initial_radius + @target_radius) ) ) | ||
@time_to_prime = ( Math::PI * | ||
Math.sqrt( (@initial_radius + @target_radius) ** 3 / | ||
(8 * GM) ) ).round | ||
end | ||
|
||
def fire_delta_v | ||
calculate_hohmann_transfer | ||
# thrust(*apply_thrust(@delta_v)) | ||
delta_x, delta_y = apply_thrust(@delta_v) | ||
thrust(-delta_x, -delta_y) | ||
@mode = :fire_delta_v_prime | ||
end | ||
|
||
def apply_thrust(delta) | ||
if @x.zero? | ||
raise "x = #{@x}, y = #{@y}" | ||
else | ||
radius_slope = @y / @x | ||
tangent_slope = -1 / radius_slope | ||
delta_x = Math.sqrt(delta ** 2 / (1 + tangent_slope ** 2)) | ||
delta_y = tangent_slope * delta_x | ||
end | ||
[delta_x, delta_y] | ||
end | ||
|
||
def fire_delta_v_prime | ||
if (@time_to_prime -= 1) <= 0 | ||
# delta_x, delta_y = apply_thrust(@delta_v_prime) | ||
# thrust(-delta_x, -delta_y) | ||
thrust(*apply_thrust(@delta_v_prime)) | ||
@mode = :coast | ||
else | ||
coast | ||
end | ||
end | ||
|
||
def coast | ||
thrust(0.0, 0.0) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#!/usr/bin/env ruby -wKU | ||
|
||
module JEdI | ||
class Program | ||
class Hohmann < Program | ||
CONFIGURATION = 1 | ||
|
||
def initialize(configuration, options = Hash.new) | ||
super | ||
@mode = :fire_delta_v | ||
end | ||
|
||
def adjust_actuators | ||
update_target_radius | ||
send(@mode) | ||
end | ||
|
||
private | ||
|
||
def update_target_radius | ||
@target_radius ||= @vm.output_ports[4] | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.