Form tiles in a rectangular ring

8

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:

enter image description here

  • 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

Creative Magic

Posted 2016-04-17T15:34:14.403

Reputation: 191

1Could you give examples of input/output ? – FliiFe – 2016-04-17T15:35:32.730

2Can we use a full program as well as a function? – Blue – 2016-04-17T15:36:37.640

@FliiFe Input is two integers ( cannot be negative or null ), output is a printed image like in the image attached. – Creative Magic – 2016-04-17T15:37:35.357

Can the output be a 2D array? – Doorknob – 2016-04-17T15:38:32.777

@muddyfish I would very much prefer the solution to be mathematical and not a part of some API. – Creative Magic – 2016-04-17T15:38:46.503

@Doorknob sure, that's totally valid – Creative Magic – 2016-04-17T15:39:12.490

You can use any way to display the tiles You should clarify this. Can it be ASCII art? Any characters? – Luis Mendo – 2016-04-17T15:41:00.753

@LuisMendo yes, you can use ASCII art or any characters if you want to display it in the output window/console. I'll update the question. – Creative Magic – 2016-04-17T15:42:01.253

Sorry for the bombardment, but some clarifying questions, part 1: 1) Is the expected output an image (e.g. JPG/PNG/displayed to screen) or ASCII-art? You seem to mention both in the comments, 2) Is the "4x4" or similar text part of the output? 3) Any rules on spacing between the tiles? – Sp3000 – 2016-04-17T15:47:47.677

@Sp3000 no rule how to display the image, it can be text ( but I thought Mathematica golfers might want to output an image and not text ). No rule on how to pass the input, so long as the input are two integers. No rule for spacing the tiles. Each tile can be viewed as a pixel. – Creative Magic – 2016-04-17T15:51:12.850

In that case I'd recommend giving example outputs for ASCII art as well so people know what's allowed (allowing both image and ASCII output's a bit weird, but your choice I guess). I'd also suggest removing mentions of "square" if the width/height are taken as input, since that might confuse people. – Sp3000 – 2016-04-17T15:53:45.580

Clarifications part two: 4) In the case of ASCII output, any rules on what characters are allowed to represent the tiles and the blank space in between? – Sp3000 – 2016-04-17T15:55:08.963

I also suggest that you allow either a function or a program, as usual on this site. – Luis Mendo – 2016-04-17T15:57:43.007

@Sp3000 absolutely any characters can be used to represent the tile. There's no space between the tiles in case of ASCII/text output, the tiles must be neighboring to each other. – Creative Magic – 2016-04-17T15:59:25.643

@CreativeMagic If the output is an array, can we use the language's default displaying of arrays, even if that means spaces between the numbers? (see my answer for example) – Luis Mendo – 2016-04-17T16:00:47.647

@LuisMendo it's allowed, but it's simply my own preference to have the logic of placing the tiles in the method, other than that it's pretty free. – Creative Magic – 2016-04-17T16:00:50.180

Related. Related. – Martin Ender – 2016-04-17T16:30:08.933

@CreativeMagic When you say "cannot be a line... drawing a rectangle size is not valid", do you mean that it cannot be a thin line? That is, if the "line" becomes a frame one tile thick (see my answer) is it valid? – Luis Mendo – 2016-04-17T21:11:01.577

@LuisMendo your answer is valid, I just wanted to prevent a hack that would use drawing API's of some languages for example drawRect( 0, 0, tilesX, tilesY ) – Creative Magic – 2016-04-18T00:54:03.830

Answers

6

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.

Dennis

Posted 2016-04-17T15:34:14.403

Reputation: 196 637

5

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

enter image description here

Luis Mendo

Posted 2016-04-17T15:34:14.403

Reputation: 87 464

@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 – 2016-04-17T15:44:44.427

@LuisMendo great work, but it has to have two values passes to the method – Creative Magic – 2016-04-17T15:46:29.653

@CreativeMagic Sorry. Corrected now. Maybe rephrase the challenge? "Square ring" may be confusing – Luis Mendo – 2016-04-17T15:50:43.833

@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 – 2016-04-17T15:53:50.613

@CreativeMagic Maybe "rectangular ring" instead of "square ring"? – Luis Mendo – 2016-04-17T15:54:54.307

