Skip to content

Commit 12e4c29

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents e46e795 + 075b059 commit 12e4c29

File tree

21 files changed

+895
-0
lines changed

21 files changed

+895
-0
lines changed

.github/workflows/management.yaml

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
name: Management 🔧
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
action:
7+
description: "Action to perform"
8+
required: true
9+
type: choice
10+
default: "approve-prs"
11+
options:
12+
- approve-prs
13+
- merge-prs
14+
exclude_prs:
15+
description: 'PR numbers to exclude (comma-separated, e.g., "1972,1973")'
16+
required: false
17+
type: string
18+
default: ""
19+
20+
jobs:
21+
approve-prs:
22+
name: Approve Open PRs 👍
23+
runs-on: ubuntu-latest
24+
if: ${{ inputs.action == 'approve-prs' }}
25+
permissions:
26+
contents: read
27+
28+
steps:
29+
- name: Approve PRs via GitHub App
30+
id: approve
31+
run: |
32+
echo "👍 GitHub App을 통해 모든 Open PR 승인 중..."
33+
34+
# Parse exclude_prs input into JSON array
35+
exclude_input="${{ inputs.exclude_prs }}"
36+
if [ -z "$exclude_input" ]; then
37+
excludes="[]"
38+
else
39+
# Convert "1972,1973" to [1972,1973]
40+
excludes="[$(echo "$exclude_input" | sed 's/,/, /g')]"
41+
fi
42+
43+
echo "제외할 PR: $excludes"
44+
45+
response=$(curl -s -X POST "https://github.dalestudy.com/approve-prs" \
46+
-H "Content-Type: application/json" \
47+
-d "{\"repo_name\": \"${{ github.event.repository.name }}\", \"excludes\": $excludes}")
48+
49+
echo "response=$response" >> $GITHUB_OUTPUT
50+
echo "$response" | jq '.'
51+
52+
- name: Summary
53+
run: |
54+
response='${{ steps.approve.outputs.response }}'
55+
56+
success=$(echo "$response" | jq -r '.success // false')
57+
total=$(echo "$response" | jq -r '.total_open_prs // 0')
58+
processed=$(echo "$response" | jq -r '.processed // 0')
59+
approved=$(echo "$response" | jq -r '.approved // 0')
60+
skipped=$(echo "$response" | jq -r '.skipped // 0')
61+
62+
echo "## 👍 PR 승인 완료" >> $GITHUB_STEP_SUMMARY
63+
echo "" >> $GITHUB_STEP_SUMMARY
64+
65+
if [ "$success" = "true" ]; then
66+
echo "✅ **성공적으로 완료되었습니다**" >> $GITHUB_STEP_SUMMARY
67+
else
68+
echo "❌ **오류가 발생했습니다**" >> $GITHUB_STEP_SUMMARY
69+
fi
70+
71+
echo "" >> $GITHUB_STEP_SUMMARY
72+
echo "- 📋 전체 Open PR: **$total**개" >> $GITHUB_STEP_SUMMARY
73+
echo "- 🔍 검사한 PR: **$processed**개" >> $GITHUB_STEP_SUMMARY
74+
echo "- ✅ 승인한 PR: **$approved**개" >> $GITHUB_STEP_SUMMARY
75+
echo "- ⏭️ 건너뛴 PR: **$skipped**개" >> $GITHUB_STEP_SUMMARY
76+
77+
# Show detailed results if available
78+
results=$(echo "$response" | jq -r '.results // []')
79+
if [ "$results" != "[]" ]; then
80+
echo "" >> $GITHUB_STEP_SUMMARY
81+
echo "### 📝 상세 결과" >> $GITHUB_STEP_SUMMARY
82+
echo "" >> $GITHUB_STEP_SUMMARY
83+
echo "$response" | jq -r '.results[] | "- PR #\(.pr_number): \(.status) \(if .reason then "(\(.reason))" else "" end)"' >> $GITHUB_STEP_SUMMARY
84+
fi
85+
86+
merge-prs:
87+
name: Merge Open PRs 🚀
88+
runs-on: ubuntu-latest
89+
if: ${{ inputs.action == 'merge-prs' }}
90+
permissions:
91+
contents: read
92+
93+
steps:
94+
- name: Merge PRs via GitHub App
95+
id: merge
96+
run: |
97+
echo "🚀 GitHub App을 통해 모든 승인된 PR 머지 중..."
98+
99+
# Parse exclude_prs input into JSON array
100+
exclude_input="${{ inputs.exclude_prs }}"
101+
if [ -z "$exclude_input" ]; then
102+
excludes="[]"
103+
else
104+
# Convert "1972,1973" to [1972,1973]
105+
excludes="[$(echo "$exclude_input" | sed 's/,/, /g')]"
106+
fi
107+
108+
merge_method="merge"
109+
echo "머지 방식: $merge_method"
110+
echo "제외할 PR: $excludes"
111+
112+
response=$(curl -s -X POST "https://github.dalestudy.com/merge-prs" \
113+
-H "Content-Type: application/json" \
114+
-d "{\"repo_name\": \"${{ github.event.repository.name }}\", \"merge_method\": \"$merge_method\", \"excludes\": $excludes}")
115+
116+
echo "response=$response" >> $GITHUB_OUTPUT
117+
echo "$response" | jq '.'
118+
119+
- name: Summary
120+
run: |
121+
response='${{ steps.merge.outputs.response }}'
122+
123+
success=$(echo "$response" | jq -r '.success // false')
124+
total=$(echo "$response" | jq -r '.total_open_prs // 0')
125+
processed=$(echo "$response" | jq -r '.processed // 0')
126+
merged=$(echo "$response" | jq -r '.merged // 0')
127+
skipped=$(echo "$response" | jq -r '.skipped // 0')
128+
merge_method=$(echo "$response" | jq -r '.merge_method // "unknown"')
129+
130+
echo "## 🚀 PR 머지 완료" >> $GITHUB_STEP_SUMMARY
131+
echo "" >> $GITHUB_STEP_SUMMARY
132+
133+
if [ "$success" = "true" ]; then
134+
echo "✅ **성공적으로 완료되었습니다**" >> $GITHUB_STEP_SUMMARY
135+
else
136+
echo "❌ **오류가 발생했습니다**" >> $GITHUB_STEP_SUMMARY
137+
fi
138+
139+
echo "" >> $GITHUB_STEP_SUMMARY
140+
echo "- 🔧 머지 방식: **$merge_method**" >> $GITHUB_STEP_SUMMARY
141+
echo "- 📋 전체 Open PR: **$total**개" >> $GITHUB_STEP_SUMMARY
142+
echo "- 🔍 검사한 PR: **$processed**개" >> $GITHUB_STEP_SUMMARY
143+
echo "- ✅ 머지한 PR: **$merged**개" >> $GITHUB_STEP_SUMMARY
144+
echo "- ⏭️ 건너뛴 PR: **$skipped**개" >> $GITHUB_STEP_SUMMARY
145+
146+
# Show detailed results if available
147+
results=$(echo "$response" | jq -r '.results // []')
148+
if [ "$results" != "[]" ]; then
149+
echo "" >> $GITHUB_STEP_SUMMARY
150+
echo "### 📝 상세 결과" >> $GITHUB_STEP_SUMMARY
151+
echo "" >> $GITHUB_STEP_SUMMARY
152+
echo "$response" | jq -r '.results[] | "- PR #\(.pr_number): \(.status) \(if .reason then "(\(.reason))" else "" end)"' >> $GITHUB_STEP_SUMMARY
153+
fi

