Form tiles in a rectangular ring

Given the input tilesX and tilesY create a method that would make a rectangular ring from the tiles.

The function must order the tiles in a ring like this:

• tilesX and tilesY are always positive integer values, cannot be 0
• tilesX and tilesY are not always equal, expect values like: 2x5, 6x3 etc.
• Checking for invalid input is not necessary
• You can use any way to display the tiles, including 2d arrays, ASCII art or printed text.
• There's no strict way how the input is passed as long as it's two integers.
• Cannot be a line, drawing a rectangle size of tilesX and tilesY pixels is not valid
• The shortest code wins
• Could you give examples of input/output ? – FliiFe Apr 17 '16 at 15:35
• Can we use a full program as well as a function? – Blue Apr 17 '16 at 15:36
• @FliiFe Input is two integers ( cannot be negative or null ), output is a printed image like in the image attached. – Creative Magic Apr 17 '16 at 15:37
• Can the output be a 2D array? – Doorknob Apr 17 '16 at 15:38
• @muddyfish I would very much prefer the solution to be mathematical and not a part of some API. – Creative Magic Apr 17 '16 at 15:38

Dyalog APL, 8 bytes

×/¨1<⊂|⍳


This monadic function train takes height and width as right arguments and returns a 2D array of 0's (border) and 1's (interior). Test it on TryAPL.

How it works

×/¨1<⊂|⍳  Right argument: h w

⍳  Generate all index pairs (1-based) of a h×w array.
⊂    Enclose (h w), so it depth matches the one of the index array.
|   For each pair (i j) compute the remainders of the division by (h w).
1<     Compare all remainders with 1.
×/¨       Reduce each pair of Booleans by multiplication.


MATL, 10 bytes

