diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b881eff --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.analysis.autoImportCompletions": true +} \ No newline at end of file diff --git a/python/cap5/work1.py b/python/cap5/work1.py new file mode 100644 index 0000000..f8d4832 --- /dev/null +++ b/python/cap5/work1.py @@ -0,0 +1 @@ +# 检验一个给定表达式中的括号是否正确匹配 diff --git a/python/cap5/work2.py b/python/cap5/work2.py new file mode 100644 index 0000000..4d43a46 --- /dev/null +++ b/python/cap5/work2.py @@ -0,0 +1,66 @@ +from fractions import Fraction + +# 第五章 作业一 +# 有分数1/2,1/3,1/4,1/5,1/6,1/8,1/10,1/12,1/15,求将其中若干个分数相加和恰好等于1的组成方案,并输出 +# +# 1. 给定的分数使用 Fraction 类型,可以方便地进行分数的计算和比较。 +# +# 2. 使用递归来查找满足条件的组合。参数: +# - `target`:目标和,初始值为 1。 +# - `current_combination`:当前已选择的分数组合,初始为空列表。 +# - `index`:当前处理的分数在列表中的索引,初始为 0。 +# +# 3. 在递归函数中,有两个选择: +# - 不选择当前分数:继续递归,不修改 `target` 和 `current_combination`。 +# - 选择当前分数:继续递归,更新 `target` 为 `target - fractions[index]`,并将当前分数添加到 `current_combination` 中。 +# +# 4. 当 `target` 等于 0 时,我们找到了一个满足条件的组合,将其打印出来。 +# +# 5. 递归继续处理下一个分数,直到遍历完所有分数或找到所有满足条件的组合。 + + +def find_combinations( + target: Fraction, + fractions: list[Fraction], + current_combination: list[Fraction], + index: int, + resultSet: list[list[Fraction]], +): + if target == 0: + resultSet.append(current_combination.copy()) + return + if index >= len(fractions): + return + + # 不选择当前分数 + find_combinations(target, fractions, current_combination, index + 1, resultSet) + # 选择当前分数 + find_combinations( + target - fractions[index], + fractions, + current_combination + [fractions[index]], + index + 1, + resultSet, + ) + + +fractions = [ + Fraction(1, 2), + Fraction(1, 3), + Fraction(1, 4), + Fraction(1, 5), + Fraction(1, 6), + Fraction(1, 8), + Fraction(1, 10), + Fraction(1, 12), + Fraction(1, 15), +] + +result_set = [] + +find_combinations( + target=1, fractions=fractions, current_combination=[], index=0, resultSet=result_set +) + +for result in result_set: + print(" + ".join(map(str, result)) + " = 1") diff --git a/python/cap5/work3.py b/python/cap5/work3.py new file mode 100644 index 0000000..4a4a033 --- /dev/null +++ b/python/cap5/work3.py @@ -0,0 +1,36 @@ +# 第五章 作业3 +# 找出所有由1~9组成的9位数,每个数字只能出现一次,且这个9位数由高位到低位前i位能被i整除 +# +# 1. 使用深度优先搜索(DFS)来查找满足条件的 9 位数。 +# +# 2. 定义一个 `dfs` 函数,两个参数: +# - `k`:当前已选择的数字个数,初始值为 0。 +# - `num`:当前已选择的数字组成的整数,初始值为 0。 +# +# 3. 在 `dfs` 函数中,遍历数字 1 到 9。对于每个数字,检查是否已经使用过(通过 `used` 数组判断)。如果没有使用过,我们尝试将该数字添加到当前的数字组合中。 +# +# 4. 检查当前数字组合是否满足条件:前 i 位能被 i 整除。如果满足条件,我们继续递归调用 `dfs`,更新 `k` 和 `num`。 +# +# 5. 当 `k` 等于 9 时,找到了一个满足条件的 9 位数。 + + +def find(k: int, num: int, used: list[bool], resultSet: list[int]): + if k != 0 and num % k != 0: + return + + if k == 9: + resultSet.append(num) + return + + # digit: 1 ~ 9 + for digit in range(1, 10): + if not used[digit]: + used[digit] = True + find(k + 1, num * 10 + digit, used, resultSet) + # 当前数字撤销使用标记,以便下一个数字的搜索时可用 + used[digit] = False + + +resultSet = [] +find(0, 0, [False] * 10, resultSet) +print(resultSet) diff --git a/python/cap5/work4.py b/python/cap5/work4.py new file mode 100644 index 0000000..e69de29 diff --git a/python/cap5/work5.py b/python/cap5/work5.py new file mode 100644 index 0000000..4729089 --- /dev/null +++ b/python/cap5/work5.py @@ -0,0 +1,7 @@ +# 翻币问题:有N个硬币(N≥10),正面向上排成一排。每次必须翻5个硬币,直到全部反面向上。 + +def flip_coins(num: int): + pass + +result = flip_coins(21) +print(result) diff --git a/python/cap5/work6.py b/python/cap5/work6.py new file mode 100644 index 0000000..1cd19c7 --- /dev/null +++ b/python/cap5/work6.py @@ -0,0 +1,75 @@ +# 等分液体 +# 在一个瓶子中装有8(一般情形下为偶数N)升汽油,要平均分成两份, +# 但只有一个装3(一般情形下为N/2-1)升和装5(一般情形下为N/2+1)升的量杯(都没有刻度)。 +# 若有解,则打印出所有把汽油分成两等分的操作过程。若无解,则打印“No”。 + +from collections import deque + + +def pour(source, target, target_capacity): + amount = min(source, target_capacity - target) + return source - amount, target + amount + + +def get_next_states(state, capacities): + next_states = [] + bottle, cup3, cup5 = state + max_bottle, max_cup3, max_cup5 = capacities + + # bottle -> cup3 + next_states.append(pour(bottle, cup3, max_cup3) + (cup5,)) + # bottle -> cup5 + next_states.append(pour(bottle, cup5, max_cup5) + (cup3,)) + # cup3 -> bottle + next_states.append( + (pour(cup3, bottle, max_bottle)[1],) + pour(cup3, bottle, max_bottle) + ) + # cup5 -> bottle + next_states.append( + (pour(cup5, bottle, max_bottle)[1], cup3, pour(cup5, bottle, max_bottle)[0]) + ) + # cup3 -> cup5 + next_states.append((bottle,) + pour(cup3, cup5, max_cup5)) + # cup5 -> cup3 + next_states.append((bottle,) + pour(cup5, cup3, max_cup3)[::-1]) + + return next_states + + +def bfs(initial_state, capacities, target): + queue = deque([(initial_state, [])]) + visited = set() + + while queue: + (state, path) = queue.popleft() + + if (state[0] == target and state[1] == target) or ( + state[0] == target and state[2] == target + ): + return path + + if state in visited: + continue + + visited.add(state) + + for next_state in get_next_states(state, capacities): + if next_state not in visited: + queue.append((next_state, path + [next_state])) + + return "No" + + +N = 8 +capacities = (N, N // 2 - 1, N // 2 + 1) +initial_state = (N, 0, 0) +target = N // 2 + +result = bfs(initial_state, capacities, target) + +if result == "No": + print("No") +else: + print("状态步骤:(汽油瓶, 5L杯, 3L杯)") + for step in result: + print(step) diff --git a/python/cap5/work7.py b/python/cap5/work7.py new file mode 100644 index 0000000..b30c1a2 --- /dev/null +++ b/python/cap5/work7.py @@ -0,0 +1,46 @@ +# 一个正整数有可能可以被表示为n(n≥2)个连续的正整数之和,如n=15时, +# 15=1+2+3+4+5 +# 15=4+5+6 +# 15=7+8 +# 请编写算法,根据输入的任何一个正整数,找出符合这种要求的所有连续正整数序列。 + +# 需要找到所有可能的连续正整数序列,这些序列的和等于给定的正整数 N 。 +# 考虑到一个连续的正整数序列 a, a+1, a+2, ..., a+(k-1) ,和可以表示为: +# +# S = a + (a + 1) + (a + 2) + ... + (a + k - 1) +# +# 简化为: +# +# S = k * a + (k*(k - 1)) / 2 +# +# S 是给定的正整数 N,a 是序列的起始数,k 是序列中的项数。 +# +# 所以有: +# +# N = k * a + (k*(k - 1)) / 2 +# +# 即: +# +# 2N = k * (2a + k - 1) +# +# 为了找到所有满足条件的序列,从 2 开始遍历可能的 k 值,直到 k*(k-1) < 2N为止,检查是否有整数 a 使得上面的等式成立。 + + +def find_consecutive_sequences(N): + result = [] + + k = 2 + while k * (k - 1) < 2 * N: + if (2 * N - k * (k - 1)) % (2 * k) == 0: + a = (2 * N - k * (k - 1)) // (2 * k) + sequence = [a + i for i in range(k)] + result.append(sequence) + k += 1 + + return result + + +N = 15 +sequences = find_consecutive_sequences(N) +for seq in sequences: + print(seq)