Matrix Jigsaw Puzzle Pieces

10

(Inspirado aleatoriamente em https://codegolf.meta.stackexchange.com/a/17272/42963 )

Dada uma matriz retangular de dígitos (isto é, 0 - 9), imprima as "partes" da matriz como se os dígitos estivessem conectados juntos, formando uma única peça, em ordem crescente pelos dígitos. É garantido que as peças se conectem apenas ortogonalmente - nenhuma peça se conectará na diagonal. Só haverá no máximo 10 peças (ou seja, uma 3peça não aparecerá duas vezes na mesma matriz).

Por exemplo, dada a matriz

0 1 1 1
0 0 1 2
3 3 2 2

a seguir estão as peças e um exemplo de saída:

0
0 0

1 1 1
  1

  2
2 2

3 3

O espaçamento é importante para manter a forma das peças, mas as peças não precisam necessariamente de espaçamento interior. As peças em si devem, de alguma forma, ser diferenciadas de maneira consistente (por exemplo, uma nova linha entre as peças, garantindo que cada uma seja um personagem diferente etc.). Além disso, espaços em branco externos (por exemplo, novas linhas à direita ou colunas à esquerda) não são permitidos. Por exemplo, o seguinte também seria válido:

0
00
111
 1
 2
22
33

ou

#
##

###
 #

 #
##

##

Mas o seguinte não seria (observe os espaços à direita atrás dos 0):

0      
0 0    

Rotações ou reflexões também não são permitidas. Por exemplo, saída

 1
111

para a matriz acima também é inválida.

As peças da matriz podem ter furos ou ser apenas um elemento:

0 0 0 1
0 2 0 1
0 0 0 3

Ou, a peça pode ser toda a matriz:

0 0 0
0 0 0

Aqui está um caso de teste maior e mais complicado:

1 1 1 1 1 2 2
3 4 4 4 2 2 2
5 5 4 4 2 0 0
5 6 6 6 6 7 7
5 6 8 8 6 6 7
9 6 6 6 7 7 7

E um exemplo de saída:

00

11111

 22
222
2

3

444
 44

55
5
5

6666
6  66
666

 77
  7
777

88

9

Regras e E / S

  • A entrada e a saída podem ser fornecidas por qualquer método conveniente .
  • Você pode imprimi-lo em STDOUT ou retorná-lo como resultado de uma função.
  • Um programa completo ou uma função são aceitáveis.
  • É necessário um espaço em branco à esquerda para manter a forma (por exemplo, a forma "T" 1do exemplo), um espaço em branco consistente para diferenciar as peças e uma única linha nova à direita no final é permitida, mas nenhum outro espaço em branco é permitido.
  • Você pode assumir com segurança que as peças são numeradas 0de forma Ncontígua, o que significa que (por exemplo) 3não seria ignorado em uma matriz de seis peças.
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.
AdmBorkBork
fonte
A saída pode realmente ser uma lista das peças? Ou a E / S não pode ser feita com strings, mas com matrizes e números inteiros (com -1ou um espaço representando um espaço vazio ou a ausência de um elemento, se possível)?
Erik the Outgolfer
É aceitável se a entrada for baseada em 1 (não contém zeros) e a saída usar 0como valor de preenchimento? Portanto, cada peça seria impressa com o restante dos valores na matriz configurados para0
Luis Mendo
Independente da minha pergunta anterior: nenhum outro espaço em branco é permitido : nem mesmo espaços à direita para fazer todas as linhas terem o mesmo comprimento?
Luis Mendo
@EriktheOutgolfer Ausência de um elemento seria aceitável, pois está produzindo apenas a "peça" em si. A saída de uma matriz inteira para cada peça com -1ou algum outro valor em vez de nada / espaço em branco não seria bom, no entanto.
AdmBorkBork 11/01/19
@AdmBorkBork Ah, então o espaço ( ' ') deve ser usado nesse caso?
Erik the Outgolfer

Respostas:

2

05AB1E , 20 19 bytes

ZƒNQ2Fζʒà}}ε0Ü}0ð:,

-1 byte graças a @ Mr.Xcoder .

Produz listas 2D de peças (com 1e caracteres de espaço " ") por nova linha.

Experimente online ou verifique todos os casos de teste ou imprima todos os casos de teste .

Explicação:

