
전광판에 숫자를 표기하는 전구가 5*3개씩 세트로 되어있고 해당 전구가 전부 정상적일때 표기되는 건 위에 문제에 나와있는데 로와 같음.
10^N개의 층에 혹해서 설마 연산개수가 저정도로 많아질까 걱정하긴 했었는데 최대 9개의 전광판 까지만 다루면 되니까 괜찮았음.
숫자를 표기하는데 필요한 문자가 15개 밖에 안되니 숫자 정보를 가지는 리스트를 만들기로 했음.
number = []
temp = []
temp.append(list("###"))
temp.append(list("#.#"))
temp.append(list("#.#"))
temp.append(list("#.#"))
temp.append(list("###"))
number.append(temp)
temp = []
temp.append(list("..#"))
temp.append(list("..#"))
temp.append(list("..#"))
temp.append(list("..#"))
temp.append(list("..#"))
number.append(temp)
# ...
temp = []
temp.append(list("###"))
temp.append(list("#.#"))
temp.append(list("###"))
temp.append(list("#.#"))
temp.append(list("###"))
number.append(temp)
temp = []
temp.append(list("###"))
temp.append(list("#.#"))
temp.append(list("###"))
temp.append(list("..#"))
temp.append(list("###"))
number.append(temp)
이렇게 number라는 곳에 숫자를 나타내는 전구 정보가 들어가게 됨. 비슷한 코드를 반복해서 쓰는 경우가 가끔 있고, 이를 함수로 빼내는게 애매한 경우가 있는데, 이러면 그냥 복붙으로 붙여넣고 필요한 부분만 바꾸면 제법 빠르게 처리 가능함.
c는 현재 전광판내 특정 숫자가 시작하는 열임.
def find_possible(c):
# number는 위에 만들었던 정답 숫자 전광판표임. board는 입력받은 전광판 정보임.
global number , board
result = []
#숫자 0부터 9까지 전부 확인
for i in range(10):
# 가능한지 여부 확인.
isPossible = True
# 전광판은 5행임.
for y in range(5):
# 전광판은 3열임.
for x in range(3):
# 현재 입력받은 전광판에서 #는 확실히 켜진거임. .는 고장났을지도 모르는 거라 켜질 수도 있고 안켜질 수 있음. 따라서 전광판에 #를 전부 만족하는 숫자들만 찾으면 됨.
if board[y][c+x] == "#" and number[i][y][x] != "#" :
isPossible = False
break
if isPossible == False:
break
# 찾으면 result에 대입. 초기 설계의 흔적으로 str(i)로 했는데 그냥 str 안하고 i로 넣어도 됨.
if isPossible == True:
result.append(str(i))
else:pass
현재 전광판 숫자칸에서 가능한 모든 숫자 후보군들 반환.
return result
answer = 0
reserve = []
for i in range(n):
c = i*3 + i
result = find_possible(c)
# 단 한자리라도 표현 할 수 없는 상황이라면 해당 숫자는 표현할 수 없음. 따라서 -1임.
if result == []:
answer = -1
break
else:
reserve.append(result)
#print(result)
pass
각 자리수를 구하면 합을 구하는 것을 linear 하게 처리 가능함.
예를 들어 n은 2이며 첫째 자리에서 [1,2]가 가능하다고 치고, 두번째 자리에서 [3,4,5]가 가능하다고 치자. 그러면 해당 경우에서 가능한 숫자는 13,14,15,23,24,25다.
가능한 총 경우의 수는 첫째자리수에 가능한 숫자 개수 * 둘째자리수에 가능한 숫자 한 것이며, 일반화하면 각 자리수에서 가능한 숫자들의 개수들의 곱이 총 경우의 개수이다. 또 더하는 경우 그 자리에 그 숫자가 몇번 더해지는지와 자리수가 어디인지를 고려를 해야하는데, 자리수는 reserve를 역순으로 돌려 1의 자리수부터 시작하면 된다. 또한 해당 숫자가 총 더해지는 횟수는 다른 자리수의 숫자들의 개수의 곱과 같다.
def getNumber():
global reserve
# numNum은 가능한 모든 숫자들의 개수
numNum = 1
answer = 0
# 전부다 곱하는걸로 연산 완료.
for rl in reserve:
numNum *= len(rl)
# index는 자리수에 따른 10^(자리수 - 1)임
index = 1
# reserve를 역순으로 계산해서 1의 자리부터 처리함.
for rl in reserve[::-1]:
temp = 0
# 현재 자리수를 제외한 나머지 자리수를 고려한 경우의 수.
curReserveLen = numNum // len(rl)
#곱하고 더함.
for rle in rl:
temp += curReserveLen * int(rle)
# 자리수 보정한 후 answer에 더해줌.
answer += (temp * index)
# 자리수 올려줌.
index *= 10
#전체 합을 전체 개수로 나누어 평균을 구함.
answer = answer / numNum
return answer

성공!