Enumerar todas las cuadrículas posibles de enteros con restricciones

17

Problema

Considere una cuadrícula de 3 por 3 de enteros no negativos. Para cada fila, ila suma de los enteros se establece en r_i. Del mismo modo, para cada columna, jla suma de los enteros en esa columna se establece en c_j.

La tarea es escribir código para enumerar todas las posibles asignaciones diferentes de enteros a la cuadrícula dadas las restricciones de suma de filas y columnas. Su código debe generar una asignación a la vez.

Entrada

Su código debe tomar 3 enteros no negativos que especifiquen las restricciones de fila y 3 enteros no negativos que especifiquen las restricciones de columna. Puede suponer que estos son válidos, es decir, que las restricciones de suma o fila son iguales a la suma de las restricciones de columna. Su código puede hacer esto de cualquier manera que sea conveniente.

Salida

Su código debe generar las diferentes cuadrículas 2d que calcula en cualquier formato legible por humanos que elija. Cuanto más bonita, mejor, por supuesto. La salida no debe contener cuadrículas duplicadas.

Ejemplo

Si todas las restricciones de fila y columna son exactamente, 1entonces solo hay 6diferentes posibilidades. Para la primera fila, puede poner una 1en cualquiera de las primeras tres columnas, para la segunda fila ahora hay 2alternativas y la última fila ahora está completamente determinada por las dos anteriores. Todo lo demás en la cuadrícula debe establecerse en 0.

Digamos que la entrada es 2 1 0para las filas y 1 1 1para las columnas. Usando el formato de salida encantador de APL, las posibles cuadrículas de enteros son:

┌─────┬─────┬─────┐
│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│
└─────┴─────┴─────┘

Ahora digamos que la entrada es 1 2 3para las filas y 3 2 1para las columnas. Las posibles cuadrículas de enteros son:

┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│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│
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
Martin Ender
fuente

Respuestas:

9

APL (Dyalog) , 42 bytes

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

Pruébalo en línea!

Utiliza el ⎕IO←0que está predeterminado en muchos sistemas. Las otras cosas en el encabezado son solo impresiones bonitas para las matrices (pantalla en recuadro).

La entrada es una lista de seis valores, las sumas de las filas primero, luego las sumas de las columnas.

¿Cómo?

o←⍳1+⌈/⍵- oobtiene el rango 0al máximo ( ⌈/) de entrada

,o∘.,⊢- producto cartesiano con oy aplanar ( ,)

⍣8 - repetido por ocho veces

3 3∘⍴¨ - forma cada lista de 9 elementos en una matriz 3 × 3

¨o←- guarde estas matrices en o, y para cada

+/,+⌿- compruebe si las filas sumas ( +/) se concatenan con las columnas sumas ( +⌿)

⍵≡ - corresponde con la entrada

o/⍨- filtrar o(la matriz de matrices) por valores verdaderos

Uriel
fuente
Esta respuesta muy bonita necesita una explicación (por favor).
Explicación agregada de @Lembik
Uriel
Gracias. Entonces enumera todas las matrices posibles y verifica las que se ajustan a las restricciones que parece. No es el más eficiente, pero funciona.
1
@Lembik, sí, es el más corto. Podría lograr un poco más eficiente al obtener todas las listas de 3 elementos que pueden coincidir con las sumas, luego elegir las que se ajusten a la suma de la primera fila y luego elegir las (para cada una de las combinaciones anteriores) que coincidan con la suma de las primeras columnas, y así sucesivamente. Ese sería el algoritmo general de fuerza no bruta.
Uriel
@EriktheOutgolfer gracias, siempre me olvido de actualizar mi recuento de bytes
Uriel
7

Casco , 20 17 bytes

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

-3 bytes gracias a @ H.PWiz

Toma datos como una lista que xscodifica las restricciones [r_1,r_2,r_3,c_1,c_2,c_3], ¡ pruébelo en línea!

Explicación

Enfoque de fuerza bruta: P Genera todas las cuadrículas de 3x3 con 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
ბიმო
fuente
6

Brachylog , 17 bytes

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

Pruébalo en línea!

ADVERTENCIA: ¡SALIDA FEA! No te asustes, todavía es legible para los humanos, no estoy obligado a dar cuenta de cuánto. ;)

Por alguna razón, debe ser mucho más largo de lo que esperaría que tuviera sentido (13 bytes):

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