Z              # Get the maximum digit of the (implicit) matrix-input (implicitly flattens)
 ƒ             # Loop in the range [0, max]:
  NQ           #  Check for each digit in the (implicit) matrix if it's equal to the index
    2F    }    #  Inner loop two times:
      ζ        #   Zip/transpose; swapping rows/columns
       ʒ }     #   Filter the inner lists by:
        à      #    Get the max of the list
               #  (so all rows/columns containing only 0s are removed)
  ε  }         #  Map the remaining rows:
   0Ü          #   Remove all trailing 0s
  0ð:          #  Then replace any remaining 0 with a space " "
     ,         #  And output the piece-matrix with a trailing newline
Kevin Cruijssen
fonte
2

Haskell, 133 132 129 bytes

f x=[until(any(>"!"))(tail<$>)m|m<-[[until((>'!').last)init r|r<-[[last$' ':[s|s==n]|s<-z]|z<-x],any(>'!')r]|n<-['0'..'9']],m>[]]

Pega a matriz como uma lista de cadeias e retorna uma lista de lista de cadeias.

Experimente online!

                                    -- example matrix: ["0111","0012","3322"] 
                                    --
[          |n<-[0..9]]              -- for each digit 'n' from '0' .. '9'
  [  |z<-x]                         --   for each line 'z' of the input matrix 'x'
   [      |s<-z]                    --     for each digit 's' of line 'z'
      last$' ':[s|s==n]             --       take 's' if 's'=='n', else a space
                                    --       now we have a list of 10 matrices where
                                    --       each matrix contains only the
                                    --       corresponding digit 'n' at it's original
                                    --       position and spaces for all other digits
                                    --       -> [["0   ","00  ","    "],[" 111","  1 ","    "],["    ","   2","  22"],["    ","    ","33  "],["    ","    ","    "],["    ","    ","    "],["    ","    ","    "],["    ","    ","    "],["    ","    ","    "],["    ","    ","    "]]
   [     |r<-[    ],any(>'!')r]     --     loop through rows 'r' and keep those with
                                    --     at least one non-space element
    until((>'!').last)init r        --     and remove trailing spaces
                                    --     -> [["0","00"],[" 111","  1"],["   2","  22"],["33"],[],[],[],[],[],[]]
   [     |m<-[   ],m>[]]            --   loop through matrices 'm' and keep only
                                    --   non-empty
    until(any(>"!"))(tail<$>)m      --   and remove common leading spaces
                                    --   -> [["0","00"],["111"," 1"],[" 2","22"],["33"]]
nimi
fonte
2

Gelatina , 18 bytes

ẎQṢ=€ẸƇZ$⁺œr€ɗ€0o⁶

Experimente online!

Retorna uma lista de peças, onde 1representa uma parte de uma peça e ' 'está preenchida. Os últimos ' 'são removidos.

Erik, o Outgolfer
fonte
ẎQ=€deve fazer, embora precisemos das peças em ordem crescente, de modo que 9Ż=€(a menos que não devamos incluir "peças inexistentes" nesse caso ẎQṢ=€))
Jonathan Allan
@JonathanAllan Corrigido o problema, embora eu tenha certeza 9Ż=€que não funcionará (acho que "espaço em branco estranho [...] não é permitido") se estende também às matrizes, é por isso que estou cortando).
Erik the Outgolfer
Sim, isso faz sentido.
Jonathan Allan
2

Python 3 , 271 209 206 183 176 172 191 bytes

lambda t:[[[*"".join(' #'[i==d]for i in r).rstrip()]for r in[w[min(r.index(d)for r in t if d in r):max(len(R)-R[::-1].index(d)for R in t if d in R)]for w in t if d in w]]for d in{*sum(t,[])}]

Experimente online!

Edit: Alguma limpeza e -5 graças a @ Jonathan Frech .

Edit: -3 -26 mais uma vez, graças a @ Jonathan Frech .

Edit: -7 novamente graças a @ Jonathan Frech .

Edit: +19: Conforme observado por @ nimi, a saída anterior tinha um formato incorreto.


A entrada é matriz como lista de listas:

Input =  [[0, 1, 1, 1],
          [0, 0, 1, 2],
          [3, 3, 2, 2]]

Saída é uma lista de matrizes:

Output = [[['#'],
           ['#', '#']],
          [['#', '#', '#'],
           [' ', '#']],
          [[' ', '#'],
           ['#', '#']],
          [['#', '#']]],

Ungolfed:

O = ' '
X = '#'

def digits(t):
    return {d for r in t for d in r}

