[2016][ruby][1]
change yqvtlzktpnoxlsoxyyqnokyqoysuyxlq
commit 78b2c1790a9e51097024f393b1cfb6ec4135e5c6
author Alpha Chen <alpha.chen@gmail.com>
date
parent ssorwuwq
diff --git a/2016/ruby/Gemfile b/2016/ruby/Gemfile
new file mode 100644
index 0000000..2b8ce04
--- /dev/null
+++ b/2016/ruby/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org'
+
+gem 'minitest'
diff --git a/2016/ruby/Gemfile.lock b/2016/ruby/Gemfile.lock
new file mode 100644
index 0000000..75b11ae
--- /dev/null
+++ b/2016/ruby/Gemfile.lock
@@ -0,0 +1,13 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    minitest (5.10.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  minitest
+
+BUNDLED WITH
+   1.13.6
diff --git a/2016/ruby/day_01.rb b/2016/ruby/day_01.rb
new file mode 100644
index 0000000..cf606b2
--- /dev/null
+++ b/2016/ruby/day_01.rb
@@ -0,0 +1,67 @@
+include Math
+
+def follow_instructions(input)
+  seq = input.split(', ')
+
+  # start facing north at the origin
+  dir = -PI/2
+  locations = [[0,0]]
+  seq.each.with_object(locations) do |step, locations|
+    /(?<turn>\w)(?<blocks>\d+)/ =~ step
+
+    case turn
+    when ?R
+      dir += PI/2
+    when ?L
+      dir -= PI/2
+    else
+      raise "unexpected turn: #{turn}"
+    end
+
+    blocks.to_i.times do
+      location = locations.last
+      x = location[0] + cos(dir).to_i
+      y = location[1] + sin(dir).to_i
+      locations << [x, y]
+    end
+  end
+
+  locations
+end
+
+def first_dupe(ary)
+  seen = Set.new
+  ary.find { |elem|
+    seen.include?(elem) || (seen << elem && false)
+  }
+end
+
+require 'minitest'
+# require 'minitest/autorun'
+class TestInstructions < Minitest::Test
+  def test_instructions
+    assert_distance 5, 'R2, L3'
+    assert_distance 2, 'R2, R2, R2'
+    assert_distance 12, 'R5, L5, R5, R3'
+  end
+
+  def test_first_dupe
+    assert_equal 1, first_dupe([1, 2, 3, 1])
+    assert_equal 2, first_dupe([1, 2, 3, 2])
+    assert_equal 3, first_dupe([1, 2, 3, 3])
+
+    locations = follow_instructions('R8, R4, R4, R8')
+    assert_equal [4, 0], first_dupe(locations)
+  end
+
+  def assert_distance(expected, instructions)
+    locations = follow_instructions(instructions)
+    assert_equal expected, locations.last.map(&:abs).inject(:+)
+  end
+end
+
+if __FILE__ == $0
+  puts first_dupe(follow_instructions(DATA.read))
+end
+
+__END__