.github/workflows/weekcheck.yaml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Week Check 🗓️
2+
3+
on:
4+
schedule:
5+
# 매일 오전 10시, 오후 6시 (KST 기준, UTC로는 1시, 9시)
6+
- cron: "0 1,9 * * *"
7+
workflow_dispatch:
8+
9+
jobs:
10+
check-weeks:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
15+
steps:
16+
- name: Check all PRs via GitHub App
17+
id: check
18+
run: |
19+
echo "🔍 GitHub App을 통해 모든 Open PR 검사 중..."
20+
21+
response=$(curl -s -X POST "https://github.dalestudy.com/check-weeks" \
22+
-H "Content-Type: application/json" \
23+
-d "{\"repo_owner\": \"${{ github.repository_owner }}\", \"repo_name\": \"${{ github.event.repository.name }}\"}")
24+
25+
echo "response=$response" >> $GITHUB_OUTPUT
26+
echo "$response" | jq '.'
27+
28+
- name: Summary
29+
run: |
30+
response='${{ steps.check.outputs.response }}'
31+
32+
total=$(echo "$response" | jq -r '.total_prs // 0')
33+
checked=$(echo "$response" | jq -r '.checked // 0')
34+
commented=$(echo "$response" | jq -r '.commented // 0')
35+
deleted=$(echo "$response" | jq -r '.deleted // 0')
36+
37+
echo "## 🎯 Week 설정 체크 완료" >> $GITHUB_STEP_SUMMARY
38+
echo "" >> $GITHUB_STEP_SUMMARY
39+
echo "- 📋 전체 Open PR: **$total**개" >> $GITHUB_STEP_SUMMARY
40+
echo "- ✅ 검사한 PR: **$checked**개" >> $GITHUB_STEP_SUMMARY
41+
echo "- 💬 댓글 작성한 PR: **$commented**개" >> $GITHUB_STEP_SUMMARY
42+
echo "- 🗑️ 댓글 삭제한 PR: **$deleted**개" >> $GITHUB_STEP_SUMMARY
43+
echo "" >> $GITHUB_STEP_SUMMARY
44+
echo "다음 체크: $(date -u -d '+1 hour' +'%Y-%m-%d %H:00 UTC')" >> $GITHUB_STEP_SUMMARY

