킬러 스도쿠 솔버 구축


9

일반 스도쿠가 어렵다고 생각했습니다. 이제 Killer Sudoku를 사용해보십시오 !

Killer Sudoku 게임에서는 숫자가 전혀 주어지지 않습니다. 대신 특정 숫자를 더한 지역이 제공됩니다. Wikipedia의 다음 예제를 고려하십시오.

킬러 스도쿠 퍼즐

그리고 그 해결책 :

킬러 스도쿠 퍼즐 솔루션

작성하는 프로그램은 지역을 나타내는 81 개의 문자 시퀀스와 일련의 숫자로 구성된 형식을 취합니다. 그런 다음 시퀀스의 각 숫자는 "A", "B"등에서 시작하여 각 문자 영역의 숫자 합계를 나타냅니다.

그런 다음 솔루션을 나타내는 81 자리 시퀀스를 출력합니다.

예를 들어 위의 퍼즐 예는 다음과 같은 입력을 갖습니다.

AABBBCDEFGGHHCCDEFGGIICJKKFLMMINJKOFLPPQNJOORSPTQNUVVRSTTQWUUXXSYZWWaaXXSYZWbbbcc
3 15 22 4 16 15 25 17 9 8 20 6 14 17 17 13 20 12 27 6 20 6 10 14 8 16 15 13 17

결과 출력은 다음과 같습니다.

215647398368952174794381652586274931142593867973816425821739546659428713437165289

입력이 유효하고 영역이 항상 A, B, ..., Y, Z, a, b, ..., z 순서대로 나타날 것이라고 가정 할 수 있습니다.

(작동하는 가장 짧은 코드가 승리합니다.)


어떻게 경쟁에서이기나요? 가장 짧은 코드? 가장 빠른 코드?
beary605

