ทับทิม - 541 ... , 394
อัลกอริทึมพื้นฐานคือการค้นหาความลึกแรก recursive ซ้ำเพื่อยืนยันเลือกมองผ่านแถวที่ 1 แล้วคอลัมน์ 1 แล้วแถวที่ 2, ฯลฯ และการตรวจสอบว่าสองประเทศเพื่อนบ้านไม่ได้ถูกฆ่าตายและตารางมีการเชื่อมต่อ (ที่break if
ประโยคหนึ่งใน ตรงนั้นและบิตที่มาก่อน)
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"
เทคนิคบางอย่างเรียบร้อย:
if w[1]
สั้นกว่าif !w.one?
และถ้าคุณรู้ว่ามีสมาชิกอย่างน้อยหนึ่งคนก็เป็นผลลัพธ์เดียวกัน
ในทำนองเดียวกัน[0]
จะสั้นกว่าany?
หากไม่มีบล็อกและs[j]
เป็นทางลัดที่น่ารักสำหรับj<s.size
(ในทางเทคนิคแล้วจะมีลักษณะเหมือนj.abs<s.size
)
และy%N+(y/N).i
สั้นกว่ามากComplex(y%N,y/N)
นอกจากนี้เมื่อมีสองเงื่อนไขที่ซับซ้อนในการสร้างสตริงมันอาจจะสั้นกว่าที่จะทำ[cond1?str1a:str1b,cond2?str2a:str2b]*''
มากกว่าการเพิ่ม parens หรือ#{}
s ทั้งหมด
Ungolfing และคำอธิบาย:
(นี่คือจากรุ่น 531 byte ฉันได้ทำการเปลี่ยนแปลงที่สำคัญที่สุดตั้งแต่ฉันได้ยกเลิกการเรียกใช้ผลิตภัณฑ์ - เพียงแค่แก้หนึ่งหลักต่อแถว / คอลัมน์ในแต่ละครั้งและตอนนี้ J เป็นเพียงอาร์เรย์ที่จัดทำดัชนีโดย จำนวนเต็มพิกัดทั้งหมดเป็นเพียงจำนวนเต็ม)
H
คำนวณเพื่อนบ้าน
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
คือขนาดของกริด
N = gets.to_i
K
คือกุญแจสู่แผนที่ (จำนวนเชิงซ้อน)
# 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
คือแผนที่อินพุต (คุก)
# 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
เป็นกุญแจที่ไม่ถูกฆ่า
# starts as K
Q
เป็นวิธีการเรียกซ้ำหลัก
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
รหัสจะถูกดำเนินการด้วย:
# run with whole board
Q[K]
# if we get here, we didn't hit an exit, so we fail
puts"no answer"
การเปลี่ยนแปลง
เพิ่ม394คำแนะนำของ @ blutorange ด้านล่างและตัดการจัดการที่มากขึ้น
408แก้ไขผลลัพธ์อีกครั้ง ใช้.min
แทน.inject(:+)
เพราะฉันเอาแค่แถวเดียวอยู่ดี
การคำนวณผลลัพธ์ที่สั้นลง417
421ลดจำนวนเชิงซ้อน เพียงใช้จำนวนเต็ม บันทึกบันเดิล
ปรับปรุงอินพุตเพิ่มอีก450 รายการ
การปรับปรุงอินพุต456
การปรับปรุงที่เพิ่มขึ้น462 - esp find
ไม่ใช่select
475ดร็อปu
และบีบตัวสร้างแถว / คอลัมน์คู่
503แก้ไขตัวเลขที่ซ้ำกันหนึ่งหลักต่อแถว / คอลัมน์ในแต่ละครั้ง
530ใช้map &:pop
แทนvalues
531ดึงแลมบ์ดาออกมาซึ่งทำให้อาเรย์ของคู่หู
552โอ๊ะโอ! พลาดความต้องการ
536 การปรับปรุงจำนวนประชากรของอาร์เรย์ที่ซ้ำกัน (ก่อนหน้านี้คืออะไรd
)
เริ่มต้น541