Enumera tutte le possibili griglie di numeri interi con vincoli


17

Problema

Considera una griglia quadrata 3 per 3 di numeri interi non negativi. Per ogni riga iviene impostata la somma degli interi r_i. Allo stesso modo per ogni jcolonna è impostata la somma degli interi in quella colonna c_j.

Il compito è scrivere codice per enumerare tutte le possibili diverse assegnazioni di numeri interi alla griglia dati i vincoli di somma di riga e colonna. Il tuo codice dovrebbe generare un compito alla volta.

Ingresso

Il codice deve assumere 3 numeri interi non negativi che specificano i vincoli di riga e 3 numeri interi non negativi che specificano i vincoli di colonna. Si può presumere che siano validi, ovvero che i vincoli di somma o riga siano uguali alla somma dei vincoli di colonna. Il tuo codice può farlo in qualsiasi modo sia conveniente.

Produzione

Il tuo codice dovrebbe generare le diverse griglie 2D che calcola in qualsiasi formato leggibile dall'uomo che preferisci. Più carina è, meglio ovviamente. L'output non deve contenere griglie duplicate.

Esempio

Se tutti i vincoli di riga e colonna sono esattamente 1allora ci sono solo 6diverse possibilità. Per la prima riga puoi inserire a 1in una delle prime tre colonne, per la seconda riga ora ci sono 2alternative e l'ultima riga è ora completamente determinata dalle due precedenti. Tutto il resto nella griglia dovrebbe essere impostato su 0.

Supponiamo che l'input sia 2 1 0per le righe e 1 1 1per le colonne. Usando l'adorabile formato di output di APL, le possibili griglie di interi sono:

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

Ora supponiamo che l'input sia 1 2 3per le righe e 3 2 1per le colonne. Le possibili griglie intere sono:

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

Risposte:


9

APL (Dyalog) , 42 byte

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

Provalo online!

Utilizza l' ⎕IO←0impostazione predefinita su molti sistemi. L'altra roba nell'intestazione è solo una bella stampa per le matrici (display in scatola).

L'input è un elenco di sei valori, prima le righe vengono sommate, quindi le somme delle colonne.

Come?

o←⍳1+⌈/⍵- oottiene l'intervallo 0al massimo ( ⌈/) dell'input

,o∘.,⊢- prodotto cartesiano con oe appiattire ( ,)

⍣8 - ripetuto per otto volte

3 3∘⍴¨ - modella ogni elenco di 9 elementi in una matrice 3 × 3

¨o←- salva queste matrici in oe per ciascuna

+/,+⌿- controlla se le righe sum ( +/) concatenate alla colonna sum ( +⌿)

⍵≡ - corrisponde all'ingresso