Esta última versión, si funcionó, habría tomado la entrada de la salida (es decir, argumento de línea de comandos) en su lugar.

Erik el Outgolfer
fuente
@Riker Lea la sección "Salida" del OP. Claro, todavía tiene corchetes que separan las cuadrículas, podría haberlas despojado también y la salida aún no habría perdido ningún dato ...
Erik the 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*

Pruébalo en línea!

Toma datos como una lista de listas: [[r1, c1], [r2, c2], [r3, c3]]

TFeld
fuente
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 las sumas de las filas y columnas como una sola lista plana de 6 elementos [r1,r2,r3,c1,c2,c3].

Pruébalo en línea!

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

A medida que los elementos de las matrices para probar ascienden a la suma de r, el código no termina en un tiempo razonable para sumas grandes de fila / columna. Aquí hay una versión que sube al máximo de la rcual es más rápida, pero 4 bytes más: ¡ Pruébelo en línea!

nimi
fuente
3

Mathematica, 81 bytes

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

encuentra todas las matrices 3x3 con elementos 0..Max y selecciona las correctas,
esto significa que las (Max+1)^9matrices deben ser verificadas

Pruébalo en línea!

J42161217
fuente
¿Podría agregar una explicación por favor?
3
@Lembik lo haré, después de agregar algunos casos de prueba y hacer que este desafío sea "claro" para todas las personas aquí. Voté por reabrir pero parece que no intentas mejorar esto para todos aquellos que necesitan ayuda
J42161217
Agregado a la pregunta ahora.
¿Qué aún no está claro? / Gridtambién trabajo con TIO, usando ToString. Pruébalo en línea!
user202729
@ user202729 nada para mí, pero faltaban casos de prueba
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)

Pruébalo en línea!

Toma la entrada como c(r1,r2,r3,c1,c2,c3)una sola vectore imprime las matrices en stdout.

Es bastante similar a la respuesta APL de Uriel , pero genera las cuadrículas de 3x3 de manera algo diferente.

Dejando M=max(S), genera el vector 0:M, luego lo repcome 9 veces, es decir, [0..M, 0...M, ..., 0...M]nueve veces. Luego selecciona todas las combinaciones de ese nuevo vector tomadas 9 a la vez, utilizando matrix, 3, 3para convertir cada combinación de 9 en una 3x3matriz y obligando simplify=Fa devolver una lista en lugar de una matriz. Luego uniquifica esta lista y la guarda como m.

Luego filtra mpara aquellos donde las sumas de fila / columna son idénticas a la entrada, imprime las que están y no hace nada por las que no lo son.

Dado que calcula choose(9*(M+1),9)diferentes cuadrículas posibles (más que las (M+1)^9posibilidades), se quedará sin memoria / tiempo más rápido que la respuesta más eficiente (pero menos golfosa) a continuación:

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

Pruébalo en línea!

Giuseppe
fuente
R es muy bienvenido!
3

MATL , 35 22 bytes

-13 bytes gracias a Luis Mendo

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

Pruébalo en línea!

El enlace es a una versión del código que se imprime un poco mejor; Esta versión imprimirá todas las matrices con una sola línea nueva entre ellas.

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

Obviamente, esto calcula el poder cartesiano X^de 0...max(input)con exponente 9y transposición !. Luego recorre "las columnas, rediseñando cada @una como una matriz de 3x3 3e, duplicándolas t, transponiéndolas !y concatenándolas horizontalmente h. Luego calcula las sumas de columnas s, lo que dará como resultado el vector [c1 c2 c3 r1 r2 r3]. Hacemos igualdad de elementos a la entrada G=, y si ?todos son distintos de cero, recuperamos la matriz correcta seleccionando la entrada a la función !mediante 4M.

Giuseppe
fuente
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(

El cuadrado superior izquierdo 2 × 2 fuerza el resultado, por lo que el mejor enfoque es generar todos los valores para el entero superior izquierdo, todos los valores válidos para la suma del entero superior izquierdo y medio superior, todos los valores válidos para la suma del top entero izquierdo y medio izquierdo, y calcule el rango de valores válidos para el entero medio, luego, tras recorrer todos los rangos apropiados, calcule los valores restantes a partir de las restricciones.

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

Pruébalo en línea!


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

Pruébalo en línea!

xnor
fuente