2$lO6Lt4$(


This outputs an array containing zeros and ones.

Try it online!

2$l % Implicit inputs M, N. Generate M×N array of ones O % Push number 0 6Lt % Push [2 -1] twice, corresponding to index "2:end-1" 4$(    % Fill the center of the array with value 0. Implicit display


For graphical output, add 1YG at the end to display the array as an image (13 bytes) :

2$Ol6Lt4$(1YG


Try it at MATL Online! For example,

>> matl 2$Ol6Lt4$(1YG
> 5
> 7


produces

• @Sp3000 You're right... I couldn't resist :-) Anyway, the OP has clarified that an array or ASCII art with any characters is valid output – Luis Mendo Apr 17 '16 at 15:44
• @LuisMendo great work, but it has to have two values passes to the method – Creative Magic Apr 17 '16 at 15:46
• @CreativeMagic Sorry. Corrected now. Maybe rephrase the challenge? "Square ring" may be confusing – Luis Mendo Apr 17 '16 at 15:50
• @LuisMendo not trying to make an excuse, but English is not my first language, if you can give me a better title, I'd be happy to hear it. – Creative Magic Apr 17 '16 at 15:53
• @Neil The OP says Cannot be a line. I took that as "it cannot be a line without the appropriate thickness, corresponding to one tile". I'll ask them – Luis Mendo Apr 17 '16 at 21:09

HTML/JS/CSS, 198 194 bytes

Graphical output version. The byte count doesn't include f= nor the three <input> elements which are used for demonstration purposes only. Saved 3 bytes thanks to @IsmaelMiguel.

f=(n,m)=>{with(d.style)width=n*25+'px',height=m*25+'px'}
<input id=w placeholder=width><input id=h placeholder=height><input type=button value=Go! onclick=f(w.value,h.value)>
<div id=d style="border-image:radial-gradient(#fff 0,#fff 0)0 fill/25px;background:radial-gradient(#000 0,#000 8px,#fff 9px)0 0/25px 25px">

• Can't f=(n,m)=>{d.style.width=n*25+'px';d.style.height=m*25+'px';} be simplified to f=(n,m)=>with(d.style)width=n*25+'px',height=m*25+'px';? – Ismael Miguel Apr 17 '16 at 18:33
• @IsmaelMiguel The with does save me 3 bytes but I still need the {}s. On the other hand the ; is unnecessary so I removed that too. – Neil Apr 17 '16 at 18:54

MATL, 10 bytes

2$l3XyZ+3=  Input arguments are height and width as integers. The output is a matrix of size height x width where the boundary tiles are 0 and the inner values are 1. Try it Online! Explanation Same logic as my other answer with fewer bytes.  % Grab two input parameters implicitly 2$l     % Create a matrix of ones that has the dimensions specified as inputs
3       % Number literal 3
Xy      % Create a 3x3 identity matrix
Z+      % Perform 2D convolution (preserving size)
3=      % Create a logical matrix where values == 3 are 1 and 0 otherwise (boundary)
% Implicitly display output.


MATLAB, 32 31 bytes

@(x)conv2(ones(x),eye(3),'s')>2


This creates an anonymous function which can then be run as ans([4 5]) within the workspace.

Input is [height, width] and output is a matrix with 1 in the center and 0 for the boundary.

The way that this works is a matrix of ones the size of the input is created. It is then convolved with a 3 x 3 identify matrix with ones on the diagonal. We use the same input to conv2 (shortened to 's' here) to keep the result the same size as the input.

We then want to convert the output to a binary value with 0 around the boundary and 1 inside. We use the inequality >2 because all edge pixels will have a result < 3 and all non-boundary elements will have a result equal to 3.

For graphical output:

@(x)imagesc(conv2(ones(x),eye(3),'s')>8)
ans([6,9])


Jelly, 10 bytes

p%€,>1P€G


Returns a grid of 0's (border) and 1's (interior). Try it online!

How it works

p%€,>1P€sG  Main link. Arguments: h (height), w (width)

p           Cartesian product; return all pairs in [1, ..., h] × [1, ..., w].
,        Yield the pair [h, w].
%€         For each pair [i, j] in the product, compute [i % h, j % w].
>1      Compare all resulting moduli with 1.
P€    Compute the product of each pair of Booleans.
s   Split the resulting flat list into rows of length w.
G  Display the results in a 2D grid.

• This answer is great, but it has to visually be a rectangular ring. While it's fine to use arrays, strings etc., it has to look like a ring on the screen when you run it. – Creative Magic Apr 18 '16 at 1:15
• OK. When I read that 2D arrays were allowed, I didn't expect their visual representation to matter. I've edited my answer. – Dennis Apr 18 '16 at 2:59
• @Dennis "[I]t has to look like a ring on the screen when you run it". That means spaces should be used? – Erik the Outgolfer Apr 19 '16 at 14:44

Julia, 46 34 bytes

f(n,m)=[n>i>1<j<m for i=1:n,j=1:m]


This is a function that accepts two integers and returns a 2-dimensional boolean array.

We construct an n × m matrix using an array comprehension with a double for loop. For each index from 1 to n and 1 to m, i.e. each element of the matrix, we set the value to true if n > i > 1 and 1 < j < m. This is true everywhere but the boundaries, so the resulting array will have trues in the middle and falses around the border.

Examples:

julia> f(n,m)=[n>i>1<j<m for i=1:n,j=1:m]
f (generic function with 1 method)

julia> f(4,4)
4x4 Array{Bool,2}:
false  false  false  false
false   true   true  false
false   true   true  false
false  false  false  false

julia> f(1,1)
1x1 Array{Bool,2}:
false

julia> f(2,5)
2x5 Array{Bool,2}:
false  false  false  false  false
false  false  false  false  false


Saved 12 bytes thanks to Dennis!

CJam, 20 bytes

l~S*a*{3a.f|W%z}4*N*


Input should be in the form height width, output is an ASCII grid using spaces for the centre and # for the boundary.

Test it here.

Explanation

l~       e# Read and evaluate input, dumping h and w on the stack.
S*       e# Create a string of w spaces.
a*       e# Create an array of h copies of that string.
{        e# Repeat this block 4 times...
3a.f|  e#   For each character in the first row, take its bitwise OR with 3, turning
e#   spaces into # and leaving # unchanged.
W%z    e#   Reverse and transpose the grid, rotating it by 90 degrees.
}4*
N*       e# Join the lines of the result with linefeeds.


Pyke, 16 15 bytes

jQ]Uajt%!RQt%!|


Try it here!

Explanation:

                - Q = eval_input()
j               - j = eval_input()
jQ]             - [Q,j]
U            - create a 3d array sized Q by j with coords
a           - for each coord (2d for)
jt%!       -   not (coord_1 % j-1)
| -  ^ or V
Qt%!  -   not (coord_2 % Q-1)


For prettified output, use this code.

Or 13 bytes with a zeroed out mask round the edge (middle chars non-zero)

jQ]Uajt%RQt%&


Try it here!

JavaScript (ES6), 80 82 85

Edit 3 bytes saved thx @Neil
Edit 2 bytes saved using reduce for once

Anonymous function returning a multi line string

(w,h)=>[...Array(h)].reduce(o=>o+(w>1?'O'+' O'[!--h|!o].repeat(w-2):'')+O
,'')


Test

f=(w,h)=>[...Array(h)].reduce(o=>o+(w>1?'O'+' O'[!--h|!o].repeat(w-2):'')+O
,'')

function test(){
var [w,h] = I.value.match(/\d+/g)
w=+w,h=+h // convert to numeric
O.textContent=f(w,h)
}

test()
<input value='5 4' id=I><button onclick='test()'>Test</button><pre id=O></pre>

• Surely !--h|!o is already an integer? Otherwise, I like the use of !o. – Neil Apr 17 '16 at 18:59

Ruby, 63 bytes

Anonymous function, prints to STDOUT. Border is #.

