27
\$\begingroup\$

This is a 3x3 ASCII jigsaw puzzle:

 _____ _____ _____
|    _|     |_    |
|   (_   _   _)   |
|_   _|_( )_|_   _|
| (_) |_   _| (_) |
|  _   _) (_   _  |
|_( )_|_   _|_( )_|
|    _| (_) |_    |
|   (_       _)   |
|_____|_____|_____|

This is also a 3x3 ASCII jigsaw puzzle:

 _____ _____ _____
|     |_   _|     |
|  _   _) (_   _  |
|_( )_|_   _|_( )_|
|    _| (_) |_    |
|   (_   _   _)   |
|_   _|_( )_|_   _|
| (_) |_   _| (_) |
|      _) (_      |
|_____|_____|_____|

Each line in a ASCII jigsaw puzzle (excluding the edge cases i.e. the pieces literally on the edges) consists of the following pattern:

   _           _           _
 _( )_ _   _ _( )_ _   _ _( )_
|_   _| (_) |_   _| (_) |_   _|
 _) (_   _   _) (_   _   _) (_
|_   _|_( )_|_   _|_( )_|_   _| ...
  (_)         (_)         (_)

Given 2 integers H and W where H is the height (vertical amount) and W is the width (horizontal amount) and H and W are >1 output a possible HxW ASCII jigsaw puzzle.

Examples

Test Case 1

Input: 2, 4

Output:

 _____ _____ _____ _____
|     |_   _|     |_    |
|  _   _) (_   _   _)   |
|_( )_|_   _|_( )_|_   _|
|    _| (_) |_   _| (_) |
|   (_       _) (_      |
|_____|_____|_____|_____|

Test Case 2

Input: 4, 4

Output:

 _____ _____ _____ _____
|     |_   _|     |_    |
|  _   _) (_   _   _)   |
|_( )_|_   _|_( )_|_   _|
|    _| (_) |_   _| (_) |
|   (_   _   _) (_   _  |
|_   _|_( )_|_   _|_( )_|
| (_) |_   _| (_) |_    |
|  _   _) (_   _   _)   |
|_( )_|_   _|_( )_|_   _|
|    _| (_) |_   _| (_) |
|   (_       _) (_      |
|_____|_____|_____|_____|

Test Case 3

Input: 3, 5

Output:

 _____ _____ _____ _____ _____
|     |_   _|     |_   _|     |
|  _   _) (_   _   _) (_   _  |
|_( )_|_   _|_( )_|_   _|_( )_|
|    _| (_) |_   _| (_) |_    |
|   (_   _   _) (_   _   _)   |
|_   _|_( )_|_   _|_( )_|_   _|
| (_) |_   _| (_) |_   _| (_) |
|      _) (_       _) (_      |
|_____|_____|_____|_____|_____|

Test Case 4

Input: 2, 2

Output:

 _____ _____
|    _|     |
|   (_   _  |
|_   _|_( )_|
| (_) |_    |
|      _)   |
|_____|_____|

Clarifications

  • The height and width for each puzzle piece should not be scaled up or down.
  • With H and W being greater than one, the smallest dimensions possible are 2x2 (see IO 4).
  • You can have a full program or a function.
  • The input will be 2 lines with H on the 1st and W on the 2nd if you're using a function you can have them in the parameters.
  • Output to stdout (or something similar).
  • This is code-golf so shortest answer in bytes wins.
\$\endgroup\$
10
  • \$\begingroup\$ Must the tabs of the pieces be in alternating directions? \$\endgroup\$
    – Zgarb
    Commented Dec 29, 2016 at 11:44
  • \$\begingroup\$ Should I output at random or can I output just one puzzle each time around? If at random, should all puzzles be uniformly available? \$\endgroup\$
    – user48538
    Commented Dec 29, 2016 at 11:47
  • \$\begingroup\$ @Zgarb yes, i edited in the basic pattern each line in the jigsaw puzzle follows \$\endgroup\$
    – Bobas_Pett
    Commented Dec 29, 2016 at 11:58
  • \$\begingroup\$ @zyabin101 you just need to output a possible "ASCII jigsaw puzzle" so only 1 output for 1 input \$\endgroup\$
    – Bobas_Pett
    Commented Dec 29, 2016 at 11:59
  • 1
    \$\begingroup\$ First attempt is looking like it is going to end up at about a megabyte. Nice question. \$\endgroup\$
    – ElPedro
    Commented Dec 29, 2016 at 20:14

6 Answers 6

6
\$\begingroup\$

JavaScript (ES6) 272 277 271

Edit bug fix

Edit 2 saved 6 bytes thx @L.Serné

Edit 3 bug fix again

(w,h,z=(s,q=3,i=h)=>'|  '.slice(0,q)+s.repeat(w).substr(i%2*6+q,w*6-q-~-q)+`  |
`.slice(~q))=>eval("t=z(' _____',0,0)+z('|_   _|     ',2,--h)+z(b=' _) (_   _  ')+z(c='|_   _|_( )_',0);for(a='|_   _| (_) ';--h;)t+=z(a,2)+z(b)+z(c,0)")+z(a,2)+z(' _) (_      ')+z('|_____',1)

Less golfed

(w,h,
  z=(s,q=3,i=h)=>'|  '.slice(0,q)+s.repeat(w).substr(i%2*6+q,w*6-q-~-q)+'  |\n'.slice(~q),
  a='|_   _| (_) ',
  b=' _) (_   _  ',
  c='|_   _|_( )_',
  t=z(' _____',0,0)+z('|_   _|     ',2,--h)+z(b)+z(c,0)
)=>{
  for(;--h;)
    t+=z(a,2)+z(b)+z(c,0);
  return t+z(a,2)+z(' _) (_      ')+z('|_____',1)
}

Test

F=
(w,h,z=(s,q=3,i=h)=>'|  '.slice(0,q)+s.repeat(w).substr(i%2*6+q,w*6-q-~-q)+`  |
`.slice(~q))=>eval("t=z(' _____',0,0)+z('|_   _|     ',2,--h)+z(b=' _) (_   _  ')+z(c='|_   _|_( )_',0);for(a='|_   _| (_) ';--h;)t+=z(a,2)+z(b)+z(c,0)")+z(a,2)+z(' _) (_      ')+z('|_____',1)

function update() {
  var w=+W.value,h=+H.value
  O.textContent=F(w,h)
}

update()
W<input id=W value=2 oninput='update()' type=number min=2>
H<input id=H value=2 oninput='update()' type=number min=2>
<pre id=O></pre>

\$\endgroup\$
6
  • \$\begingroup\$ Very nice! The golfed version is giving me trouble, though: Nx2 does not work (e.g. 3x2 yields undefined| | () |_ | | (_ _) | |_____|_____|_____| and submitting an odd height results in the top-right piece missing its top border. Looks like something got lost in golf-lation. Edit: the "odd height" bug results from both golfed and non-golfed code. \$\endgroup\$ Commented Dec 30, 2016 at 0:00
  • \$\begingroup\$ @BenceJoful Not enough test after the last golfing. Now fixed \$\endgroup\$
    – edc65
    Commented Dec 30, 2016 at 7:50
  • \$\begingroup\$ You could move the declaration of last argument (t) and the fourth argument (a) to the for loop (and move the declaration of b and c inside the declaration of t like this: for(t=z(' _____',0,0)+z('|_ _| ',2,--h)+z(b=' _) (_ _ ')+z(c='|_ _|_( )_',0);--h;a='|_ _| (_) '). This saves 4 comma's, so you end up with only 273 characters. EDIT: The test snippet is still bugged... \$\endgroup\$
    – Luke
    Commented Dec 30, 2016 at 12:49
  • \$\begingroup\$ @L.Serné bugged how? You cannot put t=... inside the for, it fails for h==2. It's exactly the bug I fixed today. \$\endgroup\$
    – edc65
    Commented Dec 30, 2016 at 13:19
  • 1
    \$\begingroup\$ np, I played around with your code, and the cause of the undefined turned out to be declaring a in the last part of the for loop. I changed the code a bit, and ended up with this. You should be able to integrate that with the eval for another 2B save. (w,h,z=(s,q=3,i=h)=>'| '.slice(0,q)+s.repeat(w).substr(i%2*6+q,w*6-2*q+1)+' |\n'.slice(~q),a='|_ _| (_) ')=>{for(t=z(' _____',0,0)+z('|_ _| ',2,--h)+z(b=' _) (_ _ ')+z(c='|_ _|_( )_',0);--h;)t+=z(a,2)+z(b)+z(c,0);return t+z(a,2)+z(' _) (_ ')+z('|_____',1)} (276 B). \$\endgroup\$
    – Luke
    Commented Dec 30, 2016 at 13:55
5
\$\begingroup\$

Python, 513 bytes

def r(m,n):
 r=3*m
 c=6*n
 l=3-(n%2)*3
 z=[1,2,3,4,5,0]
 p=zip
 return"\n".join("".join(" |_()"[[[((j%6,i%3)in[(1,0),(5,0)])*2or((j%6,i%3)in[(0,1),(0,0)])or((j%4,i%6)in[(1,1),(1,2),(3,4),(3,5)])*2or((i%6,j%12)in p(z,[10,2,10,4,8,4]))*4or((i%6,j%12)in p(z,[8,4,8,2,10,2]))*3,1,0][j in[0,c]or((j,i%6)in p([1,1,2,2],[1,2]*2)+p([c-1,c-1,c-2,c-2],[1+l,2+l]*2)or(i,j%12)in[(1,8),(1,9),(1,10),(2,8),(2,9),(2,10),(r-1,9)]or(i,j%12)==(r-1,3+6*(m%2)))*2],2*(j%6>0)or i>0][i in[0,r]]]for j in range(c+1))for i in range(r+1))

Perhaps more of an exercise in obfuscation than in golfing, this one works by deciding what character each (x,y) coordinate goes to rather than building up each pattern by string. Ungolfed it looks like

char_codes = " |_()"
def base(row, col):
    if col % 6 in [5] and row % 3 in [0, 2]:
        return 1
    if col % 6 in [0, 4] and row % 3 in [2]:
        return 2
    return 0

def underscores(row, col):
    if col % 4 in [0] and row % 6 in [0, 1] or col % 4 in [2] and row % 6 in [3, 4]:
        return 2
    return 0

def parentheses(row, col):
    if (row % 6, col % 12) in [(0, 9), (1, 1), (2, 9), (3, 3), (4, 7), (5, 3)]:
        return 4
    if (row % 6, col % 12) in [(0, 7), (1, 3), (2, 7), (3, 1), (4, 9), (5, 1)]:
        return 3
    return 0

def value(row, col):
    return base(row, col) + underscores(row, col) + parentheses(row, col)

def new_value(last_row, last_col, row, column):
    if row in [0, last_row]:
        return 2*(column % 6 > 0) or row>0
    if column in [0, last_col]:
        return 1
    if column in [1,2] and row % 6 in [1, 2]:
        return 0
    if column in [last_col - 1, last_col - 2] and row % 6 in [[4,5],[1,2]][last_col%12>0]:
        return 0
    if row in [1, 2] and column % 12 in [8,9,10]:
        return 0
    if row == last_row - 1 and column % 12 == 9:
        return 0
    return value(row - 1, column - 1)

def puzzle(rows, cols):
    last_row = rows * 3
    last_col = cols * 6
    return "\n".join("".join(new_value(last_row, last_col, row, col) for col in range(last_col + 1)) for row in range(last_row + 1))

The patterns themselves look like

we can see this as a lookup table from integers with columns taken mod 6 and rows mod 3

 012345
0     |
1
2_   _|

 0123
0_
1_
2
3  _
4  _
5

 0123456789AB
0       ( )
1 ) (
2       ( )
3 ( )
4       ) (
5 ( )

This strategy of combining different patterns has not really worked out for me here because expressing them is quite cumbersome (though I think I could have golfed more) and because the edge cases take up so many characters to fix. I'm putting this up regardless because it took me a minute and it might be of interest.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You are able to save 7 bytes by putting the entire thing on 1 line separated by semicolons \$\endgroup\$
    – Blue
    Commented Dec 30, 2016 at 14:56
  • \$\begingroup\$ @Blue Thanks mate, it's been a while since my last golf and I've forgotten some tricks. \$\endgroup\$
    – walpen
    Commented Dec 30, 2016 at 18:59
2
\$\begingroup\$

Mathematica, 384 bytes

(m=#~Mod~2&;a=#~Array~Y&;s=(h="   _  ")[o="|_( )_",z="|_   _",w=" _) (_",z,p="| (_) "];l="|  _  "[o,"|    _",u="|   (_",z,p];r=h[o,q="|_    ",t=" _)   ",z,p];{X,Y}=#;a[" _____"&]<>" \n"<>Join[{a[If[#<Y,z,q]["|     "][[m@#]]&]},Table[Which[y<2,l,y<Y,s,0<1,r][[Mod[x+3y,6]]],{x,3,3X-1},{y,1,Y}],{a[If[#<2,"|     "[u],"      "[If[#<Y,w,t]]][[m[X+#]]]&],a["|_____"&]}]~Riffle~"|\n"<>"|")&

Unnamed function taking an ordered pair of integers as its argument, and returning a string containing appropriate newlines. With spaces and newlines added:

(m = Mod[#1, 2] &; a = Array[#1, Y] &; 
 s = (h = "   _  ")[o = "|_( )_", z = "|_   _", w = " _) (_", z, p = "| (_) "];
 l = "|  _  "[o, "|    _", u = "|   (_", z, p]; 
 r = h[o, q = "|_    ", t = " _)   ", z, p];
 {X, Y} = #1; 
 a[" _____" &] <> " \n" <>
 Riffle[
   Join[
     {a[If[#1 < Y, z, q]["|     "][[m[#1]]] &]}, 
     Table[
       Which[y < 2, l, y < Y, s, 0 < 1, r][[Mod[x + 3 y, 6]]],
       {x, 3, 3 X - 1}, {y, 1, Y}
     ],
     {a[If[#1 < 2, "|     "[u], "      "[If[#1 < Y, w, t]]][[m[X + #1]]] &],
     a["|_____" &]}
   ], "|\n"
 ] <> "|") &
\$\endgroup\$
2
\$\begingroup\$

Batch, 562 528 bytes

@echo off
set t=!  !
set w=%2
set a= _) (_!_   _! (_) !        _  !_( )_!_   _ _) (_
call:d "!     !_   _" 2 " _____ _____" 4
for /l %%j in (2,1,%1)do call:t
call:d "!_____!_____" 1 "%a:~18,6%%a:~-6%" 3
exit/b
:t
set a=%a:~24%%a:~0,24%
call:d "%a:~6,6%%a:~30,6%" 1 "%a:~0,6%%a:~24,6%" 3
call:c "%a:~12,6%%a:~36,6%" 2
exit/b
:d
call:c %3 %4
:c
set s=
for /l %%i in (%w%,-2,1)do call set s=%~1%%s%%&if %%i==1 call set s=%%s:~6%%
if %2 lss 4 set s=%s%!&call set s=%%t:~0,%2%%%%s:~%2,-%2%%%%t:~-%2%%
echo %s:!=^|%

Proved resistant to golfing, as the repetition tended to cost too many bytes to eliminate, for example, I manually pass in the line number mod 3 because it's too expensive to compute. Edit: Furthermore, I had inadvertently golfed extra |s every third line, which is incorrect. Fixing this actually saved me 2 bytes (4 bytes on my original version). Explanation: a contains various bits of jigsaw. The :t function swaps them over each set of three rows, then extracts the required substrings which the :c function then repeats in pairs, but deleting the first column if w is odd. The left and right edge cases are then handled before the row is output. The other edge case is the very first row in which the !s are changed to spaces instead of |s (the code avoids |s because they are tricky to handle in Batch).

\$\endgroup\$
2
\$\begingroup\$

Befunge, 263 243 bytes

|_   _| (_)
 _) (_   _
|_   _|_( )_

|
|
|_____
 _____
>&:08p3*28p&:18p6*38pv
@#!`g82:,_v0+55+1p84:<_
\g82+g84<| `g83:+1,g\%*6-g852+*6/3+2g84\++%3+2\!:g84*4p85:!!+*`0%6\!*`
6/08g+2%^>>::::48g3/2%2*`\48g3/18g+2%!2*+38g\`*!48g3%0`*\::6/2%!48g\`\

Try it online!

The way this works is by iterating over the x,y coordinates of the area we want to output, and mapping those x,y values to u,v coordinates in the puzzle pattern (stored on the first three lines of the playfield). This mapping is achieved with the following basic formulae:

u = (x+(y+2)/3*6) % 12
v = (y+2)%3 + (y==0)

The u coordinate repeats every 12 columns, but also needs to be offset by 6 every 3 rows. The v coordinate repeats every 3 rows, but we add y==0 to the value so the very first row can be rendered as a special case. However, to handle the edges, we need to introduce an additional boolean value, e, which is true for various edge locations, and which adjusts the formulae as follows:

u = (x+(y+2)/3*6) % (e?6:12)
v = (y+2)%3 + (y==0) + e*4

Thus if we're on an edge, we add 4 to the v coordinate so as to use the simpler edge pattern on lines 5 to 7. And we also now need to mod the u coordinate by 6 rather than 12, since this edge pattern repeats every 6 columns.

As for the e value itself, that requires a fairly complex formula, since the edge locations encompass a somewhat irregular area of the puzzle border.

elr = (x <= 2*y/3%2 or x >= w-2*!(y/3+cols)%2) and (y%3 > 0)
etb = (y <= !(x/6%2) or y >= h-(x/6+rows)%2) and (x%6 > 0)
e   = elr or etb

Without going into too much detail, the basic breakdown is that elr matches the edge locations along the left and right borders, while etb matches locations along the top and bottom borders.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 285 bytes

f=
(h,w,a=` _) (_|_   _| (_)    _  |_( )_|_   _      |     |_____`.match(/.{6}/g),g=(l,r,j)=>a[7].slice(0,j)+(a[l]+a[r]).repeat(w).slice(j,w*6+1-j)+`  |`.slice(-j))=>[` _____`.repeat(w),g(1,7,2),...[...Array(--h*3)].map((_,i)=>g(i%6,(i+3)%6,"312"[i%3])),g(h=h%2*6,6-h,3),g(8,8,1)].join`
`
<div oninput=o.textContent=+h.value&&+w.value?f(h.value,w.value):''><input id=h type=number min=1><input id=w type=number min=1><pre id=o>

This is a port of my Batch answer, just to see whether it competes with @edc65's answer. The annoyingly long string contains jigsaw pieces. The first six pieces represent two rows of one column of the interior of the jigsaw. The seventh piece is used for the penultimate line of the jigsaw, in place of the fourth piece. The eighth piece is used on the second line of the jigsaw, in place of the fifth piece, and also does double duty as the left edge of the jigsaw. The ninth piece is the last line of the jigsaw.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.