alien-dictionary/hu6r1s.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from typing import (
2+
List,
3+
)
4+
5+
import heapq
6+
heap = [c for c in indegree if indegree[c] == 0]
7+
heapq.heapify(heap)
8+
res = []
9+
10+
11+
class Solution:
12+
"""
13+
@param words: a list of words
14+
@return: a string which is correct order
15+
"""
16+
def alien_order(self, words: List[str]) -> str:
17+
# Write your code here
18+
adj = {c: set() for word in words for c in word}
19+
indegree = {c: 0 for c in adj}
20+
21+
for i in range(len(words) - 1):
22+
w1, w2 = words[i], words[i+1]
23+
minlen = min(len(w1), len(w2))
24+
if len(w1) > len(w2) and w1[:minlen] == w2[:minlen]:
25+
return ""
26+
for j in range(minlen):
27+
if w1[j] != w2[j]:
28+
if w2[j] not in adj[w1[j]]:
29+
adj[w1[j]].add(w2[j])
30+
indegree[w2[j]] += 1
31+
break
32+
33+
while heap:
34+
c = heapq.heappop(heap)
35+
res.append(c)
36+
for nei in adj[c]:
37+
indegree[nei] -= 1
38+
if indegree[nei] == 0:
39+
heapq.heappush(heap, nei)
40+
41+
if len(res) != len(adj):
42+
return ""
43+
44+
return "".join(res)

