Enumere todas as grades possíveis de números inteiros com restrições


17

Problema

Considere uma grade quadrada de 3 por 3 de números inteiros não negativos. Para cada linha, ia soma dos números inteiros é configurada para ser r_i. Da mesma forma, para cada coluna, ja soma dos números inteiros nessa coluna está configurada para ser c_j.

A tarefa é escrever código para enumerar todas as possíveis atribuições diferentes de números inteiros para a grade, dadas as restrições de soma de linhas e colunas. Seu código deve gerar uma atribuição por vez.

Entrada

Seu código deve usar 3 números inteiros não negativos, especificando as restrições de linha e 3 números inteiros não negativos, especificando as restrições de coluna. Você pode assumir que eles são válidos, ou seja, que as restrições de soma ou linha são iguais à soma das restrições de coluna. Seu código pode fazer isso da maneira que for mais conveniente.

Resultado

Seu código deve gerar as diferentes grades 2D que ele calcula em qualquer formato legível por humanos de sua escolha. Quanto mais bonito, melhor, é claro. A saída não deve conter grades duplicadas.

Exemplo

Se todas as restrições de linha e coluna forem exatamente, 1então existem apenas 6possibilidades diferentes. Para a primeira linha, você pode colocar um 1em qualquer uma das três primeiras colunas, para a segunda linha agora existem 2alternativas e a última linha agora é completamente determinada pelas duas anteriores. Tudo o resto na grade deve ser definido como 0.

Digamos que a entrada seja 2 1 0para as linhas e 1 1 1para as colunas. Usando o adorável formato de saída da APL, as possíveis grades inteiras são:

┌─────┬─────┬─────┐
│0 1 1│1 0 1│1 1 0│
│1 0 0│0 1 0│0 0 1│
│0 0 0│0 0 0│0 0 0│
└─────┴─────┴─────┘

Agora diga que a entrada é 1 2 3para as linhas e 3 2 1para as colunas. As possíveis grades inteiras são:

┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│0 0 1│0 0 1│0 0 1│0 1 0│0 1 0│0 1 0│0 1 0│1 0 0│1 0 0│1 0 0│1 0 0│1 0 0│
│0 2 0│1 1 0│2 0 0│0 1 1│1 0 1│1 1 0│2 0 0│0 1 1│0 2 0│1 0 1│1 1 0│2 0 0│
│3 0 0│2 1 0│1 2 0│3 0 0│2 1 0│2 0 1│1 1 1│2 1 0│2 0 1│1 2 0│1 1 1│0 2 1│
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘

Respostas:


9

APL (Dyalog) , 42 bytes

{o/⍨(⍵≡+/,+⌿)¨o←3 3∘⍴¨(,o∘.,⊢)⍣8⊢o←⍳1+⌈/⍵}

Experimente online!

Usa o ⎕IO←0padrão em muitos sistemas. O outro material no cabeçalho é apenas uma bonita impressão para as matrizes (exibição em caixa).

Entrada é uma lista de seis valores, as linhas somam primeiro e, em seguida, a coluna.

Quão?

o←⍳1+⌈/⍵- oobtém o intervalo 0para o máximo ( ⌈/) de entrada

,o∘.,⊢- produto cartesiano com oe achatado ( ,)

⍣8 - repetido oito vezes

3 3∘⍴¨ - forma cada lista de 9 itens em uma matriz 3 × 3

¨o←- salve essas matrizes em oe para cada

+/,+⌿- verifique se as linhas somas ( +/) concatenadas com a coluna somas ( +⌿)

⍵≡ - corresponde à entrada

o/⍨- filtrar o(a matriz de matrizes) por valores reais


Esta resposta muito bonita precisa de uma explicação (por favor).

@Lembik adicionou uma explicação
Uriel

Obrigado. Então, você enumera todas as matrizes possíveis e verifica aquelas que se ajustam às restrições que parecem. Não é o mais eficiente, mas funciona.

1
@ Lembik sim, esse é o mais curto. Eu pude gerenciar um pouco mais eficiente, obtendo todas as listas de três itens que podem corresponder às somas e, em seguida, escolher as que se encaixam na soma da primeira linha e depois as (para cada uma das combinações anteriores) que correspondem à soma das primeiras colunas, e assim por diante. Esse seria o algoritmo geral de força não-bruta.
Uriel

