[Question]
  [
You're given a hexagonal grid of the characters `.` and `#`, like this:
```
 . . . . . . . .
. . . . # . . . 
 . # . . . # . .
. . . # . . . . 
 . . . . . # . .
. . . . . . . . 
```
Your task is to fill the entire axis-aligned bounding box of the `#` with further `#`:
```
 . . . . . . . .
. . # # # # . . 
 . # # # # # . .
. . # # # # # . 
 . . # # # # . .
. . . . . . . . 
```
The axis-aligned bounding box is the smallest convex hexagonal shape which contains all the `#`. Note that in the case of the hexagonal grid, there are *three* axes to consider (W/E, SW/NE, NW/SE):
[![enter image description here](https://i.stack.imgur.com/gcBoY.png)](https://i.stack.imgur.com/gcBoY.png)
Here is another example to show that in some cases, one or more sides will contain only one `#`:
```
. . . . . . . .         . . . . . . . . 
 . # . . . . . .         . # # # # . . .
. . . . . # . .         . . # # # # . . 
 . . # . . . . .         . . # # # . . .
. . . . . . . .         . . . . . . . . 
```
You can either view these as hexagons with degenerate sides, or you can draw the bounding box around them, like I have done above, in which case they are still hexagons:
[![enter image description here](https://i.stack.imgur.com/yNMAq.png)](https://i.stack.imgur.com/yNMAq.png)
**Too hard? [Try Part I!](https://codegolf.stackexchange.com/q/91065/8478)**
## Rules
You may use any two *distinct* non-space printable ASCII characters (0x21 to 0x7E, inclusive), in place of `#` and `.`. I'll continue referring to them as `#` and `.` for the remainder of the specification though.
Input and output may either be a single linefeed-separated string or a list of strings (one for each line), but the format has to be consistent.
You may assume that the input contains at least one `#` and all lines are the same length. Note that there are two different "kinds" of lines (starting with a space or a non-space) - you may *not* assume that the input always starts with the same type. You may assume that the bounding box always fits inside the grid you are given.
You may write a [program or a function](http://meta.codegolf.stackexchange.com/q/2419) and use any of the our [standard methods](http://meta.codegolf.stackexchange.com/q/2447) of receiving input and providing output.
You may use any [programming language](http://meta.codegolf.stackexchange.com/q/2028), but note that [these loopholes](http://meta.codegolf.stackexchange.com/questions/1061/loopholes-that-are-forbidden-by-default) are forbidden by default.
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest valid answer – measured in *bytes* – wins.
## Test Cases
Each test case has input and output next to each other.
```
#    #
 . .      . . 
# . #    # # #
 . .      . . 
 . #      . # 
. . .    . # .
 # .      # . 
 # .      # . 
. . .    . # .
 . #      . # 
 # .      # . 
# . .    # # .
 . #      # # 
 . #      # # 
# . .    # # #
 . #      # # 
. . #    . # #
 . .      # # 
# . .    # # .
# . .    # # .
 . .      # # 
. . #    . # #
. . . . . . . .         . . . . . . . . 
 . . # . # . . .         . . # # # . . .
. . . . . . . .         . . . # # . . . 
 . . . # . . . .         . . . # . . . .
. . . . . . . .         . . . . . . . . 
 . . # . . . # .         . . # # # # # .
. . . . . . . .         . . . # # # # . 
 . . . # . . . .         . . . # # # . .
. . . . . . . .         . . . . . . . . 
 . # . . . . . .         . # # # # . . .
. . . . . # . .         . . # # # # . . 
 . . . . . . . .         . . . . . . . .
. . . . . . . .         . . . . . . . . 
 . # . . . . . .         . # # # # . . .
. . . . . # . .         . . # # # # . . 
 . . # . . . . .         . . # # # . . .
. . . . # . . .         . . # # # # . . 
 . # . . . # . .         . # # # # # . .
. . . # . . . .         . . # # # # # . 
 . . . . . # . .         . . # # # # . .
```
  
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), ~~82~~ 71 bytes
```
~~L,hbebMqH@S+GH1KhMyJs.e,Lkfq\#@bTUb.zA,ySm-FdJySsMJj.es.eXW&&gKkgG-kYgH+kYZ\.\#b.z~~
MqH@S[hGHeG)1j.es.eXW&&ghMJs.e,Lkfq\#@bTUb.zkgSm-FdJ-kYgSsMJ+kYZ\.\#b.z
```
[Try it online!](http://pyth.herokuapp.com/?code=MqH%40S%5BhGHeG%291j.es.eXW%26%26ghMJs.e%2CLkfq%5C%23%40bTUb.zkgSm-FdJ-kYgSsMJ%2BkYZ%5C.%5C%23b.z&input=+.+.+.+.+.+.+.+.%0A.+.+.+.+%23+.+.+.+%0A+.+%23+.+.+.+%23+.+.%0A.+.+.+%23+.+.+.+.+%0A+.+.+.+.+.+%23+.+.%0A.+.+.+.+.+.+.+.+&debug=0)
### Explanation
* Let A be the point with the lowest y-coordinate and B the point with the highest y-coordinate.
* Let C be the point with the lowest (x-value minus y-value) and D the point with the highest.
* Let E be the point with the lowest (x-value plus y-value) and F the point with the highest.
Then it is equivalent to finding the coordinates which the y-coordinate is between A and B, the x-value minus y-value is between C and D, and the x-value plus y-value is between E and F.
[Answer]
## Haskell, ~~256 254~~ 243 bytes
```
import Data.List
f=z(\l->(,).(,))[0..]l)[0..]
q l=m(m(\e->min(snd e).(".#"!!).fromEnum.and.z($)(m(\x y->y>=minimum x&&y<=maximum x).transpose.m b.filter((==)'#'.snd).concat$l)$b e))l
b=(m uncurry[const,(-),(+)]<*>).pure.fst
z=zipWith
m=map
q.f
```
Thanks @Damien for golfing `f`!
Input is taken as list of list of chars, output is provided the same way.
Soo this was a beast to write. It's based on LeakyNun's idea using a maximum and minimum based filtering on the coordinates of the items.
I'm really surprised by the fact that `m=map` actually saves bytes since it seems so costly.
---
Explanation:
Here's a slightly less butchered version (emphasis on *slightly*):
```
import Data.List
f=zipWith(\y l->zipWith(\x e->((y,x),e))[0..]l)[0..]
p=map(\x y->y>=minimum x&&y<=maximum x).transpose.map b.filter((==)'#'.snd).concat
q l=map(map(\e->min(snd e).(".#"!!).fromEnum.and.zipWith($)(p$l)$b e))l
b=(map uncurry[const,(-),(+)]<*>).pure.fst
```
* `f` is a function which assigns each char an index `(y-index, x-index)` while preserving the original structure of the list.
* `b`: Given an item of the indexed list, `b` computes `[y-index, y - x, y + x]`.
* `p`: Given the indexed field, return 3 functions `Int -> Bool`, the first of which is the check of the y-index, the second of the difference and the third of the sum. `min(snd e)` takes care of the spaces (a space is smaller than both). This function is inlined in the golfed code.
* `q` given the indexed field, change all necessary `.` to `#` by checking if that specific field return `True` to every test function.
The final solution is then the composition of `q` and `f`.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~45~~ ~~3513~~ ~~42~~ 41 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
Ṁ€»\
ṚÇṚ«Çṁ"
ŒDṙZL$ÇṙL’$ŒḌ«Ç
ṚÇṚ«Ç
n⁶aÇo⁶
```
This is a list of links; the last one has to be called on the input to produce the output.
I/O is in form of string arrays, where `.` indicates empty and `@` indicates filled.
[Try it online!](http://jelly.tryitonline.net/#code=4bmA4oKswrtcCuG5msOH4bmawqvDh-G5gSIKxZJE4bmZWkwkw4fhuZlM4oCZJMWS4biMwqvDhwrhuZrDh-G5msKrw4cKbuKBtmHDh2_igbYK4bu0w4dZICAgICAgICAgICAgICDhuLcg4oCcU3BsaXQgYXQgbGluZWZlZWRzLCBjYWxsIHByZXZpb3VzIGxpbmssIGpvaW4gYXQgbGluZWZlZWRzLuKAnQ&input=&args=LiAuIEAKIC4gLiAKQCAuIC4) or [verify all test cases](http://jelly.tryitonline.net/#code=4bmA4oKswrtcCuG5msOH4bmawqvDh-G5gSIKxZJE4bmZWkwkw4fhuZlM4oCZJMWS4biMwqvDhwrhuZrDh-G5msKrw4cKbuKBtmHDh2_igbYK4bu0w4dZCsWT4bmj4oCcwrbCtuKAncOH4oKsauKAnMK2wrbigJ0&input=&args=QAoKIC4gLiAKQCAuIEAKIC4gLiAKCiAuIEAgCi4gLiAuCiBAIC4gCgogQCAuIAouIC4gLgogLiBAIAoKIEAgLiAKQCAuIC4KIC4gQCAKCiBAIEAgCkAgQCBACiBAIEAgCgouIC4gLiAuIC4gLiAuIC4gCiAuIC4gQCAuIEAgLiAuIC4KLiAuIC4gLiAuIC4gLiAuIAogLiAuIC4gQCAuIC4gLiAuCgouIC4gLiAuIC4gLiAuIC4gCiAuIC4gQCAuIC4gLiBAIC4KLiAuIC4gLiAuIC4gLiAuIAogLiAuIC4gQCAuIC4gLiAuCgouIC4gLiAuIC4gLiAuIC4gCiAuIEAgLiAuIC4gLiAuIC4KLiAuIC4gLiAuIEAgLiAuIAogLiAuIC4gLiAuIC4gLiAuCgouIC4gLiAuIC4gLiAuIC4gCiAuIEAgLiAuIC4gLiAuIC4KLiAuIC4gLiAuIEAgLiAuIAogLiAuIEAgLiAuIC4gLiAuCgouIC4gQCAuIEAgLiAuIC4gCiAuIEAgLiAuIC4gQCAuIC4KLiAuIC4gQCAuIEAgQCAuIAogLiAuIEAgLiAuIEAgLiAu).
### Background
Let's consider the following example.
```
. . . . . . . . 
 . @ . . . . . .
. . . . . @ . . 
 . . @ . . . . .
```
By drawing a pair or parallel lines – the closest pair that encloses all filled positions – in each of the three directions, we can determine the hexagonal bounding box.
In the implementation, we replace all characters between those two lines with `@`, and everything outside these lines with `.`, with the possible exception of diagonals that only contains spaces).
For the horizontal axis, this gives
```
................
@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@
```
for the falling diagonal axis, it gives
```
..@@@@@@@......
...@@@@@@@......
....@@@@@@@.....
 ....@@@@@@@....
```
and for the raising diagonal axis, it gives
```
....@@@@@@@@@...
...@@@@@@@@@....
..@@@@@@@@@....
.@@@@@@@@@.... .
```
By taking the character-wise minimum of all three, since `.` < `@`, we get
```
...............
...@@@@@@@......
....@@@@@@@....
 ....@@@@@.... .
```
All that's left to do is restoring the spaces.
### How it works
```
n⁶aÇo⁶           Main link. Argument: A (array of strings)
n⁶               Not-equal space; yield 0 for spaces, 1 otherwise.
  aÇ             Take the logical AND with the result the 4th helper link.
                 This will replace 1's (corresponding to non-space characters) with
                 the corresponding character that result from calling the link.
    o⁶           Logical OR with space; replaces the 0's with spaces.
```
```
ṚÇṚ«Ç            4th helper link. Argument: A
Ṛ                Reverse the order of the strings in A.
 Ç               Call the 3rd helper link.
  Ṛ              Reverse the order of the strings in the resulting array.
    Ç            Call the 3rd helper link with argument A (unmodified).
   «             Take the character-wise minimum of both results.
```
```
ŒDṙZL$ÇṙL’$ŒḌ«Ç  3rd helper link. Argument: L (array of strings)
ŒD               Yield all falling diagonals of L. This is a reversible operation,
                 so it begins with the main diagonal.
   ZL$           Yield the length of the transpose (number of columns).
  ṙ              Shift the array of diagonals that many units to the left.
                 This puts the diagonals in their natural order.
      Ç          Call the helper link on the result.
        L’$      Yield the decremented length (number of columns) of L.
       ṙ         Shift the result that many units to the left.
                 This puts the changed diagonals in their original order.
           ŒḌ    Undiagonal; reconstruct the string array.
              Ç  Call the 2nd helper link with argument L (unmodified).
             «   Take the character-wise minimum of both results.
```
```
ṚÇṚ«Çṁ"          2nd helper link. Argument: M (array)
Ṛ                Reverse the rows of M.
 Ç               Call the 1st helper link on the result.
  Ṛ              Reverse the rows of the result.
    Ç            Call the 1nd helper link with argument M (unmodified).
   «             Take the minimum of both results.
     ṁ"          Mold zipwith; repeat each character in the result to the left
                 as many times as needed to fill the corresponding row of M.
```
```
Ṁ€»\             1st helper link. Argument: N (array)
Ṁ€               Take the maximum of each row of N.
  »\             Take the cumulative maxima of the resulting characters.
```
[Answer]
# Python 3, ~~380~~ ~~378~~ ~~348~~ 346 bytes
Note that the indentation is with tabs, not spaces. 
### Golfed version:
```
def s(i):
    L=i.splitlines();E=enumerate;A=lambda x,y:(y,x+y,x-y);N=(2**64,)*3;X=(-2**64,)*3
    for y,l in E(L):
        for x,c in E(l):
            if c=='#':p=A(x,y);X=tuple(map(max,X,p));N=tuple(map(min,N,p))
    R=''
    for y,l in E(L):
        for x,c in E(l):
            if c!='.':R+=c
            else:p=A(x,y);f=all(N[j]<=p[j]<=X[j]for j in range(0,3));R+='.#'[f]
        R+='\n'
    return R
```
[Test it on Ideone](https://ideone.com/zSrjwB)
### Explanation (for ungolfed version below):
All processing is done without any conversion, space characters are simply skipped.  
Function `axes_pos` calculates 3-tuple of imaginary "3D" coordinates, they are accumulated into (element wise) minimum and maximum 3-tuples (`bmin`, `bmax`) for all `#` characters. 
Coordinates are calculated in `def axes_pos(x, y): return y, x + y, lc - y + x`;  
where X counts from 0 to right, and Y counts from 0 to bottom (from first line to last).  
First imaginary coordinate is basically Y, because it's obvious why. Its axe is orthogonal to green bounds (in the OP's pictures)  
Second is orthogonal to red bounds, and third is orthogonal to blue bounds.
In the second pass, replacement is done for all `.` characters which "3D" coordinates fall into `bmin`..`bmax` range, element wise — this is checked in this expression `all(bmin[j] <= p[j] <= bmax[j] for j in range(0, 3))`.
### Ungolfed version with tests, [also on Ideone](https://ideone.com/zb0Gkk):
```
def solve(i):
    ls = i.splitlines()
    lc = len(ls)
    def axes_pos(x, y):
        return y, x + y, lc - y + x
    I = 2 ** 64
    bmin = (I, I, I)
    bmax = (0, 0, 0)
    for y, line in enumerate(ls):
        for x, char in enumerate(line):
            if char != '#': continue
            p = axes_pos(x, y)
            bmax = tuple(map(max, bmax, p))
            bmin = tuple(map(min, bmin, p))
    result = ''
    for y, line in enumerate(ls):
        for x, char in enumerate(line):
            if char != '.':
                result += char
            else:
                p = axes_pos(x, y)
                f = all(bmin[j] <= p[j] <= bmax[j] for j in range(0, 3))
                result += '#' if f else char
        result += '\n'
    return result
def run_test(a, b):
    result = solve(a)
    if result != b:
        raise AssertionError('\n' + result + '\n\nshould be equal to\n\n' + b)
def run_tests():
    run_test(
        "#\n",
        "#\n")
    run_test(
        " . . \n"
        "# . #\n"
        " . . \n",
        " . . \n"
        "# # #\n"
        " . . \n")
    run_test(
        " . # \n"
        ". . .\n"
        " # . \n",
        " . # \n"
        ". # .\n"
        " # . \n")
    run_test(
        " # . \n"
        ". . .\n"
        " . # \n",
        " # . \n"
        ". # .\n"
        " . # \n")
    run_test(
        " # . \n"
        "# . .\n"
        " . # \n",
        " # . \n"
        "# # .\n"
        " # # \n")
    run_test(
        " . # \n"
        "# . .\n"
        " . # \n",
        " # # \n"
        "# # #\n"
        " # # \n")
    run_test(
        ". . . . . . . . \n"
        " . . # . # . . .\n"
        ". . . . . . . . \n"
        " . . . # . . . .\n",
        ". . . . . . . . \n"
        " . . # # # . . .\n"
        ". . . # # . . . \n"
        " . . . # . . . .\n")
    run_test(
        ". . . . . . . . \n"
        " . . # . . . # .\n"
        ". . . . . . . . \n"
        " . . . # . . . .\n",
        ". . . . . . . . \n"
        " . . # # # # # .\n"
        ". . . # # # # . \n"
        " . . . # # # . .\n")
    run_test(
        ". . . . . . . . \n"
        " . # . . . . . .\n"
        ". . . . . # . . \n"
        " . . . . . . . .\n",
        ". . . . . . . . \n"
        " . # # # # . . .\n"
        ". . # # # # . . \n"
        " . . . . . . . .\n")
    run_test(
        ". . . . . . . . \n"
        " . # . . . . . .\n"
        ". . . . . # . . \n"
        " . . # . . . . .\n",
        ". . . . . . . . \n"
        " . # # # # . . .\n"
        ". . # # # # . . \n"
        " . . # # # . . .\n")
    run_test(
        ". . . . # . . . \n"
        " . # . . . # . .\n"
        ". . . # . . . . \n"
        " . . . . . # . .\n",
        ". . # # # # . . \n"
        " . # # # # # . .\n"
        ". . # # # # # . \n"
        " . . # # # # . .\n")
if __name__ == '__main__':
    run_tests()
```
Update 1:
Removed unnecessary `-1` for third imaginary coordinate, because it doesn't change anything
Update 2,3:
Partially implemented improvements suggested by `Leaky Nun` + my own too.
[Answer]
# Python, ~~237~~ 230 bytes
**7 bytes thanks to Dennis.**
```
def f(a):i=range(len(a[0]));j=range(len(a));b,c,d=map(sorted,zip(*[[x,x+y,x-y]for y in i for x in j if"?"<a[x][y]]));return[[[a[x][y],"#"][(a[x][y]>" ")*(b[0]<=x<=b[-1])*(c[0]<=x+y<=c[-1])*(d[0]<=x-y<=d[-1])]for y in i]for x in j]
```
Port of [my answer in Pyth](https://codegolf.stackexchange.com/a/91545/48934).
Takes array of lines as input, outputs 2D array of characters.
* Python 2: [Ideone it!](http://ideone.com/FMoB1y)
* Python 3: [Ideone it!](http://ideone.com/fIlW3a)
[Answer]
# Perl, ~~128~~ 126 bytes
Includes +6 for `-0F\n`
Run with input on STDIN. Use `1` for filled, `0` for empty.
Lines do not have to be padded with spaces at the end:
```
perl -M5.010 hexafill.pl
 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 
 0 1 1 1 1 1 0 0
0 0 1 1 1 1 1 0 
 0 0 1 1 1 1 0 0
0 0 0 0 0 0 0 0 
^D
```
`hexafill.pl`
```
#!/usr/bin/perl -0F\n
$-=map{s%$=%$=^!map{/$/;grep{pos=$`;$=?$_|="!"x$`.1:!/\b.*\G./}${--$@}}@F-$-+pos,$-+pos,$-%eeg;--$-;$=||say}@F while$=--
```
Uses cube coordinates. Determine maximum and minimum during the `$= == 1` loop and fills coordinates between these bounds during the `$= == 0` loop. The first 58 loops are pointless and are only there to fill `$-` with the number of lines
[Answer]
# TSQL, 768 bytes
I wrote a query to solve this - which I found quite difficult. It is not able to compete with all the excellent shorter answer. But wanted to post it anyway for those interested. Sorry about the length of the answer - hoping codegolf is also about different approachs.
**Golfed:**
```
DECLARE @ varchar(max)=
'
. . . . # . . . 
 . # . . . # . .
. . . # . . . . 
 . . . . . # . .
. . . . . . . . 
'
;WITH c as(SELECT cast(0as varchar(max))a,x=0,y=1,z=0UNION ALL SELECT SUBSTRING(@,z,1),IIF(SUBSTRING(@,z,1)=CHAR(10),1,x+1),IIF(SUBSTRING(@,z,1)=CHAR(10),y+1,y),z+1FROM c WHERE LEN(@)>z)SELECT @=stuff(@,z-1,1,'#')FROM c b WHERE((exists(SELECT*FROM c WHERE b.y=y and'#'=a)or exists(SELECT*FROM c WHERE b.y<y and'#'=a)and exists(SELECT*FROM c WHERE b.y>y and'#'=a))and a='.')and(exists(SELECT*FROM c WHERE b.x<=x-ABS(y-b.y)and'#'=a)or exists(SELECT*FROM c WHERE b.x<=x+y-b.y and a='#'and b.y<y)and exists(SELECT*FROM c WHERE b.x<=x+b.y-y and a='#'and b.y>y))and(exists(SELECT*FROM c WHERE b.x>=x+ABS(y-b.y)and'#'=a)or exists(SELECT*FROM c WHERE b.x>=x-y+b.y and b.y<y and'#'=a)and exists(SELECT*FROM c WHERE b.x>=x-b.y+y and a='#'and b.y>y))OPTION(MAXRECURSION 0)PRINT @
```
**Ungolfed:**
```
DECLARE @ varchar(max)=
'
. . . . # . . . 
 . # . . . # . .
. . . # . . . . 
 . . . . . # . .
. . . . . . . . 
'
;WITH c as
(
  SELECT 
    cast(0as varchar(max))a,x=0,y=1,z=0
  UNION ALL
  SELECT
    SUBSTRING(@,z,1),IIF(SUBSTRING(@,z,1)=CHAR(10),1,x+1),
    IIF(SUBSTRING(@,z,1)=CHAR(10),y+1,y),
    z+1
  FROM c
  WHERE LEN(@)>z
)
SELECT @=stuff(@,z-1,1,'#')FROM c b
WHERE((exists(SELECT*FROM c WHERE b.y=y and'#'=a)
or exists(SELECT*FROM c WHERE b.y<y and'#'=a)
and exists(SELECT*FROM c WHERE b.y>y and'#'=a)
)and a='.')
and 
(exists(SELECT*FROM c WHERE b.x<=x-ABS(y-b.y)and'#'=a)
or exists(SELECT*FROM c WHERE b.x<=x+y-b.y and a='#'and b.y<y)
and exists(SELECT*FROM c WHERE b.x<=x+b.y-y and a='#'and b.y>y))
and(exists(SELECT*FROM c WHERE b.x>=x+ABS(y-b.y)and'#'=a)
or exists(SELECT*FROM c WHERE b.x>=x-y+b.y and b.y<y and'#'=a)
and exists(SELECT*FROM c WHERE b.x>=x-b.y+y and a='#'and b.y>y))
OPTION(MAXRECURSION 0) 
PRINT @
```
**[Fiddle ungolfed](https://data.stackexchange.com/stackoverflow/query/530759/highlight-the-bounding-box-part-ii-hexagonal-grid)**
[Answer]
# GNU Octave, ~~212~~, 196 bytes
Maybe not really a golfer's favourite choice language, but that's what makes the challenge, isn't it? Assuming m is taken as a char matrix: **178 bytes** stand alone and **196 if stuffed into a function**.
golfed: 
```
function k=f(m)[a,b]=size(m);[y,x]=ndgrid(1:a,1:b);t={y,y+x,x-y};k=m;s=x>0;for j=1:3l{j}=unique(sort(vec(t{j}.*(m==['#']))))([2,end]);s&=(l{j}(1)<=t{j})&(l{j}(2)>=t{j});endk(s&mod(x+y,2))=['#']end
```
ungolfed:
```
function k=f(m)
[a,b]=size(m);[y,x]=ndgrid(1:a,1:b);t={y,y+x,x-y};k=m;s=x>0;
for j=1:3
  l{j}=unique(sort(vec(t{j}.*(m==['#']))))([2,end]);
  s&=(l{j}(1)<=t{j})&(l{j}(2)>=t{j});
end
k(s&mod(x+y,2))=['#']
end
```
**Explanation** : we build a coordinate system, 3 axes - orthogonal to the hexagons sides, find max and min of each coordinate, then build a logical mask starting with 1 everywhere and logically and:ing each coordinate max and min constraint, finally re-setting each remaining "true" position to "#" char.
If you want to test it, you can just create m matrix like this:
```
m = [' . . . . . . . .. . . . # . . .  . # . . . # . .. . . # . . . .  . . . . . # . .. . . . . . . . ']; m = reshape(m,[numel(m)/6,6])';
```
and then call the f(m) and compare with m by building a matrix with both of them in:
```
['     before           after      ';m,ones(6,1)*'|',f(m)]
```
]