->x,y{h=?#;puts t=h*x,y>1?[[h+(x<2?'':' '*(x-2)+h)]*(y-2),t]:p}

• Sorry, you must output a ring, so no backticks allowed inside. – Erik the Outgolfer Apr 18 '16 at 13:23
• And there goes the one byte I had been hoping to save by filling the inside with a small less-noticeable character... – Value Ink Apr 18 '16 at 17:44
• You get an upvote, you deserve it. – Erik the Outgolfer Apr 19 '16 at 14:38

JavaScript (ES6), 97 bytes

(n,m)=>Array(n).fill(' '.repeat(m).replace(/^ | $/g,0)).join .replace(/^.+|.+$/g,'0'.repeat(m))


Creates a ring of 0s. Probably a terrible approach but I wanted to avoid edge cases.

JavaScript (ES6), 77 bytes

h=>w=>[...Array(i=h)].map(_=>(a=Array(w).fill(h-i--&&i?0:1),a[0]=a[w-1]=1,a))

• I don't like the array of array output (even if it's allowed). What I see in console is f(4)(4) -> Array [ Array[4], Array[4], Array[4], Array[4] ] – edc65 Apr 17 '16 at 18:15

Retina, 45 43 bytes

\d+
$* S_1(?=.* (1+))|. T1#^.+|.+$|.?¶.


Input should be in the form height width, output is an ASCII grid using 1 for the centre and # for the boundary.

Try it online!

Explanation

\d+
$*  Convert each number N to a string of N ones (i.e. convert the input to unary). S_1(?=.* (1+))|.  Match each 1 in height and replace it with width, while also matching everything else and removing it. We do this by abusing a split stage. This creates a w x h grid. T1#^.+|.+$|.?¶.


Finally we replace every 1 with a # that is either found in the first line, the last line or at the beginning or end of a line.

Actually, 23 bytes

;'#*;))¬' *'#;)@+(+nXX(


Try it online!

This approach is very similar to my approach in this related challenge.

Explanation:

;'#*;))¬' *'#;)@+(+nXX(
(implicit) push all input to stack
;'#*                     push a string containing X #s
;))                  dupe, and push both to bottom of stack
¬' *              push a string containing (X-2) spaces
'#;)@+(+      add a # to the front and the back of the string
nXX   make (Y-2) copies
(  bring one of the "#"*X strings back to the top
(implicit) pop and print each stack item, separated by newlines

• If Seriously v3 isn't called Wait, Really? I'll be quite disappointed. – Alex A. Apr 18 '16 at 18:14
• @AlexA. Did you seriously just? – cat Apr 18 '16 at 20:41

QBasic, 69 bytes

INPUT x,y
FOR i=1TO y
FOR j=1TO x
?i MOD y<2OR j MOD x<2;
NEXT
?
NEXT


Takes dimensions as width,height. The boolean value from the is-it-on-the-border test is simply printed: -1 for true and 0 for false. A sample run looks like:

? 5,3
-1 -1 -1 -1 -1
-1  0  0  0 -1
-1 -1 -1 -1 -1


Bonus: Graphical version, 88 bytes

INPUT x,y
SCREEN 9
FOR i=1TO y
FOR j=1TO x
PSET(j*3,i*3),i MOD y<2OR j MOD x<2
NEXT
NEXT


I believe this counts as "not a line." When the MOD expression is false (0), PSET plots a black pixel; when it's true (-1), PSET apparently plots a white pixel. Here's 17,31, shown at 2x size:

TSQL, 107105 97 bytes

DECLARE @ INT=3,@y INT=5

PRINT REPLICATE(1,@)+ISNULL('
'+REPLICATE('1'+ISNULL(SPACE(@-2),'')+'1
',@y-2)+REPLICATE(1,@),'')

1. generating first line
2. adding hollow lines + line breaks

P3G$PG@PS@S$L2B$T1B@T1N  Because who doesn't like unicorns?! Explanation ("list program" output): P3 Paint current square with 3 G$P Get: sets $from input P G@P Get: sets @ from input P S@ Subtract 1 from @ S$  Subtract 1 from $L2 ~Loop 2 times B$  ~Brush $more square T1 ~Turn 1 right angle clockwise B@ ~Brush @ more square T1 ~Turn 1 right angle clockwise N ~Next (loop)  Output for tilesX = 3, tilesY = 5: Note: This version only works for tilesX up to 6 and tilesY up to 5. The question does not mention what range we need to support though, so I'm assuming this is OK. Otherwise, a small addition to the program produces this alternative, which supports a slightly larger range: Unicorn, 30 27 bytes x0y9P3G$PG@PS@S$L2B$T1B@T1N


By adding x0y9, which starts the box at (0,9), the program works for tilesX up to 9 and tilesY up to 9 (because input only goes up to 9).

J, 16 bytes

0(<2#<<0 _1)}$&1  Use shape $ to create a rectangle of all ones the size of the inputs, and then use the complementary form of Amend } to turn the interior to zeros.

Try it online!

Perl 5, 76 + 1 (-a) = 77 bytes

print(1x($a=$F[0]),$/,((1,$"x($a-2),1 x($a>1),$/)x($F[1]-2),1x$a)x($F[1]>1))


Try it online!

Perl 5, 45 + 1 (-p) = 46 bytes

$_=join$/,(1x$_)x<>;1while s/ .+\K1(?=.+ )/ /  following 45 bytes doesn't handle tileY=1 $_=1x<>.$/;say$_.s/(?!^.|.$)./ /gr x(<>-2).$_


Try it online