69 lines
1.4 KiB
Ruby
69 lines
1.4 KiB
Ruby
|
require 'victor'
|
||
|
|
||
|
def sum_digits(n)
|
||
|
while n > 9
|
||
|
n = n.to_s.chars.map(&:to_i).sum
|
||
|
end
|
||
|
n
|
||
|
end
|
||
|
|
||
|
def step(x, y, n, dir)
|
||
|
case dir
|
||
|
when :top
|
||
|
return [x,y+n,:right]
|
||
|
when :right
|
||
|
return [x+n,y,:bottom]
|
||
|
when :bottom
|
||
|
return [x,y-n,:left]
|
||
|
when :left
|
||
|
return [x-n,y,:top]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def run_number(number)
|
||
|
counter = 1
|
||
|
x, y, dir = 0, 0, :top
|
||
|
line_stack = [[0,0]]
|
||
|
|
||
|
loop do
|
||
|
x, y, dir = step(x,y, sum_digits(counter*number), dir)
|
||
|
line_stack << [x,y]
|
||
|
counter += 1
|
||
|
break if x == 0 && y == 0
|
||
|
end
|
||
|
return make_svg(line_stack)
|
||
|
end
|
||
|
|
||
|
def make_svg(line_stack)
|
||
|
line_length = 20
|
||
|
xs = line_stack.map { |c| c[0] }
|
||
|
ys = line_stack.map { |c| c[1] }
|
||
|
|
||
|
x_offset = -xs.min
|
||
|
y_offset = -ys.min
|
||
|
svg_coords = ->(p) {
|
||
|
nx, ny = p
|
||
|
[(nx+x_offset)*line_length + line_length/2, (ny+y_offset)*line_length + line_length/2]
|
||
|
}
|
||
|
|
||
|
max_width = (xs.max - xs.min).abs * line_length + line_length
|
||
|
max_height = (ys.max - ys.min).abs * line_length + line_length
|
||
|
svg = Victor::SVG.new width: max_width, height: max_height
|
||
|
|
||
|
style = { stroke: 'black', stroke_width: 5 }
|
||
|
svg.build do
|
||
|
line_stack.each_cons(2) do |pair|
|
||
|
p1, p2 = pair
|
||
|
x1, y1 = svg_coords.call(p1)
|
||
|
x2, y2 = svg_coords.call(p2)
|
||
|
line x1: x1, y1: y1, x2: x2, y2: y2, style: style
|
||
|
circle cx: x2, cy: y2, r: line_length/6, style: style, fill: 'black'
|
||
|
end
|
||
|
end
|
||
|
return svg
|
||
|
end
|
||
|
|
||
|
(1..9).each do |i|
|
||
|
run_number(i).save "pattern_#{i}"
|
||
|
end
|