"Exercise: Diamond"

diamond: aString
"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."
"(self new diamond: 'A') >>> #('A')"
"(self new diamond: 'C') >>> #('  A  ' ' B B ' 'C   C' ' B B ' '  A  ')"
"(self new diamond: 'E') >>> #('    A    ' '   B B   ' '  C   C  ' ' D     D ' 'E       E' ' D     D ' '  C   C  ' '   B B   ' '    A    ')"
| topHalf fullGrid maxLevel |
    aString size = 1 ifFalse: [ self error: 'The input should be a string with exactly one character' ].
    aString first = $A ifTrue: [ ^ { 'A' } ].

    maxLevel := aString first asciiValue - $A asciiValue.
    topHalf := OrderedCollection new.

    0 to: maxLevel do: [ :i |
        | ch leading inner line |
        ch := ($A asciiValue + i) asCharacter.
        leading := maxLevel - i.
        inner := i * 2 - 1.
        line := String streamContents: [ :s |
            | leadingWhitespace |
            leadingWhitespace := String new: leading withAll: Character space.
            leadingWhitespace isEmpty ifFalse: [ s nextPutAll: leadingWhitespace ].
            s nextPut: ch.
            inner > 0 ifTrue: [
                s nextPutAll: (String new: inner withAll: Character space).
                s nextPut: ch ].
            leadingWhitespace isEmpty ifFalse: [ s nextPutAll: leadingWhitespace ] ].
        topHalf add: line ].

    fullGrid := topHalf , topHalf allButLast reversed.
    ^ fullGrid asArray


"Tests"
testDiamond
self assert: (task diamond: 'A') equals: #('A').
  self assert: (task diamond: 'B') equals: #(' A ' 'B B' ' A ').
  self assert: (task diamond: 'C') equals: #('  A  ' ' B B ' 'C   C' ' B B ' '  A  ').
  self assert: (task diamond: 'D') equals: #('   A   ' '  B B  ' ' C   C ' 'D     D' ' C   C ' '  B B  ' '   A   ').
  self assert: (task diamond: 'Z') equals: #('                         A                         ' '                        B B                        ' '                       C   C                       ' '                      D     D                      ' '                     E       E                     ' '                    F         F                    ' '                   G           G                   ' '                  H             H                  ' '                 I               I                 ' '                J                 J                ' '               K                   K               ' '              L                     L              ' '             M                       M             ' '            N                         N            ' '           O                           O           ' '          P                             P          ' '         Q                               Q         ' '        R                                 R        ' '       S                                   S       ' '      T                                     T      ' '     U                                       U     ' '    V                                         V    ' '   W                                           W   ' '  X                                             X  ' ' Y                                               Y ' 'Z                                                 Z' ' Y                                               Y ' '  X                                             X  ' '   W                                           W   ' '    V                                         V    ' '     U                                       U     ' '      T                                     T      ' '       S                                   S       ' '        R                                 R        ' '         Q                               Q         ' '          P                             P          ' '           O                           O           ' '            N                         N            ' '             M                       M             ' '              L                     L              ' '               K                   K               ' '                J                 J                ' '                 I               I                 ' '                  H             H                  ' '                   G           G                   ' '                    F         F                    ' '                     E       E                     ' '                      D     D                      ' '                       C   C                       ' '                        B B                        ' '                         A                         ').