add diamond and rle
A => diamond/README.md +69 -0
@@ 0,0 1,69 @@ 
+# Diamond
+
+The diamond kata takes as its input a letter, and outputs it in a diamond
+shape. Given a letter, it prints a diamond starting with 'A', with the
+supplied letter at the widest point.
+
+## Requirements
+
+* The first row contains one 'A'.
+* The last row contains one 'A'.
+* All rows, except the first and last, have exactly two identical letters.
+* All rows have as many trailing spaces as leading spaces. (This might be 0).
+* The diamond is horizontally symmetric.
+* The diamond is vertically symmetric.
+* The diamond has a square shape (width equals height).
+* The letters form a diamond shape.
+* The top half has the letters in ascending order.
+* The bottom half has the letters in descending order.
+* The four corners (containing the spaces) are triangles.
+
+## Examples
+
+In the following examples, spaces are indicated by `·` characters.
+
+Diamond for letter 'A':
+
+```text
+A
+```
+
+Diamond for letter 'C':
+
+```text
+··A··
+·B·B·
+C···C
+·B·B·
+··A··
+```
+
+Diamond for letter 'E':
+
+```text
+····A····
+···B·B···
+··C···C··
+·D·····D·
+E·······E
+·D·····D·
+··C···C··
+···B·B···
+····A····
+```
+
+## Running the tests
+
+To run the tests, run the command `busted` from within the exercise directory.
+
+## Further information
+
+For more detailed information about the Lua track, including how to get help if
+you're having trouble, please visit the exercism.io [Lua language page](http://exercism.io/tracks/lua/about).
+
+## Source
+
+Seb Rose [http://claysnow.co.uk/recycling-tests-in-tdd/](http://claysnow.co.uk/recycling-tests-in-tdd/)
+
+## Submitting Incomplete Solutions
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.

          
A => diamond/diamond.lua +22 -0
@@ 0,0 1,22 @@ 
+return function(which)
+  local size = (which:byte() - 64) * 2 - 1
+  --local middle = size // 2 + 1
+  -- for Lua < 5.3
+   local middle = math.floor(size / 2) + 1
+  local ret = ""
+  for i = 1, size do
+    for j = 1, size do
+      local n = i
+      if n > middle then
+        n = size - i + 1
+      end
+      if math.abs(middle - j) + 1 == n then
+        ret = ret .. string.char(n + 64)
+      else
+        ret = ret .. ' '
+      end
+    end
+      ret = ret .. '\n'
+  end
+  return ret
+end

          
A => diamond/diamond_spec.lua +63 -0
@@ 0,0 1,63 @@ 
+local diamond = require 'diamond'
+
+describe('diamond', function()
+  it('should generate the diamond for A', function()
+    assert.are.equal('A\n', diamond('A'))
+  end)
+
+  it('should generate the diamond for B', function()
+    local expected =
+      ' A \n' ..
+      'B B\n' ..
+      ' A \n'
+
+    assert.are.equal(expected, diamond('B'))
+  end)
+
+  it('should generate the diamond for C', function()
+    local expected =
+      '  A  \n' ..
+      ' B B \n' ..
+      'C   C\n' ..
+      ' B B \n' ..
+      '  A  \n'
+
+    assert.are.equal(expected, diamond('C'))
+  end)
+
+  it('should generate the diamond for E', function()
+    local expected =
+      '    A    \n' ..
+      '   B B   \n' ..
+      '  C   C  \n' ..
+      ' D     D \n' ..
+      'E       E\n' ..
+      ' D     D \n' ..
+      '  C   C  \n' ..
+      '   B B   \n' ..
+      '    A    \n'
+
+    assert.are.equal(expected, diamond('E'))
+  end)
+
+  it('should generate the diamond for H', function()
+    local expected =
+      '       A       \n' ..
+      '      B B      \n' ..
+      '     C   C     \n' ..
+      '    D     D    \n' ..
+      '   E       E   \n' ..
+      '  F         F  \n' ..
+      ' G           G \n' ..
+      'H             H\n' ..
+      ' G           G \n' ..
+      '  F         F  \n' ..
+      '   E       E   \n' ..
+      '    D     D    \n' ..
+      '     C   C     \n' ..
+      '      B B      \n' ..
+      '       A       \n'
+
+    assert.are.equal(expected, diamond('H'))
+  end)
+end)

          
A => run-length-encoding/README.md +40 -0
@@ 0,0 1,40 @@ 
+# Run Length Encoding
+
+Implement run-length encoding and decoding.
+
+Run-length encoding (RLE) is a simple form of data compression, where runs
+(consecutive data elements) are replaced by just one data value and count.
+
+For example we can represent the original 53 characters with only 13.
+
+```text
+"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB"  ->  "12WB12W3B24WB"
+```
+
+RLE allows the original data to be perfectly reconstructed from
+the compressed data, which makes it a lossless data compression.
+
+```text
+"AABCCCDEEEE"  ->  "2AB3CD4E"  ->  "AABCCCDEEEE"
+```
+
+For simplicity, you can assume that the unencoded string will only contain
+the letters A through Z (either lower or upper case) and whitespace. This way
+data to be encoded will never contain any numbers and numbers inside data to
+be decoded always represent the count for the following character.
+
+## Running the tests
+
+To run the tests, run the command `busted` from within the exercise directory.
+
+## Further information
+
+For more detailed information about the Lua track, including how to get help if
+you're having trouble, please visit the exercism.io [Lua language page](http://exercism.io/tracks/lua/about).
+
+## Source
+
+Wikipedia [https://en.wikipedia.org/wiki/Run-length_encoding](https://en.wikipedia.org/wiki/Run-length_encoding)
+
+## Submitting Incomplete Solutions
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.

          
A => run-length-encoding/run-length-encoding.lua +20 -0
@@ 0,0 1,20 @@ 
+local rle = {}
+
+function rle.encode(s)
+  for char in s:gmatch(".") do
+    s = s:gsub(char:rep(2) .. "+", function(m)
+      return tostring(#m) .. char
+    end)
+  end
+  return s
+end
+
+function rle.decode(input)
+  local dec = ""
+  for n, c in input:gmatch("(%d*)(%D)") do
+    dec= dec.. c:rep(n == "" and 1 or tonumber(n))
+  end
+  return dec
+end
+
+return rle

          
A => run-length-encoding/run-length-encoding_spec.lua +31 -0
@@ 0,0 1,31 @@ 
+local rle = require('run-length-encoding')
+
+describe('run-length-encoding', function()
+  it('should encode simple strings', function()
+    assert.equal('2A3B4C', rle.encode('AABBBCCCC'))
+  end)
+
+  it('should encode strings with multi-digit run lengths', function()
+    assert.equal('2A10B4C', rle.encode('AABBBBBBBBBBCCCC'))
+  end)
+
+  it('should decode simple strings', function()
+    assert.equal('AABBBCCCC', rle.decode('2A3B4C'))
+  end)
+
+  it('should decode strings with multi-digit run lengths', function()
+    assert.equal('AABBBBBBBBBBCCCC', rle.decode('2A10B4C'))
+  end)
+
+  it('should not encode characters with a run length of 1', function()
+    assert.equal('2AB4CD', rle.encode('AABCCCCD'))
+  end)
+
+  it('should successfully decode characters with a run length of 1', function()
+    assert.equal('AABCCCCD', rle.decode('2AB4CD'))
+  end)
+
+  it('should decode an encoded string back to the original string', function()
+    assert.equal('zzz ZZ  zZ', rle.decode(rle.encode('zzz ZZ  zZ')))
+  end)
+end)