alien-dictionary/hyer0705.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
export class Solution {
2+
alienOrder(words: string[]): string {
3+
const indegree = new Map<string, number>();
4+
const graph = new Map<string, Set<string>>();
5+
6+
for (const word of words) {
7+
for (const ch of word) {
8+
if (graph.has(ch)) continue;
9+
graph.set(ch, new Set<string>());
10+
indegree.set(ch, 0);
11+
}
12+
}
13+
14+
for (let i = 0; i < words.length - 1; i++) {
15+
const word1 = words[i];
16+
const word2 = words[i + 1];
17+
18+
let pointer = 0;
19+
while (pointer < word1.length && pointer < word2.length && word1[pointer] === word2[pointer]) {
20+
pointer++;
21+
}
22+
23+
if (pointer < word1.length && pointer === word2.length) {
24+
return "";
25+
}
26+
27+
if (pointer < word1.length && pointer < word2.length) {
28+
const neighbors = graph.get(word1[pointer])!;
29+
if (!neighbors.has(word2[pointer])) {
30+
neighbors.add(word2[pointer]);
31+
indegree.set(word2[pointer], (indegree.get(word2[pointer]) || 0) + 1);
32+
}
33+
}
34+
}
35+
36+
const queue: string[] = [];
37+
const result: string[] = [];
38+
39+
for (const [ch, degree] of indegree) {
40+
if (degree === 0) {
41+
queue.push(ch);
42+
}
43+
}
44+
45+
while (queue.length > 0) {
46+
const current = queue.shift()!;
47+
result.push(current);
48+
49+
for (const neighbor of graph.get(current) || []) {
50+
indegree.set(neighbor, (indegree.get(neighbor) || 0) - 1);
51+
if (indegree.get(neighbor) === 0) {
52+
queue.push(neighbor);
53+
}
54+
}
55+
}
56+
57+
if (indegree.size === result.length) {
58+
return result.join("");
59+
}
60+
61+
return "";
62+
}
63+
}

alien-dictionary/yhkee0404.kt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
class Solution {
2+
/**
3+
* @param words: a list of words
4+
* @return: a string which is correct order
5+
*/
6+
fun alienOrder(words: Array<String>): String {
7+
// Write your code here
8+
val adj = List<MutableList<Int>>('z'.code - 'a'.code + 1) {mutableListOf()}
9+
for (i in 1 until words.size) {
10+
var j = 0
11+
while (j != words[i - 1].length && j != words[i].length && words[i - 1][j] == words[i][j]) {
12+
j++
13+
}
14+
if (j == words[i - 1].length) {
15+
continue
16+
}
17+
if (j == words[i].length) {
18+
return ""
19+
}
20+
adj[words[i - 1][j].code - 'a'.code].add(words[i][j].code - 'a'.code)
21+
}
22+
val visited = MutableList(adj.size) {false}
23+
words.forEach {
24+
it.map { it.code - 'a'.code }
25+
.forEach { visited[it] = true }
26+
}
27+
val inDegrees = MutableList(adj.size) {0} // Kahn T(V, E) = S(V, E) = O(V + E)
28+
adj.forEach {
29+
it.forEach { inDegrees[it]++ }
30+
}
31+
val ans = mutableListOf<Int>()
32+
val stack = mutableListOf<Int>()
33+
(0 until adj.size).filter { visited[it] && inDegrees[it] == 0 }
34+
.forEach {
35+
stack.add(it)
36+
ans.add(it)
37+
}
38+
while (! stack.isEmpty()) {
39+
val u = stack.removeLast()
40+
adj[u].forEach {
41+
if (--inDegrees[it] == 0) {
42+
stack.add(it)
43+
ans.add(it)
44+
}
45+
}
46+
}
47+
if ((0 until adj.size).any { visited[it] && inDegrees[it] != 0 }) {
48+
return ""
49+
}
50+
return ans.map { (it + 'a'.code).toChar() }
51+
.joinToString("")
52+
/*val decoder = MutableList(adj.size) {0}
53+
(0 until ans.size).forEach { decoder[ans[it]] = it }
54+
val decoded = words.map {
55+
it.map { (decoder[it.code - 'a'.code] + 'a'.code).toChar() }
56+
.joinToString("")
57+
}
58+
val sortedWords = decoded.sorted()
59+
return if (decoded == sortedWords) ans.map { (it + 'a'.code).toChar() }
60+
.joinToString("")
61+
else ""*/
62+
}
63+
}

0 commit comments

Comments
 (0)