@LuisMendo thanks, I've edited ^.^ Sorry for the confusion. – Creative Magic – 2016-04-17T15:56:07.280

@CreativeMagic No problem! – Luis Mendo – 2016-04-17T15:56:50.393

@LuisMendo Should inputs of 1 and 1 return a value of 1 or 0? – Suever – 2016-04-17T17:41:11.643

@Suever According to the first image in the OP, the output is 1 in that case – Luis Mendo – 2016-04-17T18:04:25.713

According to my interpretation the graphical output would be invalid as the tiles should not form a solid line. – Neil – 2016-04-17T19:01:55.093

1@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 – 2016-04-17T21:09:05.113

So yes, one-tile thick line is valid – Luis Mendo – 2016-04-18T09:02:57.383

@CreativeMagic Thanks for the accept, but there's a shorter answer now – Luis Mendo – 2016-04-18T09:09:42.747

4

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">

Neil

Posted 2016-04-17T15:34:14.403

Reputation: 95 035

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 – 2016-04-17T18:33:04.377

@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 – 2016-04-17T18:54:04.543

4

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])

enter image description here

Suever

Posted 2016-04-17T15:34:14.403

Reputation: 10 257

4

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.

Suever

Posted 2016-04-17T15:34:14.403

Reputation: 10 257

3

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.

Dennis

Posted 2016-04-17T15:34:14.403

Reputation: 196 637

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 – 2016-04-18T01:15:03.540

OK. When I read that 2D arrays were allowed, I didn't expect their visual representation to matter. I've edited my answer. – Dennis – 2016-04-18T02:59:55.307

@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 – 2016-04-19T14:44:29.123

3

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!

Alex A.

Posted 2016-04-17T15:34:14.403

Reputation: 23 761

2

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!

Blue

Posted 2016-04-17T15:34:14.403

Reputation: 26 661

2

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.

Martin Ender

Posted 2016-04-17T15:34:14.403

Reputation: 184 808

2

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>

edc65

Posted 2016-04-17T15:34:14.403

Reputation: 31 086

Surely !--h|!o is already an integer? Otherwise, I like the use of !o. – Neil – 2016-04-17T18:59:23.923

2

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}

Value Ink

Posted 2016-04-17T15:34:14.403

Reputation: 10 608

Sorry, you must output a ring, so no backticks allowed inside. – Erik the Outgolfer – 2016-04-18T13:23:39.547

And there goes the one byte I had been hoping to save by filling the inside with a small less-noticeable character... – Value Ink – 2016-04-18T17:44:15.207

You get an upvote, you deserve it. – Erik the Outgolfer – 2016-04-19T14:38:16.843

1

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.

Neil

Posted 2016-04-17T15:34:14.403

Reputation: 95 035

1

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))

user81655

Posted 2016-04-17T15:34:14.403

Reputation: 10 181

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 – 2016-04-17T18:15:44.837

1

Retina, 45 43 bytes

\d+
$*
S_`1(?=.* (1+))|.
T`1`#`^.+|.+$|.?¶.

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.

T`1`#`^.+|.+$|.?¶.

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.

Martin Ender

Posted 2016-04-17T15:34:14.403

Reputation: 184 808

1

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

Mego

Posted 2016-04-17T15:34:14.403

Reputation: 32 998

2If Seriously v3 isn't called Wait, Really? I'll be quite disappointed. – Alex A. – 2016-04-18T18:14:10.250

@AlexA. Did you seriously just? – cat – 2016-04-18T20:41:33.427

1

TSQL, 107 105 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
  3. adding last line(when needed)

t-clausen.dk

Posted 2016-04-17T15:34:14.403

Reputation: 2 874

1

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:

Graphical rectangle

DLosc

Posted 2016-04-17T15:34:14.403

Reputation: 21 213

0

Unicorn, 26 23 bytes

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).

Laurel

Posted 2016-04-17T15:34:14.403

Reputation: 975

0

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!

Jonah

Posted 2016-04-17T15:34:14.403

Reputation: 8 729

0

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!

Xcali

Posted 2016-04-17T15:34:14.403

Reputation: 7 671

0

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

Nahuel Fouilleul

Posted 2016-04-17T15:34:14.403

Reputation: 5 582