Last active
February 27, 2017 09:54
-
-
Save allansideas/aebc90812e82ce407e0ce08a1ddf7cb8 to your computer and use it in GitHub Desktop.
Marios Pyramid
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Pyramid.Plans do | |
defstruct height: nil, layers: nil | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Pyramid do | |
@moduledoc """ | |
Mario's Pyramid problem solution | |
""" | |
def main(height) do | |
#How to validate that input is > 0 without if? | |
plans = %Pyramid.Plans{height: height} | |
plans | |
|> build_layers | |
|> print_out | |
end | |
def print_out(%Pyramid.Plans{layers: layers}) do | |
# Say I didn't want a newline at the very end, would the best way be to just | |
# delete the last element of the flattened list? | |
#IO.puts(layers) (is far more performant - the flatten, and join are not required thanks to IO lists (see comment) | |
List.flatten(layers) | |
|> Enum.join("") | |
|> IO.puts | |
end | |
@doc """ | |
Builds a list consisting of the carachters needed for the layer of the Pyramid | |
`blocks` is the number of blocks in the layer | |
`height` is used to calculate the left padding | |
## Examples | |
iex> Pyramid.build_layer(3, 5) | |
[" ", " ", "#", "#", "#", "\\n"] | |
""" | |
def build_layer(blocks, height) do | |
# Generally speaking is this method too messy? Should I extract the Enum.maps | |
# into more descriptive smaller methods i.e pad_layer(layer), add_blocks_to_layer(layer)? | |
left_pad = height - blocks | |
# How to avoid having to trim the list (why does 0..0 iterate once) i.e. | |
# Enum.map(0..0, fn(pos)-> pos end) | |
# [0] | |
padding = Enum.map(0..left_pad, fn(pos)-> " " end) | |
padding_plus_blocks = padding ++ Enum.map(1..blocks, fn(pos)-> "#" end) | |
trimmed = List.delete_at(padding_plus_blocks, 0) | |
trimmed ++ ["\n"] | |
end | |
@doc """ | |
Builds a List of lists with each layer's representation in strings i.e. | |
[[" ", "#", "\n"], ["#", "#", "\n"]] | |
""" | |
def build_layers(%Pyramid.Plans{height: height} = plans) do | |
block_counts = Enum.to_list(1..height) | |
layers = | |
block_counts | |
# Can I do an (&build_layer/2) with args here instead of the full fn inside | |
# the map?, should this somehow be done with recursion? | |
|> Enum.map(fn(blocks_in_layer)-> build_layer(blocks_in_layer, height) end) | |
%Pyramid.Plans{plans | layers: layers} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can be further optimised via:
https://www.bignerdranch.com/blog/elixir-and-io-lists-part-1-building-output-efficiently/