2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

逆ポーランド法を用いた10パズル

Last updated at Posted at 2024-06-06

逆ポーランド法を用いた10パズル

逆ポーランド記法を用いた計算

  • 数字がスタックに積まれ、演算子が出てくるとスタックのトップ2つの数字を取り出し計算する
  • ゼロ除算を避けるため、分母がゼロの場合は大きな数(1e5)をスタックに積む
calc.py
def calc(re_polish_lists):
    stack = []
    for i in range(7):
        if re_polish_lists[i] < 10:
            stack.append(re_polish_lists[i])
        else:
            v1 = stack.pop(-1)
            v2 = stack.pop(-1)
            if re_polish_lists[i] == ADD:
                stack.append(v2 + v1)
            elif re_polish_lists[i] == SUB:
                stack.append(v2 - v1)
            elif re_polish_lists[i] == MUL:
                stack.append(v2 * v1)
            elif re_polish_lists[i] == DIV:
                if v1 != 0:
                    stack.append(v2 / v1)
                else:
                    stack.append(1e5)
    return stack.pop(-1)

演算パターン

演算子と数字の並び方は5パターン
演算子 = o
数字 = d
とすると

[d, d, d, d, o, o, o]
[d, d, d, o, d, o, o]
[d, d, d, o, o, d, o]
[d, d, o, d, d, o, o]
[d, d, o, d, o, d, o]

許容範囲内のチェック

is_within_tolerance.py
def is_within_tolerance(target, result, threshold):
    if math.fabs(target - result) < threshold: return True  
    return  False

10になる組み合わせかチェック

is10.py
def is10(l, ops):
    arrays = [
        [l[0], l[1], l[2], l[3], ops[0], ops[1], ops[2]],
        [l[0], l[1], l[2], ops[0], l[3], ops[1], ops[2]],
        [l[0], l[1], l[2], ops[0], ops[1], l[3], ops[2]],
        [l[0], l[1], ops[0], l[2], l[3], ops[1], ops[2]],
        [l[0], l[1], ops[0], l[2], ops[1], l[3], ops[2]]
    ]
    for array in arrays:
        if is_within_tolerance(10.0, calc(array), 1.0e-7):
            print_fomula(array)
            return True  
    return False

メイン部分

  • permutations_list : 数字4つの順列
  • operators : [ADD, SUB, MUL, DIV]

最初の for 文3つで演算子3種類を取り出し、4つ目の for 文で
permutations_list から数字の演算パターンを取り出す。

main.py
print("四つの数字を入力してください")
a, b, c, d = map(int, input().split())

isBeing_10 = False
permutations_list = list(itertools.permutations([a, b, c, d], 4))
for opr1 in operators:
    for opr2 in operators:
        for opr3 in operators: 
            opr_list = [opr1, opr2, opr3]
            for list_for_calc in permutations_list:
                isBeing_10 = is10(list_for_calc, opr_list)
                if isBeing_10:
                    break
            if isBeing_10:
                break
        if isBeing_10:
            break
    if isBeing_10:
        break
if not isBeing_10:
    print("\n10になりません\n")

まとめ

make10.py
import math
import itertools
ADD = 101
SUB = 102
MUL = 103
DIV = 104
operators = [ADD, SUB, MUL, DIV]

def calc(re_polish_lists):
    stack = []
    for i in range(7):
        if re_polish_lists[i] < 10:
            stack.append(re_polish_lists[i])
        else:
            v1 = stack.pop(-1)
            v2 = stack.pop(-1)
            if re_polish_lists[i] == ADD:
                stack.append(v2 + v1)
            elif re_polish_lists[i] == SUB:
                stack.append(v2 - v1)
            elif re_polish_lists[i] == MUL:
                stack.append(v2 * v1)
            elif re_polish_lists[i] == DIV:
                if v1 != 0:
                    stack.append(v2 / v1)
                else:
                    stack.append(1e5)
    return stack.pop(-1)

def is_within_tolerance(target, result, threshold):
    if math.fabs(target - result) < threshold: return True  
    return  False

def print_fomula(array):
    print("\n逆ポーランド法表示")
    for i in range(7):
        if array[i] == 101:
            print("+", end = " ")
        elif array[i] == 102:
            print("-", end = " ")
        elif array[i] == 103:
            print("*", end = " ")
        elif array[i] == 104:
            print("/", end = " ")
        else:
            print(array[i], end = " ")
    print("\n")
        
def is10(l,ops):
    arrays = [
        [l[0],l[1],l[2],l[3],ops[0],ops[1],ops[2]],
        [l[0],l[1],l[2],ops[0],l[3],ops[1],ops[2]],
        [l[0],l[1],l[2],ops[0],ops[1],l[3],ops[2]],
        [l[0],l[1],ops[0],l[2],l[3],ops[1],ops[2]],
        [l[0],l[1],ops[0],l[2],ops[1],l[3],ops[2]]
    ]
    for array in arrays:
        if is_within_tolerance(10.0, calc(array), 1.0e-7):
            print_fomula(array)
            return True  
    return False

print("四つの数字を入力してください")
a, b, c, d = map(int,input().split())

isBeing_10 = False
permutations_list = list(itertools.permutations([a, b, c, d], 4))
for opr1 in operators:
    for opr2 in operators:
        for opr3 in operators: 
            opr_list = [opr1, opr2, opr3]
            for list_for_calc in permutations_list:
                isBeing_10 = is10(list_for_calc, opr_list)
                if isBeing_10:
                    break
            if isBeing_10:
                break
        if isBeing_10:
            break
    if isBeing_10:
        break
if not isBeing_10:
    print("\n10になりません\n")

実行結果

$ python3 make10.py
四つの数字を入力してください
3 4 7 8

逆ポーランド法表示
3 7 4 / - 8 * 

解けないパターン

四つの数字を入力してください
7 7 8 9

10になりません

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?