ASCII Jigsaw Puzzle

27

Este é um 3x3quebra-cabeça ASCII:

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

Este também é um 3x3quebra-cabeça ASCII:

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

Cada linha em um quebra-cabeça ASCII (excluindo as caixas de arestas, ou seja, as peças literalmente nas arestas) consiste no seguinte padrão:

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

Dados 2 números inteiros He Wonde Hestá a altura (quantidade vertical) e Wa largura (quantidade horizontal) He Wsão >1emitidos um possível HxWquebra-cabeça ASCII.

Exemplos

Caso de teste 1

Entrada: 2, 4

Saída:

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

Caso de teste 2

Entrada: 4, 4

Saída:

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

Caso de teste 3

Entrada: 3, 5

Saída:

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

Caso de teste 4

Entrada: 2, 2

Saída:

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

Esclarecimentos

  • A altura e a largura de cada peça do quebra-cabeça não devem ser redimensionadas para cima ou para baixo.
  • Com He Wsendo maior que uma, as menores dimensões possíveis são 2x2(consulte a IO 4).
  • Você pode ter um programa completo ou uma função.
  • A entrada será de 2 linhas com Ha 1ª e Wa 2ª se você estiver usando uma função, poderá tê-las nos parâmetros.
  • Saída para stdout (ou algo semelhante).
  • Este é o código-golfe, pelo que a resposta mais curta em bytes vence.
Bobas_Pett
fonte
As guias das peças devem estar em direções alternadas?
Zgarb
Devo imprimir aleatoriamente ou posso imprimir apenas um quebra-cabeça de cada vez? Se aleatoriamente, todos os quebra-cabeças devem estar uniformemente disponíveis?
user48538
@ Zgarb sim, editei no padrão básico que cada linha do quebra-cabeça segue #
Bobas_Pett
@ zyabin101 você só precisa emitir um possível "puzzle ASCII-cabeça" para apenas 1 saída para 1 entrada
Bobas_Pett
1
A primeira tentativa parece que vai acabar em um megabyte. Boa pergunta.
ElPedro

Respostas:

6

JavaScript (ES6) 272 277 271

Editar correção de bug

Editar 2 salvos 6 bytes thx @ L.Serné

Edite 3 correções de erros novamente

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

Menos golfe

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

Teste

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>

