สร้างนักฆ่า Sudoku Solver


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 ภูมิภาคแล้วจะเป็นอย่างไร
นาย 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 ครั้ง


De-แข็งแรงเล่นกอล์ฟ:

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 กรณีทดสอบของคุณมีวิธีแก้ไขปัญหาที่ถูกต้องสี่แบบ
Joe Z.

4

Ruby, 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 ของฉัน มันค่อนข้างยาว (และยังไม่ได้เล่นกอล์ฟอย่างเต็มที่) แต่ปรับให้เหมาะกับความเร็ว ซูโดกุนักฆ่าที่ได้รับข้างต้นได้รับการแก้ไขภายในไม่กี่วินาที (ด้วยจาวาเวอร์ชันดั้งเดิมของฉันมันเป็นเพียงไม่กี่วินาทีเท่านั้น) ตัวแก้ปัญหาเองนั้นเป็นการใช้งานพื้นฐานของอัลกอริทึม DLX ของ Knuth

ต้องป้อนข้อมูลเป็นสองบรรทัดใน 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.