Ruby - 541 ..., 394
Thuật toán cơ bản là một tìm kiếm theo chiều sâu đệ quy đầu tiên của các bản sao để chọn một cách khẳng định, xem qua hàng 1, rồi cột 1, rồi hàng 2, v.v. và kiểm tra xem hai hàng xóm không bị giết và lưới được kết nối (đó là break if
mệnh đề trong ở đó, và bit đến trước nó).
K=(0...(N=gets.to_i)*N).to_a
J=gets(p).split*''
H=->m{K&[m+1,m-1,m+N,m-N]}
Q=->k{s=[k[j=0]]
(j=s.size
s.map{|x|(s+=H[x]&k).uniq!})while s[j]
break if(K-k).any?{|m|(H[m]-k)[0]}||k!=k&s
$><<K.map{|m|[k.index(m)?J[m]:?#,m%N>N-2?"
":p]}*''|exit if !g=((0...N*2).map{|x|(k.select{|m|m.divmod(N)[x/N]==x%N}.group_by{|m|J[m]}.find{|l,c|c[1]}||[])[1]}-[p]).min
g.map{|d|Q[k-g<<d]}}
Q[K]
puts"no answer"
Một số thủ thuật gọn gàng:
if w[1]
ngắn hơn nhiều if !w.one?
và nếu bạn biết có ít nhất một thành viên, đó là kết quả tương tự.
Tương tự, [0]
ngắn hơn any?
nếu không có khối và s[j]
là một phím tắt dễ thương cho j<s.size
(về mặt kỹ thuật, nó giống như j.abs<s.size
)
Và y%N+(y/N).i
ngắn hơn nhiều so vớiComplex(y%N,y/N)
Ngoài ra, khi có hai điều kiện phức tạp để tạo chuỗi, có thể sẽ ngắn [cond1?str1a:str1b,cond2?str2a:str2b]*''
hơn so với việc thêm tất cả các parens hoặc #{}
s vào.
Ungolfing và giải thích:
(Đây là từ phiên bản 531 byte. Tôi đã thực hiện các thay đổi. Đáng chú ý nhất là tôi đã loại bỏ lệnh gọi sản phẩm - chỉ giải quyết một chữ số trên mỗi hàng / cột và J hiện chỉ là một mảng, được lập chỉ mục bởi số nguyên. Tất cả các tọa độ chỉ là số nguyên.)
H
tính toán hàng xóm
def H m
# m, like all indices, is a complex number
# where the real part is x and the imaginary is y
# so neighbors are just +/-i and +/-1
i='i'.to_c
neighborhood = [m+1, m-1, m+i, m-i]
# and let's just make sure to eliminate out-of-bounds cells
K & neighborhood
end
N
là kích thước của lưới
N = gets.to_i
K
là các phím của bản đồ (số phức)
# pretty self-explanatory
# a range of, e.g., if N=3, (0..8)
# mapped to (0+0i),(1+0i),(2+0i),(0+1i),(1+1i),(2+1i),...
K = (0..N**2-1).map{|y| (y%N) +(y/N).i }
J
là bản đồ đầu vào (tù)
# so J is [[0+0,"2"],[0+1i,"3"],....].to_h
J=K.zip($<.flat_map {|s|
# take each input line, and...
# remove the "\n" and then turn it into an array of chars
s.chomp.chars
}).to_h
k
là các phím không bị giết
# starts as K
Q
là phương pháp đệ quy chính
def Q k
j=0 # j is the size of mass
# the connected mass starts arbitrarily wherever k starts
mass=[k[0]]
while j < s.size # while s hasn't grown
j = mass.size
mass.each{|cell|
# add all neighbors that are in k
(mass+=H[cell] & k).uniq!
}
end
# if mass != k, it's not all orthogonally connected
is_all_connected = k!=k&mass
# (K-k) are the killed cells
two_neighbors_killed = (K-k).any?{|m|
# if any neighbors of killed cells aren't in k,
# it means it was killed, too
(H[m]-k)[0]
}
# fail fast
return if two_neighbors_killed || is_all_connected
def u x
x.group_by{|m|J[m]}.select{|l,c|c[1]}
end
rows_with_dupes = Array.new(N){|r|u[k.select{|m|m.imag==r}]}
cols_with_dupes = Array.new(N){|r|u[k.select{|m|m.real==r}]}
# dupes is an array of hashes
# each hash represents one row or column. E.g.,
# {
# "3"=>[(0+0i),(1+0i),(3+0i)],
# "2"=>[(2+0i),(4+0i)]
# }
# means that the 0th, 1st and 3rd cells in row 0
# all are "3", and 2nd and 4th are "2".
# Any digits without a duplicate are rejected.
# Any row/col without any dupes is removed here.
dupes = (rows_with_dupes+cols_with_dupes-[{}])
# we solve one row at a time
first_row = dupes[0]
if !first_row
# no dupes => success!
J.map{|m,v|k.member?(m)?v:?#}.each_slice(N){|s|puts s*''}
exit
else
# the digit doesn't really matter
t=first_row.values
# cross-multiply all arrays in the row to get a
# small search space. We choose one cell from each
# digit grouping and drop the rest.
t.inject(:product).map{ |*e|
# Technically, we drop all cells, and add back the
# chosen cells, but it's all the same.
new_k = k-t.flatten+e.flatten
# and then search that space, recursively
Q[new_k]
}
end
end
Mã được thực thi với:
# run with whole board
Q[K]
# if we get here, we didn't hit an exit, so we fail
puts"no answer"
Thay đổi
394 đã thêm đề xuất của @ blutorange bên dưới và cắt ra nhiều thao tác hơn
408 điều chỉnh đầu ra một lần nữa. Cũng sử dụng .min
thay vì .inject(:+)
kể từ khi tôi chỉ lấy một hàng.
Tính toán đầu ra ngắn hơn 417
421 giảm số phức. Chỉ cần sử dụng số nguyên. Lưu một bó
Thêm 450 cải tiến đầu vào
456 cải tiến đầu vào
462 cải tiến gia tăng - đặc biệt. find
, không phảiselect
475 rơi u
và đè bẹp người xây dựng hàng / col dupe
503 chỉ giải quyết một chữ số trùng lặp trên mỗi hàng / cột tại một thời điểm.
530 sử dụng map &:pop
thay vìvalues
531 kéo ra lambda làm cho mảng dupes
552 oái oăm! bỏ lỡ một yêu cầu
536 dân số được cải thiện một chút về mảng dupes (trước đây là d
)
541 ban đầu