루비 -541 ..., 394
기본 알고리즘은 행 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 를 추가 하는 것보다 짧을 수 있습니다 .
풀기 및 설명 :
(이것은 531 바이트 버전에서 왔으며 변경했습니다. 가장 주목할 만하게도 제품 호출을 제거했습니다. 한 번에 한 행 / 열 당 한 자릿수 만 해결하면 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 초기