[2017][ruby][3.0]

sorbet
Alpha Chen 7 years ago
parent 4c0b47a24e
commit 14063c8ad4

@ -1,9 +1,35 @@
input = ARGF.read.to_i require "minitest"
class Spiral
def initialize
@square = [0,0]
@dir = [1,0]
@steps = [1, 1]
end
def each
return enum_for(__method__) unless block_given?
dir = [1,0] loop do
yield @square
step!
end
end
def next_dir(dir) private
case dir
def step!
@steps[0] -= 1
@square = @square.zip(@dir).map {|i,j| i+j }
if @steps[0] == 0
change_dir!
@steps << next_steps
@steps.shift
end
end
def change_dir!
@dir = case @dir
when [1,0] when [1,0]
[0,1] [0,1]
when [0,1] when [0,1]
@ -13,28 +39,51 @@ def next_dir(dir)
when [0,-1] when [0,-1]
[1,0] [1,0]
else else
raise "invalid dir: #{dir}" raise "invalid dir: #@dir"
end end
end end
grid = Hash.new(0) def next_steps
grid[[0,0]] = 1 case @dir
when [1,0]
def next_value(grid, x, y) @steps[1]
[[-1, 1],[0, 1],[1,1], when [0,1]
[-1, 0], [1,0], @steps[1] + 1
[-1,-1],[0,-1],[1,-1]].map {|i,j| grid[[x+i,y+j]]}.sum when [-1,0]
@steps[1]
when [0,-1]
@steps[1] + 1
else
raise "invalid dir: #@dir"
end
end
end end
current = [0,0] if $0 == __FILE__
loop do if ARGV.shift == "test"
next_square = current.zip(dir).map {|a,b| a + b } require "minitest/test"
value = next_value(grid, *next_square) else
puts "#{current}: #{value}" input = ARGF.read.to_i
exit if value > input p Spiral.new.each.with_index.find {|_,i| i == input - 1 }.first.sum
grid[next_square] = value end
current = next_square
dir = next_dir(dir) if grid[current.zip(next_dir(dir)).map {|a,b| a + b }] == 0
end end
p next_value(grid, 1,0) class TestSpiral < Minitest::Test
def test_spiral
spiral = Spiral.new
e = spiral.each
assert_equal [0,0], e.next
assert_equal [1,0], e.next
assert_equal [1,1], e.next
assert_equal [0,1], e.next
assert_equal [-1,1], e.next
assert_equal [-1,0], e.next
assert_equal [-1,-1], e.next
assert_equal [0,-1], e.next
assert_equal [1,-1], e.next
assert_equal [2,-1], e.next
spiral = Spiral.new
assert_equal [0,-2], spiral.each.with_index.find {|_,i| i == 22 }.first
end
end

Loading…
Cancel
Save