o/⍨- filtro o(l'array di matrici) per valori di verità


Questa risposta molto carina ha bisogno di una spiegazione (per favore).

@Lembik ha aggiunto una spiegazione
Uriel il

Grazie. Quindi elenchi tutte le matrici possibili e controlli quelle che si adattano ai vincoli che sembra. Non il più efficiente, ma funziona.

1
@Lembik yup, questo è il più breve. Potrei gestirne un po 'più efficiente ottenendo tutti gli elenchi a 3 elementi che possono corrispondere alle somme, quindi scegliere quelli che si adattano alla somma della prima riga quindi scegliere quelli (per ciascuna delle combinazioni precedenti) che corrispondono alla somma delle prime colonne, e così avanti e indietro. Sarebbe l'algoritmo generale non a forza bruta.
Uriel,

@EriktheOutgolfer grazie, ho sempre dimenticato di aggiornare il mio conteggio di byte
Uriel

7

Buccia , 20 17 byte

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

-3 byte grazie a @ H.PWiz

Prende l'input come un elenco che xscodifica i vincoli [r_1,r_2,r_3,c_1,c_2,c_3], provalo online!

Spiegazione

Approccio a forza bruta: P Genera tutte le griglie 3x3 con voci [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

Brachylog , 17 byte

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

Provalo online!

ATTENZIONE: USCITA BRUTTA! Non preoccuparti, è ancora leggibile dall'uomo, non sono tenuto a spiegare quanto. ;)

Per qualche motivo deve essere molto più lungo di quanto mi aspetterei di avere senso (13 byte):

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

Quest'ultima versione, se avesse funzionato, avrebbe invece preso input dall'output (cioè argomento della riga di comando).


@Riker Leggi la sezione "Output" dell'OP. Certo, ha ancora parentesi che separano le griglie, avrebbe potuto anche
rimuoverle

4

Python 2 , 149 145 142 141 138 136 byte

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*

Provalo online!

Accetta input come un elenco di elenchi: [[r1, c1], [r2, c2], [r3, c3]]


4

Haskell, 94 88 84 79 byte

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

Prende le somme delle righe e delle colonne come un unico elenco piatto a 6 elementi [r1,r2,r3,c1,c2,c3].

Provalo 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

Poiché gli elementi delle matrici da testare arrivano alla somma di r, il codice non termina in tempo ragionevole per somme di riga / colonna elevate. Ecco una versione che arriva al massimo r, più veloce, ma 4 byte in più: provala online!


3

Mathematica, 81 byte

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

trova tutte le matrici 3x3 con elementi 0..Max e seleziona quelle giuste
ciò significa che le (Max+1)^9matrici devono essere verificate

Provalo online!


Potresti aggiungere una spiegazione per favore.

3
@Lembik Lo farò, dopo aver aggiunto alcuni casi di test e aver reso questa sfida "chiara" per tutte le persone qui. Ho votato per riaprire, ma sembra che tu non cerchi di renderlo migliore per tutti coloro che hanno bisogno di aiuto
J42161217

Aggiunto alla domanda ora.

Cosa non è ancora chiaro? / Gridlavora anche con TIO, usando ToString. Provalo online!
user202729

@ user202729 per me non c'era nulla, ma mancavano i casi di test
J42161217

3

R , 115 110 byte

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)

Provalo online!

Accetta input come c(r1,r2,r3,c1,c2,c3) un singolo vectore stampa le matrici su stdout.

È abbastanza simile alla risposta APL di Uriel , ma genera le griglie 3x3 in modo leggermente diverso.

Lasciare M=max(S), genera il vettore 0:M, quindi lo repmangia 9 volte, cioè [0..M, 0...M, ..., 0...M]nove volte. Quindi seleziona tutte le combinazioni di quel nuovo vettore prese 9 alla volta, usando matrix, 3, 3per convertire ogni 9 combinazione in una 3x3matrice e forzando simplify=Fa restituire un elenco piuttosto che un array. Quindi unifica questo elenco e lo salva come m.

Quindi filtra mper quelli in cui le somme di riga / colonna sono identiche all'input, stampando quelle che lo sono e non facendo nulla per quelle che non lo sono.

Dal momento che calcola choose(9*(M+1),9) diverse possibili griglie (più delle (M+1)^9possibilità), esaurirà la memoria / il tempo più velocemente della risposta più efficiente (ma meno golfica) di seguito:

R , 159 byte

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

Provalo online!


R è molto gradita!

3

MATL , 35 22 byte

-13 byte grazie a Luis Mendo

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

Provalo online!

Il collegamento è a una versione del codice che stampa un po 'più bene; questa versione stamperà solo tutte le matrici con una sola nuova riga tra di loro.

Accetta input come [c1 c2 c3 r1 r2 r3] .

Ovviamente, questo calcola il potere cartesiano X^ di 0...max(input)esponente 9e trasposizione !. Quindi passa "sopra le colonne, rimodellandole ciascuna @come una matrice 3x3 3e, duplicandole t, trasponendole !e concatenandole orizzontalmente h. Quindi calcola le somme delle colonne s, che risulteranno nel vettore [c1 c2 c3 r1 r2 r3]. Facciamo uguaglianza elementale all'input G=e, se ?tutti sono diversi da zero, recuperiamo la matrice corretta selezionando l'input per la funzione !usando 4M.


2

Lotto, 367 byte

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

Il quadrato 2 × 2 in alto a sinistra forza il risultato, quindi l'approccio migliore è generare tutti i valori per l'intero in alto a sinistra, tutti i valori validi per la somma dell'intero in alto a sinistra e in alto al centro, tutti i valori validi per la somma del primo intero sinistro e medio sinistro, e calcola l'intervallo di valori validi per l'intero medio, quindi, dopo aver attraversato tutti gli intervalli appropriati, calcola i valori rimanenti dai vincoli.


1

Python 2 , 118 byte

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)

Provalo online!


Python 2 , 123 byte

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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.