def rows_with_digit(table, digit):
    return [row for row in table if digit in row]

def table_with_digit(table, digit):
    subtable = rows_with_digit(table, digit)
    left_most_column = min([row.index(digit) for row in subtable])
    right_most_column = max([len(row) - row[::-1].index(digit) for row in subtable])
    return [row[left_most_column:right_most_column] for row in subtable]

def format_table(table, digit):
    return [[X if i==digit else O for i in row] for row in table]

def f(table):
    D = digits(table)
    R = []
    for d in D:
        digit_table = table_with_digit(table, d)
        R.append(format_table(digit_table, d))    
    return R
Nishioka
fonte
11
176 bytes .
Jonathan Frech
2

Python 2 , 173 172 165 bytes

s=input()
for i in sorted(set(sum(s,[]))):R=[''.join([' ',i][c==i]for c in r)for r in s if i in r];print'\n'.join(t[min(r.find(i)for r in R):t.rfind(i)+1]for t in R)

Experimente online!

-15 bytes de uma observação por nimi .

Em forma de programa, leva como entrada uma lista de listas de caracteres únicos; saídas imprimindo as peças encontradas usando seus caracteres.

Chas Brown
fonte
@AdmBorkBork - Certo, faltou esse critério. Corrigido agora.
Chas Brown
2

C # (.NET Core) , 258 , 238 bytes

Sem LINQ.

EDIT: Modalidade de ignorância apontando melhores declarações var! Ty ty.

p=>{int j=0,o=0,l=0,x=p.GetLength(1),d=p.Length;while(j<d){int t=j/x,u=j++%x,z=p[t,u];o=z>o?z:o;l=z<l?z:l;}var s="";for(var m=l;m<=o;m++){j=0;while(j<d){int t=j/x,u=j++%x;s+=(p[t,u]==m?p[t,u]+"":" ")+(u==x-1?"\n":"");}s+="\n";}return s;};

Experimente online!

Destroigo
fonte
11
238 bytes
Modalidade de ignorância
1

Python 2 , 291 bytes

import re
t=input()
a,b=t.split(),{c for c in t if' '<c}
for c in sorted((b,a)[int(max(a))==len(a)],key=int):s=re.sub(r'[^%s\s]'%c,' ',t).split('\n');print"\n".join(''.join(l[i]for i in sorted({i for l in s for i,j in enumerate(l)if j in c})if i<len(l)).rstrip()for l in s if l.strip())+'\n'

Experimente online!

Espera uma picada delimitada por aspas como entrada. Uma porcentagem semi-ridícula do código é dedicada ao tratamento de entrada não separada por espaço / preenchida sem espaço.

Explicação sem golfe:

# built-in python regex handling.
import re
# get argument from STDIN
t=input()
# get elements which are whitespace separated, and all distinct non-whitespace characters
a,b=set(t.split()),{c for c in t if' '<c}
                # choose whichever set has the appropriate number of values based on its max element
                # for non-space separated inputs, this prevents values like '333' for 4-piece sets
                (b,a)[int(max(a))==len(a)]
# get elements in order by their integer value
# this will force the items to print in order, since sets are unordered
for c in sorted(..........................,key=int):
      # using regex substitute, replace any instance that DOESN'T match the current value or a whitespace with a space
      re.sub(r'[^%s\s]'%c,' ',t)
    # split replaced string into lines on line breaks
    s=...........................split('\n')
                # for each line in replaced input
                for l in s
                           # get the index and value of each item in line
                           for i,j in enumerate(l)
             # get distinct indexes which have a value that appears in the current piece
             {i ..................................if j in c}
    # get ordered list of distinct indexes
    a=sorted(...............................................)
                                                               # for each line in the replaced input
                                                               # only return values where line has non-whitespace values
                                                               for l in s if l.strip()
                           # get the value for each index that has a non-space value on other lines
                           # as long as that index exists (for non-space-padded inputs)
                           # this ensures that the spaces between values, if any, are removed
                           # there may still be trailing spaces
                           l[i]for i in a if i<len(l)
                   # join characters back into one string, and remove trailing whitespace
                   ''.join(..........................).rstrip()
    # join the lines back together with line breaks, and terminate with an extra line break
    # print output to screen
    print"\n".join(...................................................................)+'\n'
Triggernometria
fonte
Você tem permissão para especificar o formato de entrada (por exemplo, como uma lista de listas ou como um parágrafo separado por espaço), se isso tornar o seu código mais eficiente.
AdmBorkBork 14/01/19
1

