Skip to content

Instantly share code, notes, and snippets.

@Qqwy
Last active May 13, 2016 14:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Qqwy/8c704236d7442a50ca3d3d2cd8093faf to your computer and use it in GitHub Desktop.
Save Qqwy/8c704236d7442a50ca3d3d2cd8093faf to your computer and use it in GitHub Desktop.
defmodule ZigZagConversion do
@moduledoc """
Qqwy's solution to https://leetcode.com/problems/zigzag-conversion/
"""
@doc """
Converts a string into a zig-zagged string:
- the characters of string is distributed over `num_rows`, as follows:
- char 0 in row 0
- char 1 in row 1
- char n in row n
- char n+1 in row n-1
- char 2n in row 0
- ... etc, until the string is finished.
The final rows are concatenated again, to arrive at the result.
## Examples
iex> ZigZagConversion.convert("PAYPALISHIRING", 3)
"PAHNAPLSIIGYIR"
iex> ZigZagConversion.convert("Elixir is a fun language", 4)
"E fnlri uageiisanlugx a"
"""
@spec convert(binary, integer) :: binary
def convert(string, num_rows)
def convert(_string, num_rows) when num_rows <= 0, do: nil
def convert(string, num_rows) when num_rows == 1, do: string
def convert(string, num_rows) do
rows = Stream.cycle([[]]) |> Enum.take(num_rows) |> List.to_tuple
convert(string, rows, 0, 1)
end
@spec convert(binary, tuple, non_neg_integer, integer) :: binary
defp convert(string, rows, cur_row, dir)
defp convert("", rows, _cur_row, _dir) do
rows
|> Tuple.to_list
|> Enum.join
end
defp convert(<<char::utf8, rest::bits>>, rows, cur_row, dir) do
new_rows = put_elem(rows, cur_row, elem(rows, cur_row) ++ [char])
dir = cond do
cur_row + dir == tuple_size(new_rows) -> -1
cur_row == 0 && dir == -1 -> +1
:otherwise -> dir
end
convert(rest, new_rows, cur_row + dir, dir)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment