이제 앞서 구현했던 적합 상태로 만드는 코드를 여러번 실행시켜서 최소로 이동하는 경로를 구해보는 것이 목표이다.
코드
import random
# 입력 매트릭스의 각 행의 길이를 맞추는 함수
def normalize_matrix(A, W):
new_A = []
for row in A:
new_row = row + [0] * (W - len(row)) # 부족한 부분을 0으로 채움
new_A.append(new_row)
return new_A
# 컨테이너 배치를 Matrix형태로 바꾸기
def adjust_matrix_and_add_identifiers(A, W, H):
original_H = len(A)
original_W = len(A[0]) if original_H > 0 else 0
if original_H > H or original_W > W:
raise ValueError("Given matrix is larger than specified dimensions.")
adjusted_A = [[{'': 0}] * W for _ in range(H)]
identifier = ord('a')
for i in range(H):
for j in range(W):
if i < original_H and j < original_W and A[i][j] != 0:
adjusted_A[i][j] = {chr(identifier): A[i][j]}
identifier += 1
else:
adjusted_A[i][j] = {chr(identifier): 0}
identifier += 1
return adjusted_A
# 다음 옮길 컨테이너 고르기
def find_moving_container(A, last_moved_container):
containers = []
weights = []
for row in range(len(A)):
# 각 행의 오른쪽에서 왼쪽으로 탐색하여 가장 오른쪽에 있는 0이 아닌 컨테이너를 찾음
for col in reversed(range(len(A[0]))):
value = list(A[row][col].values())[0]
if value != 0:
# 가장 오른쪽에 있는 0이 아닌 컨테이너를 찾았지만, 마지막으로 옮긴 컨테이너가 아니어야 함
if (row, col) != last_moved_container:
containers.append((row, col))
weights.append(value)
break # 가장 오른쪽에 있는 첫 번째 0이 아닌 컨테이너를 찾으면 탐색 중지
# print(containers)
# 가중치 기반으로 선택
if containers:
selected_container = random.choices(containers, weights=weights, k=1)[0]
return selected_container
# 컨테이너를 둘 빈 자리 고르기
def find_valid_empty_slot(A, moving_con_row):
# 빈 자리(0인 위치) 찾기
empty_slots = [(i, j) for i in range(len(A)) for j in range(len(A[0])) if list(A[i][j].values())[0] == 0]
for _ in range(len(empty_slots)):
empty_row, empty_col = random.choice(empty_slots)
# print("empty_row: " + str(empty_row))
# 같은 행이면 불가능
if empty_row == moving_con_row:
continue
# 선택된 빈 자리의 왼쪽이 빈 자리이면 불가능
if empty_col > 0 and list(A[empty_row][empty_col - 1].values())[0] == 0:
continue
# 유효한 빈 자리를 찾으면 반환
return (empty_row, empty_col)
return None # 유효한 빈 자리를 찾지 못함
def is_sorted_descending(row):
values = [list(cell.values())[0] for cell in row]
return all(values[i] >= values[i + 1] for i in range(len(values) - 1))
def move_and_sort(A, W, H):
A = normalize_matrix(A, W) # 매트릭스의 각 행의 길이를 맞춤
A = adjust_matrix_and_add_identifiers(A, W, H)
process_log = [] # 각 상태를 기록할 리스트
process_log.append((A.copy(), 0, "Initial state")) # 초기 상태 기록
move_count = 0
all_sorted = False
last_moved_container = None # 마지막으로 옮긴 컨테이너 위치를 저장할 변수
# 모든 스택이 적합한지 확인
if all(is_sorted_descending(row) for row in A):
all_sorted = True
print("All containers are already suitable.")
else:
while not all_sorted:
# 1 옮길 컨테이너 고르기
moving_con = find_moving_container(A, last_moved_container)
# print(moving_con)
moving_con_row, moving_con_col = moving_con
current_container = list(A[moving_con_row][moving_con_col].items())
if not moving_con:
# print("No valid moving container is found.")
break
# 2 빈자리 선택
empty_slot = find_valid_empty_slot(A, moving_con_row)
if not empty_slot:
# print("No valid empty slot found.")
continue
# 3 빈 자리를 새로 선택했으니 컨테이너를 이동
empty_row, empty_col = empty_slot
# 현재 컨테이너 위치와 빈 자리를 교체
A[empty_row][empty_col], A[moving_con_row][moving_con_col] = A[moving_con_row][moving_con_col], A[empty_row][empty_col]
last_moved_container = (empty_row, empty_col)
move_count += 1
log_message = f"{current_container} to {empty_slot}. Move count: {move_count}"
process_log.append((A.copy(), move_count, log_message)) # 상태와 이동 횟수, 로그 메시지 기록
# 매트릭스 상태 확인
# for row in A:
# print(row)
# print()
# 정렬 상태 확인
if all(is_sorted_descending(row) for row in A):
all_sorted = True
print("########## Final State ##########")
# for row in A:
# print(row)
# print(f"Move count: {move_count}")
# print("All containers are suitable.")
break
return A, move_count, process_log
def run_experiments(num_trials, A, W, H):
results = []
for trial in range(num_trials):
print(f"Trial {trial + 1}:")
result_matrix, move_count, process_log = move_and_sort(A, W, H)
results.append((result_matrix, move_count, process_log))
print(f"Move count: {move_count}\n")
# Move count가 가장 작은 결과 찾기
min_moves = min(results, key=lambda x: x[1])
best_matrix, best_move_count, best_process_log = min_moves
return best_matrix, best_move_count, best_process_log
def main():
A = [
[2, 1],
[2, 3],
[2, 3]
]
W = 4
H = 4
num_trials = 10
try:
best_matrix, best_move_count, best_process_log = run_experiments(num_trials, A, W, H)
print("Best result with the least move count:")
for row in best_matrix:
print(row)
print(f"Minimum Move count: {best_move_count}")
print("\nProcess log of the best result:")
for step, (matrix_state, count, log_message) in enumerate(best_process_log):
print(f"Step {step}: {log_message}")
for row in matrix_state:
print(row)
print()
except ValueError as e:
print(e)
if __name__ == "__main__":
main()
결과
지금은 3by3의 구조라서 휴리스틱 방법으로 5번이 최적인데, 10번의 시도한에 최적 경로를 구하는 것을 볼 수 있다.
Trial 1:
########## Final State ##########
Move count: 6
Trial 2:
########## Final State ##########
Move count: 5
Trial 3:
########## Final State ##########
Move count: 51
Trial 4:
########## Final State ##########
Move count: 10
Trial 5:
########## Final State ##########
Move count: 7
Trial 6:
########## Final State ##########
Move count: 21
Trial 7:
########## Final State ##########
Move count: 20
Trial 8:
########## Final State ##########
Move count: 8
Trial 9:
########## Final State ##########
Move count: 10
Trial 10:
########## Final State ##########
Move count: 12
Best result with the least move count:
[{'a': 2}, {'b': 1}, {'i': 0}]
[{'e': 3}, {'h': 3}, {'f': 0}]
[{'g': 2}, {'d': 2}, {'c': 0}]
Minimum Move count: 5
Process log of the best result:
Step 0: Initial state
[{'a': 2}, {'b': 1}, {'i': 0}]
[{'e': 3}, {'h': 3}, {'f': 0}]
[{'g': 2}, {'d': 2}, {'c': 0}]
Step 1: [('e', 3)] to (2, 2). Move count: 1
[{'a': 2}, {'b': 1}, {'i': 0}]
[{'e': 3}, {'h': 3}, {'f': 0}]
[{'g': 2}, {'d': 2}, {'c': 0}]
Step 2: [('d', 2)] to (0, 2). Move count: 2
[{'a': 2}, {'b': 1}, {'i': 0}]
[{'e': 3}, {'h': 3}, {'f': 0}]
[{'g': 2}, {'d': 2}, {'c': 0}]
Step 3: [('e', 3)] to (1, 0). Move count: 3
[{'a': 2}, {'b': 1}, {'i': 0}]
[{'e': 3}, {'h': 3}, {'f': 0}]
[{'g': 2}, {'d': 2}, {'c': 0}]
Step 4: [('h', 3)] to (1, 1). Move count: 4
[{'a': 2}, {'b': 1}, {'i': 0}]
[{'e': 3}, {'h': 3}, {'f': 0}]
[{'g': 2}, {'d': 2}, {'c': 0}]
Step 5: [('d', 2)] to (2, 1). Move count: 5
[{'a': 2}, {'b': 1}, {'i': 0}]
[{'e': 3}, {'h': 3}, {'f': 0}]
[{'g': 2}, {'d': 2}, {'c': 0}]
728x90
'취업 > 취업 프로그램' 카테고리의 다른 글
공기업 주요 면접 유형 및 단계별 면접 대비 방법 (6) | 2025.05.21 |
---|---|
[2일차] 취업 준비 A to Z 캠프 (4) | 2025.01.15 |
[1일차] 취업 준비 A to Z 캠프 (4) | 2025.01.14 |
기술보증기금 기업분석 (0) | 2024.08.29 |
부경대 기업분석 프로그램 (부산은행/삼성금융그룹) (19) | 2024.06.25 |