defmodule Aoc2023.Common do def stringify(s) when is_binary(s) do s end def stringify(n) when is_integer(n) do inspect(n) end def stringify(nil), do: "nil" def map_nth(tup, n, fun) do put_elem(tup, n, fun.(elem(tup, n))) end defmacro pipe(expr) do quote do fn (val) -> val |> unquote(expr) end end end defmacro l &&& r do quote do fn val -> l = val |> unquote(l) r = val |> unquote(r) {l, r} end end end def runs(lst, f) do lst |> Enum.with_index() |> Enum.chunk_by(pipe(elem(0) |> f.())) |> Enum.filter(pipe(Enum.at(0) |> elem(0) |> f.())) |> Enum.map(Enum.at(0) |> elem(1) &&& length) end def id(x), do: x def const(_, x), do: x def lines(x), do: String.split(x, "\n") def head([head | _]), do: head def head([]), do: nil def tail([_ | tail]), do: tail def tail([]), do: nil def lcm(a, b), do: div(abs(a*b), Integer.gcd(a,b)) def lcm(ls), do: ls |> Enum.reduce(&lcm/2) def list_map_at(l, n, f) do List.replace_at(l, n, f.(Enum.at(l, n))) end def transpose(l), do: l |> Enum.zip |> Enum.map(&Tuple.to_list/1) def collapse(enum, v) do enum |> Stream.zip(enum |> Stream.drop(1) |> Stream.concat([nil])) |> Stream.filter(fn {a, b} -> a != v || b != v end) |> Stream.map(pipe(elem(0))) end def repeat(_, 0), do: [] def repeat(lst, n), do: Enum.concat(lst, repeat(lst, n - 1)) end