@EriktheOutgolfer obrigado, eu sempre esqueço de atualizar minha contagem de bytes
Uriel

7

Casca , 20 17 bytes

fȯ=⁰mΣS+Tπ3π3Θḣ▲⁰

-3 bytes graças a @ H.PWiz

Aceita entrada como uma lista que xscodifica as restrições [r_1,r_2,r_3,c_1,c_2,c_3], tente online!

Explicação

Abordagem de força bruta: P Gere todas as grades 3x3 com as entradas [0..max xs]:

f(=⁰mΣS+T)π3π3Θḣ▲⁰  -- input ⁰, for example: [1,1,1,1,1,1]
                ▲⁰  -- max of all constraints: 1
               ḣ    -- range [1..max]: [1]
              Θ     -- prepend 0: [0,1]
            π3      -- 3d cartesian power: [[0,0,0],...,[1,1,1]]
          π3        -- 3d cartesian power: list of all 3x3 matrices with entries [0..max] (too many)
f(       )          -- filter by the following predicate (eg. on [[0,0,1],[1,0,0],[0,1,0]]):
      S+            --   append to itself, itself..: [[0,0,1],[1,0,0],[0,1,0],..
        T           --   .. transposed:             ..[0,1,0],[0,0,1],[1,0,0]]
      mΣ            --   map sum: [1,1,1,1,1,1]
    =⁰              --   is it equal to the input: 1

6

Braquilog , 17 bytes

{~⟨ṁ₃{ℕᵐ+}ᵐ²\⟩≜}ᶠ

Experimente online!

AVISO: SAÍDA FEIA! Não se preocupe, ainda é legível por humanos, não sou obrigado a dar conta de quanto. ;)

Por alguma razão, deve ser muito mais longo do que o que eu esperaria fazer sentido (13 bytes):

⟨ṁ₃{ℕᵐ+}ᵐ²\⟩ᶠ

Esta última versão, se funcionasse, teria recebido a entrada da saída (ou seja, argumento da linha de comando).


@Riker Leia a seção "Saída" do OP. Claro, ele ainda tem suportes que separam as grades, que poderia ter despojado-los bem e a saída seria ainda não perderam qualquer dado ...
Erik o Outgolfer

4

Python 2 , 149 145 142 141 138 136 bytes

lambda s:[i for i in product(range(max(sum(s,[]))+1),repeat=9)if[map(sum,(i[j:j+3],i[j/3::3]))for j in 0,3,6]==s]
from itertools import*

Experimente online!

Recebe entrada como uma lista de listas: [[r1, c1], [r2, c2], [r3, c3]]


4

Haskell, 94 88 84 79 bytes

q=mapM id.(<$"abc")
f r=[k|k<-q$q$[0..sum r],(sum<$>k)++foldr1(zipWith(+))k==r]

Toma as somas das linhas e colunas como uma única lista plana de 6 elementos [r1,r2,r3,c1,c2,c3].

Experimente online!

q=mapM id.(<$"abc")         -- helper function 

f r =                       -- 
  [k | k <-   ,    ]        -- keep all k
    q$q$[0..sum r]          --   from the list of all possible matrices with
                            --   elements from 0 to the sum of r
                            -- where
    (sum<$>k) ++            --   the list of sums of the rows followed by
    foldr1(zipWith(+))k     --   the list of sums of the columns
    == r                    -- equals the input r

Como os elementos das matrizes a serem testadas chegam à soma de r, o código não termina em tempo razoável para somas grandes de linhas / colunas. Aqui está uma versão que vai até o máximo rmais rápido, mas com 4 bytes a mais: Experimente online!


3

Mathematica, 81 bytes