Retina , 75 bytes

$
¶9
.-10{T`9d`d`.$
*;(s`(\d)(?!.*\1$)
 
 +¶
¶
G`\d
/^\d|^$/m^+m`^.

.$
$&¶

Experimente online! Explicação:

$
¶9

Acrescente um dígito à entrada. Isso representa o contador de loop. A nova linha simplifica a remoção do espaço em branco à direita.

.-10{

Iniba a saída padrão e repita exatamente 10 vezes.

T`9d`d`.$

Avance o dígito do loop.

*;(

Produza o resultado do restante do script, mas restaure o buffer.

s`(\d)(?!.*\1$)
 

Substitua todos os dígitos que não correspondem ao dígito do loop por espaços. (Como isso usa um lookahead e não há nada a considerar neste momento, isso também substitui o dígito do loop.)

 +¶
¶

Remova todo o espaço em branco à direita.

G`\d

Remova todas as linhas em branco.

/^\d|^$/m^+

Repita, desde que nenhuma linha comece com um dígito ...

m`^.

... exclua o primeiro caractere em cada linha.

.$
$&¶

Se sobrar alguma coisa, acrescente uma nova linha para separar cada forma da seguinte. (Isso é feito para evitar novas linhas perdidas devido à falta de dígitos.)

Neil
fonte
É garantido que nunca haverá um "dígito ausente" se isso diminuir o seu código.
AdmBorkBork 14/01/19
@AdmBorkBork Não acho que isso ajudaria. O que seria mais provável de ajudar é não ter que produzir as peças em ordem numérica. Isso é permitido?
Neil
Não, isso é metade do desafio, caso contrário, seria muito fácil. ;-)
AdmBorkBork 14/01/19
1

Carvão vegetal , 43 bytes

WS⊞υιFχ«≔Φυ№κIιθ¿θ«UTFθ«Fκ«¿⁼λIιλ→»M±Lκ¹»D⎚

Experimente online! Link é a versão detalhada do código. Explicação:

WS⊞υι

Leia a entrada em uma matriz. (Isso poderia ser removido se eu usasse um formato de entrada feio.)

Fχ«

Faça um loop sobre os 10 dígitos.

≔Φυ№κIιθ

Obtenha as linhas que contêm esses dígitos.

¿θ«

Verifique se o dígito foi realmente encontrado (para evitar a saída de novas linhas falsas).

UT

Desative o preenchimento automático.

Fθ«

Passe pelas linhas encontradas.

Fκ«

Passar por cada coluna ...

¿⁼λIιλ→»

... se o caractere de entrada atual for igual ao dígito do loop atual, imprima-o, caso contrário, mova o cursor para a direita.

M±Lκ¹»

Vá para o início da próxima linha. O uso de comandos de movimento como esse permite que o Carvão apare a saída nos dois lados.

D⎚

Despejar e limpar a tela pronta para o próximo dígito. Isso permite que os diferentes dígitos tenham diferentes quantidades de corte.

Tentei uma abordagem programática, mas que pesava 47 bytes, embora também tivesse sido 43 bytes por um breve período de tempo quando Equalsvetorizada:

UTWS⊞υιFχ«≔ΦEυEκ⁼μIιΣκθEθ⭆✂κ⌊Eθ⌕μ¹⁻Lκ⌕⮌κ¹¦¹⎇μι 

Experimente online! Link é a versão detalhada do código. Explicação:

UT

Desative o preenchimento automático.

WS⊞υι

Leia a entrada em uma matriz.

Fχ«

Faça um loop sobre os 10 dígitos.

≔ΦEυEκ⁼μIιΣκθ

Compare cada caractere com a entrada e crie uma matriz booleana, mas depois filtre as linhas sem correspondências.

Eθ⭆✂κ⌊Eθ⌕μ¹⁻Lκ⌕⮌κ¹¦¹⎇μι 

Faça um loop sobre as linhas restantes e corte da correspondência mais antiga de qualquer linha para a correspondência mais recente da linha atual e, em seguida, mapeie a matriz booleana de volta para dígitos ou espaços, que são impressos implicitamente como uma matriz de seqüências de caracteres.

Neil
fonte
1

Wolfram Language 101 bytes

Tem que haver uma maneira muito mais eficiente de conseguir isso.

(g=#;Column[Table[Grid@Map[Replace[#,Thread[Complement[u=Union@Flatten@g,{n}]->""]]&/@#&,g],{n,u}]])&
DavidC
fonte
1

Perl 5, 97 bytes

$x=$_;for$i(0..9){$_=$x;y/ //d;s/(?!$i)./ /g;s/ *$//gm;s/^
//gm;s/^ //gm until/^(?! )/m;$\.=$_}}{

TIO

Explicação

-p0777                       # options to read whole intput and print special var by default

$x=$_;                       # save default var (input) into $x
for$i(0..9){                 # for $i in 0..9
    $_=$x;                   #   restore default var 
    y/ //d;                  #   remove all space char
    s/(?!$i)./ /g;           #   replace all char except $i by a space
    s/ *$//gm;               #   remove trailing space
    s/^\n//gm;               #   remove empty lines
    s/^ //gm until/^(?! )/m; #   remove leading space until there is no more
    $\.=$_                   #   append default var to output record separator
}
}{                           # trick with -p to output only reacord separator
Nahuel Fouilleul
fonte
1

APL (Dyalog Unicode) , 38 bytes SBCS

Função de prefixo tácito anônimo. Pega uma matriz numérica como argumento e retorna uma lista de sequências de listas. Cada lista de strings representa uma peça com 1s separados por espaço . Espaços iniciais e internos (mas não finais) são espaços.

⊂{' +$'R''↓⍕' '@~{⍉⍵⌿⍨∨/⍵}⍣2⊢⍺=⍵}¨∪∘,

Experimente online!

∪∘, os elementos únicos da matriz ravel (achatada)

⊂{ Para cada um desses , chame a seguinte função com toda a matriz como :

⍺=⍵ indicar onde o número da peça está na matriz

 rendimento que (separa 2de )

{}⍣2 Aplique a seguinte função duas vezes ( é a matriz booleana):

  ∨/ mascarar linhas com pelo menos um 1(lit. redução OR de linha)

  ⍵⌿⍨ use isso para filtrar as linhas

   transpor (então fazemos isso nas colunas também, depois transporemos de volta)

' '@~ substitua por espaços em posições onde não (ou seja, onde 0)

 formato como matriz de caracteres

 dividido em lista de strings

' +$'⎕R'' O PCRE substitui os espaços finais (qualquer número de espaços seguidos por um final de linha) por nada

Adão
fonte
1

Japonês , 29 bytes

AÆ®®¥X ÑÃÃÕfx Õfx ®¬r0S x1
fl

Experimente online!

Atualizado para obedecer a formatação de saída mais rígida.

Saída como uma lista de peças com cada peça representada por uma lista de linhas, usando 2 como caractere de preenchimento.

Explicação:

AÆ                            #For the numbers 0-9:
  ®®    ÃÃ                    # Map over each digit in the input:
    ¥X                        #  True if it equals the current number, false otherwise
       Ñ                      #  Multiply by 2 to turn the bool into a number
          Õfx                 # Remove columns that are all 0
              Õfx             # Remove rows that are all 0
                  ®           # For each remaining row:
                   ¬          #  Turn it into a string
                    r0S       #  Replace "0" with " "
                        x1    #  Trim spaces from the right
fl                            #Remove unused pieces
Kamil Drakari
fonte
Você esqueceu de remover todos os trilhos falsedas listas internas. Aqui está um pastebin para que eu possa explicar melhor o que deveria ser a saída. Sinta-se à vontade para pedir à OP que esclareça, mas até onde eu entendo do desafio, nem todos os espaços em branco restantes devem estar presentes na saída.
Kevin Cruijssen 15/01/19
0

Python 3 , 133 bytes

lambda s:[dedent(re.sub(" *$","",re.sub(f"[^{c}\\n]"," ",s),0,8)).strip("\n")for c in sorted(*s)[1:]]
from textwrap import*
import re

Experimente online!

Pega uma cadeia separada por nova linha e retorna uma lista de cadeias separadas por nova linha. Usa textwrap.dedentpara se livrar dos espaços principais.

Black Owl Kai
fonte
@AdmBorkBork Negligenciou essa regra, corrigida
Black Owl Kai
0

Geléia , 19 bytes

ŒĠµŒṬZSƇ$⁺ị⁾# œr€⁶)

Experimente online!

Um link monádico que toma a matriz como entrada e retorna uma lista de uma lista irregular por peça. O rodapé mostra isso lindamente, mas acho que a saída sem isso é consistente com as regras da pergunta.

Nick Kennedy
fonte