advent/src/advent/util.cr

105 lines
1.7 KiB
Crystal

class Array(T)
def zip_with(other : Array(R), &block : T, R -> U) forall R, U
dest = [] of U
zip(other) do |l, r|
dest << yield l, r
end
dest
end
def reduce_elementwise(&block)
reduce do |l, r|
l.zip_with(r) { |a, b| yield a, b }
end
end
def union
reduce(T.new) do |l, r|
l | r
end
end
def intersect
reduce do |l, r|
l & r
end
end
def draw(width, maps)
self.each_slice(width) do |slice|
slice.each do |c|
print maps[c]
end
puts
end
end
def find_indices
into = [] of Int32
each_with_index do |v, i|
into << i if yield v
end
into
end
end
struct Tuple(*T)
def add(other : Tuple(*T))
{% begin %}
{ {% for t, i in T %} self[{{i}}] + other[{{i}}], {% end %} }
{% end %}
end
def neg
{% begin %}
{ {% for t, i in T %} -self[{{i}}], {% end %} }
{% end %}
end
def sub(other : Tuple(*T))
add other.neg
end
def dot(other : Tuple(*T))
{% begin %}
{% for t, i in T %} self[{{i}}] * other[{{i}}] + {% end %} 0
{% end %}
end
def reduce_fraction
gcd = self[0].gcd self[1]
return self if gcd == 0
{ self[0]//gcd, self[1]//gcd}
end
def signum
{% begin %}
{ {% for t, i in T %} self[{{i}}].signum, {% end %} }
{% end %}
end
def abs
end
end
struct Number
def signum
return 0 if self == 0
self // self.abs
end
end
class Hash(K, V)
def draw(maps)
min_x, max_x = keys.minmax_of &.[0]
min_y, max_y = keys.minmax_of &.[1]
(max_y-min_y+1).times do |y|
(max_x-min_x+1).times do |x|
next unless has_key?({x,y})
print maps[self[{x,y}]]
end
puts
end
end
end