728x90
반응형
각 종 알고리즘 개념들을 따로 따로 보다보니 한 번에 보고 싶어 한 파일에 모아 봤다. 다음엔 개념 알고리즘만 모아서 항목 별로 작성 해볼 수 있는 것을 만들어 봐야겠다.
항목은 아래와 같다.
- 소수
- 최대공약수, 최소공배수
- 기하
- 자릿수의 합
- 정렬
- 탐색
- 최단 경로
- 그래프
"""
소수
- 소수 판별
- 에라토스테네스의 체
"""
import random
def is_prime(n):
for i in range(2, int(n**0.5) + 1):
if n % 2 == 0:
return False
return True
for i in range(2, 20):
if is_prime(i):
print(i, end=" ")
print()
def erathosthenes(n):
factor = [True] * (n + 1)
factor[0] = factor[1] = False
for i in range(2, int(n**0.5) + 1):
if factor[i]:
for j in range(i * 2, n + 1, i):
factor[j] = False
return factor
print(erathosthenes(20))
"""
최대공약수
- 유클리드 호제법
"""
def gcd(a, b):
while b > 1:
a, b = b, a % b
return a
print(gcd(123, 12))
"""
최소공배수
- 유클리드 호제법을 이용한 최소공배수
"""
def lcm(a, b):
return a * b // gcd(a, b)
print(lcm(123, 12))
"""
기하
- 직사각형에서 타일의 개수
- 두 원의 관계
- 벌집
"""
def sum_of_three_bar(a, b, c):
if a + b > c:
c = a + b - 1
return a + b + c
ret = sum_of_three_bar(1, 2, 5)
print(ret)
def turret(coord):
x1, y1, r1, x2, y2, r2 = coord
dist = (abs(x2 - x1) ** 2 + abs(y2 - y1) ** 2) ** 0.5
diff = abs(r1 - r2)
s = r1 + r2
# 원이 같을 때
if dist == diff == 0:
return -1
# 원이 외접하거나 내접할 때
if dist == s or dist == diff:
return 1
# 원이 두 점에서 만날 때
if diff < dist < s:
return 2
return 0
print(turret([1, 1, 1, 1, 1, 5]))
def house_of_bee(m):
a = n = 1
if m == 1:
return 1
while a < m:
a += 6 * (n - 1)
n += 1
return n - 1
print(house_of_bee(8))
"""
자릿수의 합
- 셀프 넘버
- 특정 수의 개수
- 각 자리수의 개수
"""
def sum_of_digits(n):
return sum(list(map(int, [s for s in str(n)])))
def self_number(n):
arr = [True] * (n + 1)
for i in range(1, n + 1):
idx = i + sum_of_digits(i)
if idx < n + 1:
arr[idx] = False
return arr
arr = self_number(20)
for i, v in enumerate(arr):
if v:
print(i)
def surprise_n(n):
answer = 0
for i in range(1, n + 1):
if i % sum_of_digits(i) == 0:
answer += 1
return answer
print(surprise_n(1000))
def count_digit(a, b, c):
n = a * b * c
arr = [0] * 10
ds = [s for s in str(n)]
for d in ds:
arr[int(d)] += 1
return arr
for i in count_digit(150, 266, 427):
print(i)
"""
정렬
- 버블 정렬
- 삽입 정렬
- 버킷 정렬
- 퀵 정렬
- 병합 정렬
"""
def bubble_sort(arr):
l = len(arr)
for i in range(l - 1):
for j in range(l - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
arr = random.sample(range(1, 11), 10)
print(bubble_sort(arr))
def insertion_sort(arr):
for i in range(1, len(arr)):
for j in range(i, 0, -1):
if arr[j] < arr[j - 1]:
arr[j], arr[j - 1] = arr[j - 1], arr[j]
else:
break
return arr
arr = random.sample(range(1, 11), 10)
print(insertion_sort(arr))
def bucket_sort(arr):
bucket = [0] * (max(arr) + 1)
for i in arr:
bucket[i] += 1
result = []
for i in range(len(bucket)):
if bucket[i] != 0:
result.extend([i] * bucket[i])
return result
arr = random.sample(range(1, 11), 10)
print(bucket_sort(arr))
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [i for i in arr if i < pivot]
right = [i for i in arr if i > pivot]
middle = [i for i in arr if i == pivot]
return quick_sort(left) + middle + quick_sort(right)
arr = random.sample(range(1, 11), 10)
print(quick_sort(arr))
def merge_sort(arr):
def merge(left, right):
result = []
l = r = 0
while l < len(left) and r < len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
if l < len(left):
result.extend(left[l:])
if r < len(right):
result.extend(right[r:])
return result
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
arr = random.sample(range(1, 11), 10)
print(merge_sort(arr))
"""
탐색
- 이진 탐색
- 깊이 우선 탐색
- 너비 우선 탐색
"""
def binary_search(arr, target):
start, end = 0, len(arr) - 1
while start <= end:
mid = (start + end) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
start = mid + 1
else:
end = mid - 1
return None
def binary_search_recursive(arr, target, start, end):
if start > end:
return None
mid = (start + end) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
return binary_search_recursive(arr, target, mid + 1, end)
else:
return binary_search_recursive(arr, target, start, mid - 1)
arr = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
print(binary_search(arr, 7))
print(binary_search_recursive(arr, 7, 0, len(arr) - 1))
graph = {
"A": ["B", "C"],
"B": ["A", "D"],
"C": ["A", "G", "H", "I"],
"D": ["B", "E", "F"],
"E": ["D"],
"F": ["D"],
"G": ["C"],
"H": ["C"],
"I": ["C", "J"],
"J": ["I"],
}
def dfs(graph, start):
visited = []
stack = [start]
while stack:
node = stack.pop()
if node not in visited:
visited.append(node)
stack.extend(graph[node])
return visited
print(dfs(graph, "A"))
graph = {
"A": ["B", "C"],
"B": ["A", "D"],
"C": ["A", "G", "H", "I"],
"D": ["B", "E", "F"],
"E": ["D"],
"F": ["D"],
"G": ["C"],
"H": ["C"],
"I": ["C", "J"],
"J": ["I"],
}
def bfs(graph, start):
visited = []
queue = [start]
while queue:
node = queue.pop(0)
if node not in visited:
visited.append(node)
queue.extend(graph[node])
return visited
print(bfs(graph, "A"))
import heapq
"""
최단 경로
- 다익스트라 알고리즘
- 플로이드 워셜 알고리즘
"""
graph = {
"A": {"B": 8, "C": 1, "D": 2},
"B": {},
"C": {"B": 5, "D": 2},
"D": {"E": 3, "F": 5},
"E": {"F": 1},
"F": {"A": 5},
}
def dijkstra(graph, start):
distances = {node: float("inf") for node in graph}
distances[start] = 0
queue = []
heapq.heappush(queue, [distances[start], start])
while queue:
current_distance, current_node = heapq.heappop(queue)
if distances[current_node] < current_distance:
continue
for adjacent, weight in graph[current_node].items():
distance = current_distance + weight
if distance < distances[adjacent]:
distances[adjacent] = distance
heapq.heappush(queue, [distance, adjacent])
return distances
print(dijkstra(graph, "A"))
n = 6
# this input is floyd_warshall algorithm's graph input
dist = [
[0, 1, 2],
[2, 5, 1],
[3, 2, 4],
[4, 1, 3],
[2, 3, 1],
[1, 5, 3],
[4, 2, 2],
[3, 4, 5],
]
graph = [[float("inf")] * (n + 1) for _ in range(n + 1)]
for i in range(n + 1):
graph[i][i] = 0
for d in dist:
a, b, c = d
graph[a][b] = c
graph[b][a] = c
def floyd_warshall(graph):
for k in range(1, n + 1):
for i in range(1, n + 1):
for j in range(1, n + 1):
graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])
return graph
print(floyd_warshall(graph))
"""
그래프
- 서로소 집합
- 크루스칼 알고리즘
- 위상 정렬
"""
def find(parent, x):
if parent[x] != x:
parent[x] = find(parent, parent[x])
return parent[x]
def union(parent, a, b):
a = find(parent, a)
b = find(parent, b)
if a < b:
parent[b] = a
else:
parent[a] = b
graph = [
(1, 7, 12),
(1, 4, 28),
(1, 2, 67),
(1, 5, 17),
(2, 4, 24),
(2, 5, 62),
(3, 5, 20),
(3, 6, 37),
(4, 7, 13),
(5, 6, 45),
(5, 7, 73),
]
def kruskal(v, graph):
parent = [0] * (v + 1)
edges = []
result = 0
for i in range(1, v + 1):
parent[i] = i
for edge in graph:
a, b, cost = edge
edges.append((cost, a, b))
edges.sort()
for edge in edges:
cost, a, b = edge
if find(parent, a) != find(parent, b):
union(parent, a, b)
result += cost
return result
print(kruskal(7, graph))
graph = {
1: [2, 5],
2: [3, 4],
3: [4, 6],
4: [6, 7],
5: [6],
6: [7],
}
from heapdict import heapdict
def prim(graph, start):
mst, keys, pi, total_weight = [], heapdict(), {}, 0
# 초기화
for node in graph.keys():
keys[node] = float("inf")
pi[node] = None
keys[start], pi[start] = 0, start
while keys:
current_node, current_key = keys.popitem()
mst.append([pi[current_node], current_node, current_key])
total_weight += current_key
for adjacent, weight in graph[current_node].items():
if adjacent in keys and weight < keys[adjacent]:
keys[adjacent] = weight
pi[adjacent] = current_node
return mst, total_weight
graph = {
"A": {"B": 7, "D": 5},
"B": {"A": 7, "D": 9, "C": 8, "E": 7},
"C": {"B": 8, "E": 5},
"D": {"A": 5, "B": 9, "E": 7, "F": 6},
"E": {"B": 7, "C": 5, "D": 7, "F": 8, "G": 9},
"F": {"D": 6, "E": 8, "G": 11},
"G": {"E": 9, "F": 11},
}
mst, total_weight = prim(graph, "A")
print("MST:", mst)
print("Total Weight:", total_weight)
from collections import deque
def topology_sort(graph, indegree):
result = []
q = deque()
for i in range(1, n + 1):
if indegree[i] == 0:
q.append(i)
while q:
now = q.popleft()
result.append(now)
for i in graph[now]:
indegree[i] -= 1
if indegree[i] == 0:
q.append(i)
return result
n = 7
indegree = [0] * (n + 1)
graph = [[] for _ in range(n + 1)]
graph[1].append(2)
indegree[2] += 1
graph[1].append(5)
indegree[5] += 1
graph[2].append(3)
indegree[3] += 1
graph[3].append(4)
indegree[4] += 1
graph[4].append(6)
indegree[6] += 1
graph[5].append(6)
indegree[6] += 1
graph[6].append(7)
indegree[7] += 1
print(topology_sort(graph, indegree))
728x90
반응형
'Algorithm > Python' 카테고리의 다른 글
[자료구조] 파이썬 링크드 리스트 (0) | 2020.12.04 |
---|---|
[1697] 숨바꼭질 (0) | 2020.11.08 |