Select[0~Range~Max[s=#,t=#2]~g~3~(g=Tuples)~3,(T=Total)@#==s&&T@Transpose@#==t&]&

encontra todas as matrizes 3x3 com elementos 0..Max e seleciona as corretas,
isso significa que as (Max+1)^9matrizes precisam ser verificadas

Experimente online!


Você poderia adicionar uma explicação, por favor.

3
@Lembik, depois de adicionar alguns casos de teste e tornar esse desafio "claro" para todas as pessoas aqui. Votei em reabrir, mas você parece não tentar melhorar isso para todos aqueles que precisam de ajuda
J42161217

Adicionado à pergunta agora.

O que ainda não está claro? / Gridtambém trabalho com TIO, usando ToString. Experimente online!
user202729

@ user202729 nada para mim, mas de teste casos estavam faltando
J42161217

3

R , 115 110 bytes

function(S)for(m in unique(combn(rep(0:max(S),9),9,matrix,F,3,3)))if(all(c(rowSums(m),colSums(m))==S))print(m)

Experimente online!

Recebe a entrada como c(r1,r2,r3,c1,c2,c3)uma única vectore imprime as matrizes em stdout.

É bastante semelhante à resposta do APL de Uriel , mas gera as grades 3x3 de maneira um pouco diferente.

Deixando M=max(S), gera o vetor 0:Me o repcome 9 vezes, ou seja, [0..M, 0...M, ..., 0...M]nove vezes. Em seguida, ele seleciona todas as combinações desse novo vetor tiradas 9 de cada vez, usando matrix, 3, 3para converter cada combinação 9 em uma 3x3matriz e forçando simplify=Fa retornar uma lista em vez de uma matriz. Em seguida, unifica essa lista e a salva como m.

Em seguida, filtra mpara aqueles em que as somas de linha / coluna são idênticas à entrada, imprimindo as que estão e não fazendo nada para as que não são.

Como calcula choose(9*(M+1),9)diferentes grades possíveis (mais do que as (M+1)^9possibilidades), a memória / tempo fica mais rápida do que a resposta mais eficiente (mas com menos golfe) abaixo:

R , 159 bytes

function(S,K=t(t(expand.grid(rep(list(0:max(S)),9)))))(m=lapply(1:nrow(K),function(x)matrix(K[x,],3,3)))[sapply(m,function(x)all(c(rowSums(x),colSums(x))==S))]

Experimente online!


R é muito bem-vindo!

3

MATL , 35 22 bytes

-13 bytes graças a Luis Mendo

X>Q:q9Z^!"@3et!hsG=?4M

Experimente online!

Link é para uma versão do código que imprime um pouco mais bem; esta versão apenas imprimirá todas as matrizes com uma única nova linha entre elas.

Toma entrada como [c1 c2 c3 r1 r2 r3].

Obviamente, isso calcula o poder cartesiano X^de 0...max(input)com expoente 9e de transposição !. Em seguida, percorre "as colunas, remodelando cada @uma como uma matriz 3x3 3e, duplicando t, transpondo !e concatenando horizontalmente h. Em seguida, calcula as somas da coluna s, o que resultará no vetor [c1 c2 c3 r1 r2 r3]. Fazemos igualdade elementar para a entrada G=e, se ?todos forem diferentes de zero, recuperamos a matriz correta selecionando a entrada para a função !usando4M .


2

Lote, 367 bytes

@echo off
for /l %%i in (0,1,%1)do for /l %%j in (%%i,1,%1)do for /l %%k in (%%i,1,%4)do call:c %* %%i %%j %%k
exit/b
:c
set/a"a=%1-%8,c=%4-%9,f=%8-%7,g=%9-%7,l=%5-f,m=%2-g,l^=m-l>>31&(m^l),m=%5+c-%3-f,m&=~m>>31
for /l %%l in (%m%,1,%l%)do set/a"b=%2-g-%%l,d=%5-f-%%l,e=%6-a-b"&call:l %7 %%l
exit/b
:l
echo %1 %f% %a%
echo %g% %2 %b%
echo %c% %d% %e%
echo(

O quadrado 2 × 2 superior esquerdo força o resultado, portanto, a melhor abordagem é gerar todos os valores para o número inteiro superior esquerdo, todos os valores válidos para a soma do número inteiro superior esquerdo e superior médio, todos os valores válidos para a soma do número superior inteiro esquerdo e médio esquerdo e calcule o intervalo de valores válidos para o número inteiro médio; depois de percorrer todos os intervalos apropriados, calcule os valores restantes a partir das restrições.


1

Python 2 , 118 bytes

def f(v,l=[],i=0):n=len(l);V=v*1;V[~n/3]-=i;V[n%3]-=i;return[l][any(V):]if n>8else V*-~min(V)and f(V,l+[i])+f(v,l,i+1)

Experimente online!


Python 2 , 123 bytes

V=input()
n=max(V)+1
for k in range(n**9):
 m=[];exec"m+=[k%n,k/n%n,k/n/n%n],;k/=n**3;"*3
 if map(sum,m+zip(*m))==V:print m

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.