16 Jul 2013, 02:25
Dave_gnome_head_isolated_pragsmall

Dave Thomas (337 posts)

  • An Elixir single quoted string is actually a list of individual character codes. Write a function caesar(list, n) that adds n to each element of the list, but wrapping if the addition results in a character greater than z.

    iex> MyList.caesar('ryvkve', 13)
    ?????? :)
    
A Possible Solution
defmodule MyList do

  def caesar([], _n), do: []

  def caesar([ head | tail ], n)
    when head+n <= ?z,
    do: [ head+n | caesar(tail, n) ]

  def caesar([ head | tail ], n), 
    do: [ head+n-26 | caesar(tail, n) ]

end

IO.puts MyList.caesar('ryvkve', 13)  #=> elixir
03 Aug 2013, 03:27
Generic-user-small

Luke Imhoff (2 posts)

Did I miss the ?character => integer somewhere earlier in the book? I ended up going with this since I knew only that single quotes were strings, and that single elements would give the integer:


defmodule MyList do
  @caesar_start hd('a')
  @caesar_end hd('z')
  @caesar_width (@caesar_end - @caesar_start + 1)

  def caesar([], _rotation) do
    []
  end
  def caesar([character | tail], rotation) do
    offset = character - @caesar_start
    rotated_offset = rem(offset + rotation, @caesar_width)
    rotated_character = @caesar_start + rotated_offset

    [rotated_character | caesar(tail, rotation)]
  end
end ---

I’m not sure pre-computing the start and end and width in attributes is faster or the Erlang VM would make the same lift out of the function. I do think this is better than hardcoding the 26 width.

23 Aug 2013, 13:17
Twitter-avatar-orangeblau_pragsmall

Rin Raeuber (1 post)

Alternative without hardcoded width:

defmodule MyList do

  def caesar([], n), do: []

  def caesar([head | tail], n // 0) do
    [_caesar(head, n) | caesar(tail, n) ]
  end

  defp _caesar(char, n) do
    width = ?z - ?a + 1
    ?a + rem(char + n - width, width)
  end

end

Feedback welcome.

24 Sep 2013, 03:54
Ac_simpsonized_pragsmall

Antonio Carlos da Graça Mota Durão de Souza (5 posts)

I used fixed character values.

defmodule MyList do
  def caesar([], _),  do: []

  def caesar([head | tail], salt)
    when head + salt > 122  do
    [96 + (head + salt - 122) | caesar(tail, salt)]
  end

  def caesar([head | tail], salt)
    when head + salt <= 122  do
    [head + salt | caesar(tail, salt)]
  end
end
29 Sep 2013, 04:52
Milmazz3_pragsmall

Milton Mazzarri (1 post)

I think that we can express an alternative solution as result = rem (letter + shift, 26), but first, we need to assume that A=0..Z=25

defmodule MyList do
  def caesar([], _n), do: []

  def caesar([head | tail], n) do
    [do_caesar(head, n) | caesar(tail, n)]
  end

  defp do_caesar(base, n) do
    ?a + rem(base - ?a + n, ?z - ?a + 1)
  end
end
19 Oct 2013, 15:00
Mac 128k logic board 96x96_pragsmall

Roger Turner (5 posts)


defmodule MyList do

  def caesar([], _n), do: []

  def caesar([ head | tail ], n) when head in ?a..?z do
	_caesar(head, n, ?a, tail)
  end

  def caesar([ head | tail ], n) when head in ?A..?Z do
	_caesar(head, n, ?A, tail)
  end

  defp _caesar(alpha, n, first, tail) do 
	[ rem(alpha-first + n, 26) + first  | caesar(tail, n) ]
  end

end

26 Dec 2013, 17:02
N609929290_306703_2458_pragsmall

Tanja Pislar (7 posts)

defmodule MyList do

  def caesar(list, n) do
     map list, &(if (&1 + n) > 122, do: &1 + n - 26, else: &1 + n)
  end

end
30 Dec 2013, 01:26
Generic-user-small

Brynjar Smári Bjarnason (1 post)

Quite simple map

def caesar(coll,n) do
Enum.map(coll, &(rem( &1-?a+n, (?z-?a+1) + ?a) ) end

27 Jan 2014, 00:32
Generic-user-small

Alan Gardner (6 posts)

I ended up with the following because I wasn’t aware of ?z :)

def wrap(char), do: 97 + rem(char-97, 26)
def caesar([], _), do: []
def caesar([head|tail], n), do: [wrap(head+n), caesar(tail, n)]
11 Mar 2014, 01:02
Generic-user-small

Nathan Feaver (3 posts)

I could use only one map function if I worked this out a little more. I like this solution because I let Enum.map handle the head and tail recursion logic.

defmodule MyList do
  def ceasar(list, n) do
    list
      |> Enum.map(&(&1 + n))
      |> Enum.map(&_char_wrap/1)
  end
  defp _char_wrap(n)
    when n > ?z,
    do: n - 26
  defp _char_wrap(n), do: n
end
26 Mar 2014, 10:45
Generic-user-small

Maximilian Schulz (1 post)

Well, I wasn’t sure about it upfront, but the matching magic seemed like the thing I was looking for. And Elixir seems to be able to compare single element lists pretty well:

  def caesar([], n) do
    []
  end

  def caesar([head | tail], n) when [head + n] > 'z' do
    [head + n - 26 | caesar(tail, n)]
  end

  def caesar([head | tail], n) do
    [head + n | caesar(tail, n)]
  end
  You must be logged in to comment