제약 조건이있는 모든 가능한 정수 격자를 열거하십시오.


17

문제

음이 아닌 정수의 제곱 3 x 3 그리드를 고려하십시오. 각 행 i에 대해 정수의 합은로 설정됩니다 r_i. 마찬가지로 각 열에 대해 해당 열의 j정수 합계는로 설정됩니다 c_j.

이 작업은 행 및 열 합계 제약 조건이 주어지면 그리드에 가능한 모든 다른 정수 할당을 열거하는 코드를 작성하는 것입니다. 코드는 한 번에 하나의 과제를 출력해야합니다.

입력

코드는 행 제약 조건을 지정하는 음이 아닌 정수 3 개와 열 제약 조건을 지정하는 음이 아닌 정수 3 개를 가져야합니다. 이들이 유효하다고 가정 할 수 있습니다. 즉 합 또는 행 제한 조건이 열 제한 조건의 합과 같다고 가정 할 수 있습니다. 코드는 편리한 방법으로이 작업을 수행 할 수 있습니다.

산출

코드는 선택한 사람이 읽을 수있는 형식으로 계산하는 다른 2D 그리드를 출력해야합니다. 물론 예뻐질수록 좋습니다. 출력에 중복 그리드가 포함되지 않아야합니다.

모든 행과 열 제약 조건이 정확히 일치 1하면 6다른 가능성 만 있습니다. 첫 번째 행 1의 경우 처음 세 열 중 하나에을 넣을 수 있습니다 . 두 번째 행의 경우 이제 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│
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘

답변:


9

APL (Dyalog) , 42 바이트

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

온라인으로 사용해보십시오!

⎕IO←0많은 시스템에서 기본값을 사용 합니다. 헤더의 다른 것들은 행렬 (상자 표시)에 대한 예쁜 인쇄입니다.

입력은 6 개의 값, 행 합계를 먼저 합한 후 열 합계를 나열한 것입니다.

어떻게?

o←⍳1+⌈/⍵- 입력 의 최대 o범위 0( ⌈/) 를 얻습니다.

,o∘.,⊢-데카르트 곱 o및 펴기 ( ,)

⍣8 -8 번 반복

3 3∘⍴¨ -모든 9 개 항목 목록을 3 × 3 행렬로 형상화

¨o←-이 행렬을에 저장 o하고 각각에 대해

+/,+⌿- 로우 합 (있는지 확인 +/열의 합에 연결된) ( +⌿)

⍵≡ -입력에 해당

o/⍨- o정확한 값으로 필터 (행렬 배열)


이 매우 근사한 답변에는 설명이 필요합니다 (제발).

@Lembik 님이 설명을 추가했습니다
Uriel

감사. 따라서 가능한 모든 행렬을 열거하고 제약 조건에 맞는 행렬을 확인하십시오. 가장 효율적인 것은 아니지만 작동합니다.

1
@Lembik yup, 가장 짧습니다. 합계와 일치 할 수있는 모든 3 개의 항목 목록을 가져 와서 첫 번째 행 합계에 맞는 목록을 선택한 다음 첫 번째 열 합계와 일치하는 항목을 선택하십시오 (이전 조합 각각에 대해) 등등. 이것이 브뤼 포스가 아닌 일반적인 알고리즘 일 것입니다.
Uriel

@EriktheOutgolfer 감사합니다, 항상 바이트 수를 업데이트하는 것을 잊어 버렸습니다.
Uriel

7

껍질 , 20 17 바이트

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

@ H.PWiz 덕분에 -3 바이트

목록으로 입력을 받아 xs제약을 인코딩 [r_1,r_2,r_3,c_1,c_2,c_3], 온라인 그것을 시도!

설명

Brute force approach : 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

근접 , 17 바이트

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

온라인으로 사용해보십시오!

경고 : 추악한 출력! 겁내지 말고, 여전히 사람이 읽을 수 있으며, 얼마를 설명 할 필요는 없습니다. ;)

어떤 이유로 든 내가 이해할 것으로 예상되는 것보다 훨씬 길어야합니다 (13 바이트).

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

이 후자의 버전이 작동했다면 대신 출력 (예 : 명령 줄 인수)에서 입력을 받았을 것입니다.


@Riker OP의 "출력"섹션을 읽으십시오. 물론, 그리드를 분리하는 괄호가 있으며, 스트립을 제거 할 수 있으며 출력에서 ​​여전히 데이터가 손실되지 않습니다 ...
Erik the Outgolfer


4

하스켈, 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

3

R , 115110 바이트

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)single 로 취하고 vector행렬을 stdout에 인쇄합니다.

Uriel의 APL answer 와 매우 유사 하지만 3x3 그리드를 약간 다르게 생성합니다.

시키는 M=max(S) 는 벡터를 생성하는 것은, 0:M다음, rep그것을 즉, 9 시간, 먹는 [0..M, 0...M, ..., 0...M]아홉 번. 그런 다음 matrix, 3, 3각 9 개의 조합을 3x3행렬 로 변환 simplify=F하고 배열이 아닌 목록을 강제 로 사용하여 한 번에 9 개의 새 벡터의 모든 조합을 선택합니다 . 그런 다음이 목록을 고유 화하고로 저장합니다 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

MATL , 35 22 바이트

Luis Mendo 덕분에 -13 바이트

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

온라인으로 사용해보십시오!

링크는 좀 더 멋지게 인쇄되는 코드 버전입니다. 이 버전은 모든 행렬을 하나의 줄 바꿈으로 인쇄합니다.

다음과 같이 입력을받습니다. [c1 c2 c3 r1 r2 r3] 받습니다.

분명히 이것은 지수 와 전치로 의 데카르트 힘 X^을 계산합니다 . 그런 다음 열 을 반복 하여 각각 3x3 행렬로 형태를 변경 하고 복제 , 전치 및 수평으로 연결합니다 . 그런 다음 열 합계를 계산 하여 벡터가 됩니다. 우리는 입력 과 요소 적으로 동등하며, 모두 0이 아닌 경우 를 사용하여 함수 에 대한 입력을 선택하여 올바른 행렬을 복구합니다 .0...max(input)9!"@3et!hs[c1 c2 c3 r1 r2 r3]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 제곱은 결과를 강제하므로 가장 좋은 방법은 왼쪽 위 정수에 대한 모든 값, 왼쪽 위와 상단 중간 정수의 합에 대한 모든 유효한 값, 위쪽의 합에 대한 모든 유효한 값을 생성하는 것입니다. 왼쪽 및 중간 왼쪽 정수를 입력하고 중간 정수에 유효한 값 범위를 계산 한 다음 모든 적절한 범위를 반복하여 제약 조건에서 나머지 값을 계산하십시오.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.