edc65
fonte
Muito agradável! A versão golfada está me causando problemas: Nx2 não funciona (por exemplo, 3x2 produz indefinido | | ( ) | _ | | (_ _) | | _____ | _____ | _____ | e o envio de uma altura ímpar resulta no canto superior direito peça faltando sua borda superior.Parece que algo se perdeu no campo de golfe.Edit: o bug de "altura ímpar" resulta do código do golfe e do não-
golfe.- Bence Joful 30/12/16
@BenceJoful Teste insuficiente após o último golfe. Agora corrigido
edc65
Você pode mover a declaração do último argumento (t) e o quarto argumento (a) para o loop for (e mover a declaração de bec na declaração de t assim: for(t=z(' _____',0,0)+z('|_ _| ',2,--h)+z(b=' _) (_ _ ')+z(c='|_ _|_( )_',0);--h;a='|_ _| (_) ')1. Isso salva 4 vírgulas, assim você termina com . apenas 273 caracteres EDIT: O trecho de teste ainda está grampeada ...
Lucas
@ L.Serné bugado como? Você não pode colocar t=...dentro do for, ele falha para h == 2. É exatamente o bug que corrigi hoje.
Edc65
1
np, eu brinquei com seu código e a causa do undefinedresultado foi declarada ana última parte do forloop. Mudei um pouco o código e acabei com isso. Você deve poder integrar isso ao eval para outro salvamento de 2B. (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).
Luke
5

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

Talvez seja mais um exercício de ofuscação do que de golfe, este funciona decidindo para qual caractere cada (x,y)coordenada vai, em vez de construir cada padrão por sequência. Ungolfed parece

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

Os padrões se parecem

podemos ver isso como uma tabela de pesquisa de números inteiros com colunas obtidas no mod 6 e linhas mod 3

 012345
0     |
1
2_   _|

 0123
0_
1_
2
3  _
4  _
5

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

Essa estratégia de combinar diferentes padrões realmente não funcionou para mim aqui, porque expressá-los é bastante complicado (embora eu ache que poderia ter jogado mais) e porque os casos extremos ocupam muitos caracteres para corrigir. Estou colocando isso de qualquer maneira, porque demorei um minuto e pode ser do seu interesse.

Walpen
fonte
1
Você é capaz de salvar 7 bytes colocando a coisa toda em uma linha separada por ponto
Blue
@ Blue Obrigado cara, já faz um tempo desde o meu último golfe e eu esqueci alguns truques.
walpen
2

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

Função sem nome, tendo como argumento um par ordenado de números inteiros e retornando uma sequência contendo novas linhas apropriadas. Com espaços e novas linhas adicionados:

(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"
 ] <> "|") &
Greg Martin
fonte
2

Lote, 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:!=^|%

Resistente ao golfe, como a repetição costumava custar muitos bytes para eliminar, por exemplo, passo manualmente o número da linha mod 3, porque é muito caro calcular. Edit: Além disso, eu inadvertidamente jogava golfe extra |a cada terceira linha, o que está incorreto. Corrigir isso realmente me salvou 2 bytes (4 bytes na minha versão original). Explicação: acontém vários bits de quebra-cabeças. A :tfunção os troca por cada conjunto de três linhas e extrai as substrings necessárias que a :cfunção repete em pares, mas excluir a primeira coluna se wfor ímpar. Os casos da borda esquerda e direita são tratados antes da saída da linha. A outra aresta é a primeira linha na qual os !s são alterados para espaços em vez de|s (o código evita |s porque são difíceis de manipular no Lote).

Neil
fonte
2

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\`\

Experimente online!

A maneira como isso funciona é iterando sobre as coordenadas x, y da área que queremos produzir e mapeando esses valores x , y para coordenadas u , v no padrão de quebra-cabeça (armazenado nas três primeiras linhas do campo de jogo). Esse mapeamento é realizado com as seguintes fórmulas básicas:

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

A coordenada u repete-se a cada 12 colunas, mas também precisa ser deslocada em 6 a cada 3 linhas. A coordenada v se repete a cada 3 linhas, mas adicionamos y==0ao valor para que a primeira linha possa ser renderizada como um caso especial. No entanto, para manipular as arestas, precisamos introduzir um valor booleano adicional, e , que é verdadeiro para vários locais de arestas e que ajusta as fórmulas da seguinte maneira:

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

Portanto, se estivermos em uma aresta, adicionamos 4 à coordenada v para usar o padrão de aresta mais simples nas linhas 5 a 7. E agora também precisamos modificar a coordenada u por 6 em vez de 12, pois esse padrão de aresta repete a cada 6 colunas.

Quanto ao valor e em si, isso requer uma fórmula bastante complexa, pois os locais das bordas abrangem uma área um tanto irregular da borda do quebra-cabeça.

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

Sem entrar em muitos detalhes, o detalhamento básico é que o elr corresponde aos locais da borda ao longo das bordas esquerda e direita, enquanto o etb corresponde aos locais ao longo das bordas superior e inferior.

James Holderness
fonte
1

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>

Esta é uma porta da minha resposta em lote, apenas para ver se ela concorre com a resposta da @ edc65. A corda irritantemente longa contém peças de quebra-cabeças. As seis primeiras peças representam duas linhas de uma coluna do interior do quebra-cabeças. A sétima peça é usada para a penúltima linha do quebra-cabeças, no lugar da quarta peça. A oitava peça é usada na segunda linha do quebra-cabeças, no lugar da quinta peça, e também faz o dobro do trabalho como a borda esquerda do quebra-cabeças. A nona peça é a última linha do quebra-cabeças.

Neil
fonte