가장 짧은 코드. [문자 제한을 1 자로 빠뜨
Joe Z.

그리고 52 개가 넘는 지역이 있다면 무엇입니까?
Mr Lister

45 개 이하의 지역이 없을 것이라고 가정 할 수 있습니다.
Joe Z.

1
케이지 내에서 숫자를 반복 할 수 있습니까?
피터 테일러

답변:


4

R-378 자

가정

x="AABBBCDEFGGHHCCDEFGGIICJKKFLMMINJKOFLPPQNJOORSPTQNUVVRSTTQWUUXXSYZWWaaXXSYZWbbbcc"
y="3 15 22 4 16 15 25 17 9 8 20 6 14 17 17 13 20 12 27 6 20 6 10 14 8 16 15 13 17"

378 자 :

z=strsplit
v=sapply
R=rep(1:9,9)
C=rep(1:9,e=9)
N=1+(R-1)%/%3+3*(C-1)%/%3
G=z(x,"")[[1]]
M=as.integer(z(y," ")[[1]])[order(unique(G))]
s=c(1,rep(NA,80))
i=1
repeat if({n=function(g)!any(v(split(s,g),function(x)any(duplicated(x,i=NA))))
S=v(split(s,G),sum)
n(R)&&n(C)&&n(N)&&n(G)&&all(is.na(S)|S==M)}){if(i==81)break;i=i+1;s[i]=1}else{while(s[i]==9){s[i]=NA
i=i-1};s[i]=s[i]+1}
s

2,964,690 회 반복 한 후 겸손한 PC에서 약 1 시간이 소요되는 솔루션에 도달합니다.


골퍼 해제 :

ROWS   <- rep(1:9, 9)
COLS   <- rep(1:9, each = 9)
NONETS <- 1 + (ROWS - 1) %/% 3 + 3 * (COLS - 1) %/% 3
CAGES  <- strsplit(x, "")[[1]]
SUMS   <- as.integer(strsplit(y, " ")[[1]])[order(unique(CAGES))]

is.valid <- function(sol) {

   has.no.repeats <- function(sol, grouping) {
      !any(vapply(split(sol, grouping),
                  function(x) any(duplicated(x, incomparables = NA)),
                  logical(1)))
   }
   has.exp.sum <- function(sol, grouping, exp.sums) {
      sums <- vapply(split(sol, grouping), sum, integer(1))
      all(is.na(sums) | sums == exp.sums)
   }

   has.no.repeats(sol, ROWS  ) &&
   has.no.repeats(sol, COLS  ) &&
   has.no.repeats(sol, NONETS) &&
   has.no.repeats(sol, CAGES ) &&
   has.exp.sum(sol, CAGES, SUMS)        
}

sol <- c(1L, rep(NA, 80)) # start by putting a 1
i <- 1L                   # in the first cell
it <- 0L

repeat {
   it <- it + 1L
   if (it %% 100L == 0L) print(sol)
   if(is.valid(sol)) {         # if everything looks good
      if (i == 81L) break         # we are either done
      i <- i + 1L                 # or we move to the next cell
      sol[i] <- 1L                # and make it a 1
   } else {                    # otherwise
      while (sol[i] == 9L) {      # while 9s are found
         sol[i] <- NA             # replace them with NA
         i <- i - 1L              # and move back to the previous cell
      }
      sol[i] <- sol[i] + 1L       # when a non-9 is found, increase it
   }                           # repeat
}
sol

4

GolfScript, 138 자

n%~[~]:N;1/:P.&:L;9..*?{(.[{.9%)\9/}81*;]:§;L{.`{\~@@=*}+[P§]zip%{+}*\L?N==}%§9/..zip+\3/{{3/}%zip{{+}*}%}%{+}*+{.&,9=}%+1-,!{§puts}*.}do;

이것은 GolfScript의 킬러 스도쿠 솔버입니다. 위의 예에서와 같이 STDIN의 입력은 두 행으로 예상됩니다.

참고 : 퍼즐 설명은 실행 시간을 제한하지 않기 때문에 속도보다 작은 코드 크기를 선호했습니다. 이 코드는 느린 컴퓨터에서 시간이 걸릴 수있는 솔루션에 대한 모든 9 ^ 81 그리드 구성을 테스트합니다. ;-)


확인할 수 있습니까? : P
Joe Z.

@JoeZeng, 4x4로 쉽게 조정할 수 있습니다. 다음은 테스트 사례입니다.AABBCADEFFDDGGGG 6 7 4 8 2 3 10
Peter Taylor

@PeterTaylor 테스트 케이스에는 4 가지 유효한 솔루션이 있습니다.
Joe Z.

4

루비, 970 자

A,B=gets,gets.split
L=[]
R=[]
U=[]
D=[]
N=[]
C=[]
S=[]
O=[0]*81
z='A'
(0..324).map{|j|U<<j;D<<j;R<<(j+1)%325;L<<(j+324)%325;N<<j;C<<j;S<<0}
X=->s,j,c,cf,n{j<81?(z==A[j]?(0..8).map{|i|X[s-1-i,j+1,c+[i],cf+[1+j,1+81+27*i+j/9,1+81+27*i+9+j%9,1+81+27*i+18+j/3%3+j/27*3],n+[i+1]]}:X[s,j+1,c,cf,n+[0]]if s>=0):(h=U.size;cf.uniq.sort.map{|l|N<<n;L<<(L[h]||h);R<<h;U<<U[l];D<<l;C<<l;S[l]+=1;L[R[-1]]=R[L[-1]]=U[D[-1]]=D[U[-1]]=L.size-1}if s==0)}
Y=->c{L[R[c]]=L[c];R[L[c]]=R[c];i=D[c];(j=R[i];(U[D[j]]=U[j];D[U[j]]=D[j];S[C[j]]-=1;j=R[j])while j!=i;i=D[i])while i!=c}
Z=->c{i=U[c];(j=L[i];(S[C[j]]+=1;U[D[j]]=j;D[U[j]]=j;j=L[j])while j!=i;i=U[i])while i!=c;L[R[c]]=c;R[L[c]]=c}
B.map{|k|X[k.to_i,0,[],[],[]];z=z=='Z'?'a':z.next}
s=->k{c=R[0];c<1?($><<(O[0,k].map{|s|N[s]}.transpose.map &:max)*""):(g=S[b=c];g=S[b=c]if S[c]<g while 0<c=R[c];Y[b];r=D[b];(O[k]=r;j=R[r];(Y[C[j]];j=R[j])while j!=r;s[k+1];r=O[k];c=C[r];j=L[r];(Z[C[j]];j=L[j])while j!=r;r=D[r])while r!=b;Z[b])}
s[0]

위의 루비 코드는 내 GolfScript 구독과 반대입니다. 꽤 길지만 아직 완전히 골프는 아니지만 속도에 최적화되어 있습니다. 위에서 주어진 킬러 스도쿠는 1 초 안에 잘 풀립니다 (원래 Java 버전에서는 몇 밀리 초였습니다). 솔버 자체는 Knuth의 DLX 알고리즘의 기본 구현입니다.

입력은 STDIN에서 두 줄로 제공되어야합니다. 예 ( 온라인 ) :

> AABBBCDEFGGHHCCDEFGGIICJKKFLMMINJKOFLPPQNJOORSPTQNUVVRSTTQWUUXXSYZWWaaXXSYZWbbbcc
3 15 22 4 16 15 25 17 9 8 20 6 14 17 17 13 20 12 27 6 20 6 10 14 8 16 15 13 17

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