枚举带约束的所有可能的整数网格


17

问题

考虑非负整数的3×3正方形网格。对于每一行i,整数的总和设置为r_i。同样,对于每一列j,该列中的整数总和设置为c_j

任务是编写代码,以在给定行和列总和约束的情况下枚举所有可能的不同整数分配给网格。您的代码应该一次输出一个分配。

输入项

您的代码应使用3个非负整数指定行约束,并使用3个非负整数指定列约束。您可以假设它们是有效的,即,总和或行约束等于列约束之和。您的代码可以通过任何方便的方式执行此操作。

输出量

您的代码应以您选择的任何人类可读格式输出其计算的不同2D网格。当然,越漂亮越好。输出中不得包含重复的网格。

如果所有行和列约束都完全相同1,则只有6不同的可能性。对于第一行,您可以1在前三列中的任何一列中输入a,对于第二行,现在有2替代方法,最后一行现在完全由前两行确定。网格中的其他所有内容都应设置为0

说输入是2 1 0针对行还是1 1 1针对列。使用APL的可爱输出格式,可能的整数网格为:

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

现在说输入是1 2 3行和3 2 1列的。可能的整数网格为:

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

Answers:


9

APL(Dyalog),42字节

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

在线尝试!

⎕IO←0在许多系统上使用默认值。标头中的其他内容只是用于矩阵的漂亮打印(盒装显示)。

输入是六个值的列表,首先是行总和,然后是列总和。

怎么样?

o←⍳1+⌈/⍵- o使范围0达到⌈/输入的最大值()

,o∘.,⊢-具有o并展平(,)的笛卡尔积

⍣8 -重复八次

3 3∘⍴¨ -将每9个项目列表成形为3×3矩阵

¨o←-将这些矩阵分别保存到o

+/,+⌿-检查行总和(+/)级联到列总和(+⌿

⍵≡ -与输入相对应

o/⍨- o通过真实值过滤(矩阵数组)


这个非常漂亮的答案需要一个解释(请)。

@Lembik添加了解释
Uriel

谢谢。因此,您将枚举所有可能的矩阵,并检查那些符合其约束条件的矩阵。不是最有效的,但是它可以工作。

1
@Lembik是的,那是最短的。我可以通过获取所有可以匹配总和的3个项目列表,然后选择与第一行总和匹配的项目,然后选择与第一列总和匹配的项目(对于每个先前的组合)来管理一个效率更高的项目。以此类推。那将是非蛮力的通用算法。
Uriel

@EriktheOutgolfer谢谢,我总是忘了更新字节数
Uriel

7

外壳20 17字节

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

-3个字节,感谢@ H.PWiz

将输入作为xs编码约束的列表[r_1,r_2,r_3,c_1,c_2,c_3],请在线尝试!

说明

蛮力方法:P生成所有具有条目的3x3网格[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个字节

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

在线尝试!

警告:难看的输出!不要弹开,它仍然是人类可读的,不需要我说明多少。;)

由于某些原因,它必须比我期望的要长得多(13字节):

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

如果后者有效,它将取而代之从输出中获取输入(即命令行参数)。


@Riker阅读OP的“输出”部分。当然,它仍然具有分隔网格的括号,它也可以剥离网格,并且输出仍然不会丢失任何数据……
Egg the Outgolfer

4

Python 2中149个 145 142 141 138 136字节

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*

在线尝试!

将输入作为列表列表: [[r1, c1], [r2, c2], [r3, c3]]


4

Haskell,94 88 84 79字节

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

将行和列的总和作为单个平面6元素列表 [r1,r2,r3,c1,c2,c3]

在线尝试!

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

由于要测试的矩阵元素达到的总和r,因此对于大的行/列总和,代码无法在合理的时间内完成。这是一个达到最高r速度的版本,但增加了4个字节:在线尝试!


3

Mathematica,81个字节

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

查找所有元素为0..Max的3x3矩阵,并选择正确的矩阵,
这意味着(Max+1)^9必须检查矩阵

在线尝试!


请您补充说明。

3
@Lembik我将在您添加一些测试用例并使所有此处的人都明白这一挑战之后。我投票决定重新开放,但您似乎并没有尝试对所有需要帮助的人做得更好
J42161217

现在添加到问题。

还有什么不清楚?/ Grid也可以使用与TIO一起使用ToString在线尝试!
user202729

@ user202729对我来说什么都没有,但是缺少测试用例
J42161217 '17

3

R115110字节

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)

在线尝试!

将输入作为c(r1,r2,r3,c1,c2,c3)vector,并将矩阵打印到标准输出。

这与Uriel的APL答案非常相似,但生成3x3网格的方式有所不同。

M=max(S),它产生的矢量0:M,然后rep吃它的9倍,也就是说,[0..M, 0...M, ..., 0...M]九次。然后,它一次选择9个新矢量的所有组合,matrix, 3, 3用于将每个9个组合转换为3x3矩阵,并强制simplify=F返回列表而不是数组。然后,它唯一化此列表并将其另存为m

然后,它对m行/列总和与输入相同的那些进行过滤,打印那些行/列之和,对不等于的输入不做任何处理。

由于它计算choose(9*(M+1),9)不同的可能的网格(比可能的网格更多(M+1)^9),因此它的内存/时间用完速度比以下更有效(但不那么麻烦)的答案要快:

R,159字节

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

在线尝试!


R非常欢迎!

3

MATL35 22字节

-13字节感谢Luis Mendo

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

在线尝试!

链接是一个可以更好打印的代码版本。此版本将只打印所有矩阵,并且它们之间只有一个换行符。

将输入作为[c1 c2 c3 r1 r2 r3]

显然,这种计算笛卡尔功率X^0...max(input)与指数9以及移调!。然后",它在列上循环,将每列重塑@为3x3矩阵3e,进行复制t,转置!和水平串联h。然后,它计算列总和s,这将得出向量[c1 c2 c3 r1 r2 r3]。我们做的elementwise平等的输入G=,如果?都是零,我们通过选择输入功能恢复正确的矩阵!使用4M


2

批处理,367字节

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

左上方的2×2平方会强制计算结果,因此最好的方法是生成左上方整数的所有值,左上方整数和顶部中间整数之和的所有有效值,顶上方总和的所有有效值左整数和左中间整数,并计算中间整数的有效值范围,然后遍历所有适当范围,然后根据约束条件计算剩余值。


1

Python 2,118字节

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)

在线尝试!


Python 2,123字节

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

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.