5 sayı 4 işlem Problemi

3,5,7,11,13 sayılarını toplama, çıkarma, çarpma ve bölme işlemlerinin herbirini ve istediğimiz kadar parantez kullanarak 64 sonucunu elde ediniz.

sorunum şu parantezler işi karıştıryor
Eğer dört işlem kullan deseydi sadece sonucu bu şekilde bulurdum,sizce ne yapılabilir yardımcı olurmusunuz?
Altda yerdeğiştirme dikkate alınmamıştır

from itertools import permutations
işlemler='+-*/'
permutasyonlar=permutations(işlemler,4)
for i in permutasyonlar:
    sonuç='3{}5{}7{}11{}13'.format(i[0],i[1],i[2],i[3])
    if eval(sonuç)==64:
        print(sonuç)

Buda bir işlemin birden fazla kullanıldığı durum bunu zaten istemiyor bizden ve
Burada yerdeğiştirme dikkate alınmadı

from itertools import product
işlemler='+-*/'
permutasyonlar=product(işlemler,repeat=4)
for i in permutasyonlar:
    sonuç='3{}5{}7{}11{}13'.format(i[0],i[1],i[2],i[3])
    if eval(sonuç)==64:
        print(sonuç)

En baştaki sayının önüne - gelebiliyor mu?

Hayır işaretler arada kalmalı

Parantezler için bir algoritma düşünmemiz lazım.

evet haklısınız ama ben daha belirleyemedim :frowning:

Sayıların sıralaması önemli mi?

Evet onu atlamışım sıra önemli değil yer değişebilir

Algoritmasını kurdum şuan kodu yazıyorum.

1 Beğeni

Bu infix (4 * (2 + 3)) ifadelerle ilgili bir sorun; prefix (* 4 + 2 3) veya postfix (2 3 + 4 *) ifadeler kullandigimizda bu sorun ortadan kalkiyor.

Daha once expression tree yaratmak gerektigini soylemistim; bu tur sorularin genel cozumu bu.

(Uc ifade de ayni islem agacini temsil ediyor.)

1 Beğeni

şöyle bir şey yapmayı denedim
tek parantez için sonuç veriyor

from itertools import  permutations
a=[3,5,7,11,13,'(',')','+','*']
istenenler=permutations(a,9)
liste=[]
for i in istenenler:
    boş=''
    for j in i:
        boş+=str(j)
    liste.append(boş)
sonuçlar=[]
for i in liste:
    try:
        sonuçlar.append(eval(i))
    except :
        pass
print(sonuçlar)

ama sorun şu ki

<string>:1: SyntaxWarning: 'int' object is not callable; perhaps you missed a comma?
bu yazıda ekrana geliyor 
 işlem sayısı artıkça zaman uzuyor 
birde ekrana gelen yazının sebebi nedir?

dediğiniz şekilde yapılırsa parantez kullanımına gerek kalmaz
nasıl o yazım şeklini yapabiliriz?

Bu sorum burada yetim kalmış :slight_smile:
Neden böyle bir durum oluşmuştur?

Bana hic bir sey katmadiklari ve gercek dunyada kullanim alanlari olmadigi icin eval'li cozumleri okumuyorum.

eval edilen string’lerin birinde sentaks hatasi oldugu icin olusmustur.

1 Beğeni

Merhabalar,

Aşağıdaki algoritmayı inceleyin lütfen, mümkün olan parantez koşullarını oluşturuyor.

Burada önce hedef sayılarla ve operatörlerle bir kartezyen çarpım yapılır.

Daha sonra bu çarpımdan ürettiğimiz her bir ürün için, bracket_combinations fonksiyonu ile, mümkün parantez grupları iç içe listeler kullanılarak oluşturulur.

Sonra da oluşan her bir ifadeye operatörler SyntaxError vermeyecek şekilde yerleştirilir. Ama belli ifadeler ZeroDivisionError hatası verebilir.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


def product(*iterables):
    if not iterables:
        yield []
        return
    for i in iterables[0]:
        for p in product(*iterables[1:]):
            yield [i, *p]


def find_numbers(s):
    return list(map(int, "".join(map(lambda i: i if i.isnumeric() else " ", s)).split()))


def find_chars(s):
    return list(filter(lambda i: not i.isnumeric(), s))


def unique_append(result, item):
    if item not in result:
        result.append(item)


def bracket_combinations(numbers):
    def side_brackets(result, select, left, mid, right):
        unique_append(result, [left, mid, *right] if select == left else [*left, mid, right])
        for bracket in brackets(select):
            if select == left:
                unique_append(result, [bracket, mid, *right])
                unique_append(result, [*bracket, mid, *right])
            else:
                unique_append(result, [*left, mid, bracket])
                unique_append(result, [*left, mid, *bracket])

    def brackets(n):
        step = 2
        result = [n]
        while step < len(n):
            for i in range(len(n) - 1):
                left = n[:i]
                mid = n[i: i + step]
                right = n[i + step:]
                unique_append(result, [*left, mid, *right])
                if len(left) >= 2:
                    side_brackets(result, left, left, mid, right)
                if len(right) >= 2:
                    side_brackets(result, right, left, mid, right)
                for bracket in brackets(mid):
                    unique_append(result, [*left, bracket, *right])
            step += 1
        return result
    return brackets(numbers)


def insert_operators(group, chars):
    expr = ""
    for i in range(len(group)):
        if isinstance(group[i], list):
            expr += "(" + insert_operators(group[i], chars) + ")"
            try:
                if expr[-1] != group[i + 1]:
                    expr += next(chars)
            except IndexError:
                pass
        else:
            expr += str(group[i])
            if i != len(group) - 1:
                try:
                    expr += next(chars)
                except StopIteration:
                    pass
    return expr


def get_products(ops, numbers):
    products = []
    for i in range(len(numbers)):
        if i == len(numbers) - 1:
            products += [[numbers[i]]]
        else:
            products += [[numbers[i]]] + [ops]
    return products


def find_expression(ops, numbers, target):
    for p in product(*get_products(ops, numbers)):
        stmt = "".join(map(str, p))
        chars = find_chars(stmt)
        for bracket_comb in bracket_combinations(find_numbers(stmt)):
            expr = insert_operators(bracket_comb, iter(chars))
            try:
                res = eval(expr)
                if res == target:
                    return expr, res
            except ZeroDivisionError:
                pass


def main():
    ops = "+-*/"
    numbers = [3, 5, 7, 11, 13]
    targets = [64, 32, 16, 125]
    for target in targets:
        expr = find_expression(ops, numbers, target)
        print(expr)


main()

Değişik toplamlar için ifadeler otomatik olarak üretilir.

('(3-5*7)*(11-13)', 64)
('(3+5)*7-(11+13)', 32)
('3+(5+7-11)*13', 16)
('3*(5*7+11)-13', 125)

Algoritmanın dayandığı mantığı aşağıdaki açılımda gördüğüm örüntü yoluyla oluşturuyorum. İzninizle, dört sayıya kadar olan parantez olasılıklarını açayım:

"""
i: sayıları temsil eden değişken
?: operatörleri temsil eden değişken

i ? i:
    1. i ? i
    
i ? i ? i:
    1. i ? i ? i
    2. (i ? i) ? i
    3. i ? (i ? i)
    
i ? i ? i ? i:
    1. i ? i ? i ? i
    2. (i ? i) ? i ? i
    3. i ? (i ? i) ? i
    4. i ? i ? (i ? i)
    5. (i ? i) ? (i ? i)
    6. (i ? i ? i) ? i
    7. ((i ? i) ? i) ? i
    8. (i ? (i ? i)) ? i
    9. i ? (i ? i ? i)
    10. i ? ((i ? i) ? i)  
    11. i ? (i ? (i ? i))  
"""

Yukardaki parantezleri bracket_combinations fonksiyonuyla oluşturabiliriz:

c = 0
nums = [3, 5, 7, 11, 13]
for bracket_comb in bracket_combinations(nums):
    c += 1
    print(c, bracket_comb)

Çıktı:

1 [3, 5, 7, 11, 13]
2 [[3, 5], 7, 11, 13]
3 [[3, 5], [7, 11, 13]]
4 [[3, 5], [[7, 11], 13]]
5 [[3, 5], [7, 11], 13]
6 [[3, 5], [7, [11, 13]]]
7 [[3, 5], 7, [11, 13]]
8 [3, [5, 7], 11, 13]
9 [3, [5, 7], [11, 13]]
10 [3, 5, [7, 11], 13]
11 [3, 5, 7, [11, 13]]
12 [[3, 5, 7], [11, 13]]
13 [[[3, 5], 7], [11, 13]]
14 [[3, [5, 7]], [11, 13]]
15 [[3, 5, 7], 11, 13]
16 [[[3, 5], 7], 11, 13]
17 [[3, [5, 7]], 11, 13]
18 [3, [5, 7, 11], 13]
19 [3, [[5, 7], 11], 13]
20 [3, [5, [7, 11]], 13]
21 [3, 5, [7, 11, 13]]
22 [3, 5, [[7, 11], 13]]
23 [3, 5, [7, [11, 13]]]
24 [[3, 5, 7, 11], 13]
25 [[[3, 5], 7, 11], 13]
26 [[[3, 5], [7, 11]], 13]
27 [[3, [5, 7], 11], 13]
28 [[3, 5, [7, 11]], 13]
29 [[[3, 5, 7], 11], 13]
30 [[[[3, 5], 7], 11], 13]
31 [[[3, [5, 7]], 11], 13]
32 [[3, [5, 7, 11]], 13]
33 [[3, [[5, 7], 11]], 13]
34 [[3, [5, [7, 11]]], 13]
35 [3, [5, 7, 11, 13]]
36 [3, [[5, 7], 11, 13]]
37 [3, [[5, 7], [11, 13]]]
38 [3, [5, [7, 11], 13]]
39 [3, [5, 7, [11, 13]]]
40 [3, [[5, 7, 11], 13]]
41 [3, [[[5, 7], 11], 13]]
42 [3, [[5, [7, 11]], 13]]
43 [3, [5, [7, 11, 13]]]
44 [3, [5, [[7, 11], 13]]]
45 [3, [5, [7, [11, 13]]]]

Yukardaki listeler insert_operators fonksiyonuyla paranteze dönüştürülür ve ilgili yerlere operatörler eklenir.

c = 0
nums = [3, 5, 7, 11, 13]
for bracket_comb in bracket_combinations(nums):
    c += 1
    print(c, insert_operators(bracket_comb, iter("+-*/")))

Çıktı

1 3+5-7*11/13
2 (3+5)-7*11/13
3 (3+5)-(7*11/13)
4 (3+5)-((7*11)/13)
5 (3+5)-(7*11)/13
6 (3+5)-(7*(11/13))
7 (3+5)-7*(11/13)
8 3+(5-7)*11/13
9 3+(5-7)*(11/13)
10 3+5-(7*11)/13
11 3+5-7*(11/13)
12 (3+5-7)*(11/13)
13 ((3+5)-7)*(11/13)
14 (3+(5-7))*(11/13)
15 (3+5-7)*11/13
16 ((3+5)-7)*11/13
17 (3+(5-7))*11/13
18 3+(5-7*11)/13
19 3+((5-7)*11)/13
20 3+(5-(7*11))/13
21 3+5-(7*11/13)
22 3+5-((7*11)/13)
23 3+5-(7*(11/13))
24 (3+5-7*11)/13
25 ((3+5)-7*11)/13
26 ((3+5)-(7*11))/13
27 (3+(5-7)*11)/13
28 (3+5-(7*11))/13
29 ((3+5-7)*11)/13
30 (((3+5)-7)*11)/13
31 ((3+(5-7))*11)/13
32 (3+(5-7*11))/13
33 (3+((5-7)*11))/13
34 (3+(5-(7*11)))/13
35 3+(5-7*11/13)
36 3+((5-7)*11/13)
37 3+((5-7)*(11/13))
38 3+(5-(7*11)/13)
39 3+(5-7*(11/13))
40 3+((5-7*11)/13)
41 3+(((5-7)*11)/13)
42 3+((5-(7*11))/13)
43 3+(5-(7*11/13))
44 3+(5-((7*11)/13))
45 3+(5-(7*(11/13)))
1 Beğeni

Yazdim sonunda expression tree generator’i:

from dataclasses import dataclass
import operator

@dataclass
class Node:
	value: str
	children: ['Node']

def get_exptrees(bag):
	def _get_subtrees(bag, holes):
		leaves, ops = bag

		if len(leaves) < holes:
			return

		for i in range(len(leaves)):
			leaf = leaves[i]
			rem_leaves = leaves[:i] + leaves[i+1:]
			yield (Node(leaf, []), (rem_leaves, ops))

		for i in range(len(ops)):
			op = ops[i]
			rem_ops = ops[:]

			for left in _get_subtrees((leaves, rem_ops), holes+1):
				left_st, rem_bag = left
				for right in _get_subtrees(rem_bag, holes):
					right_st, rem_bag = right
					yield (Node(op, [left_st, right_st]), rem_bag)

	for tree, rem in _get_subtrees(bag, 0):
		yield tree

def eval_exptree(tree):
	if len(tree.children) > 0:
		return tree.value(*map(eval_exptree, tree.children))
	else:
		return tree.value

def print_infix(labels, t):
	if len(t.children) > 0:
		return f"({print_infix(labels, t.children[0])} {labels[t.value]} {print_infix(labels, t.children[1])})"
	else:
		return t.value

bag = ([3, 5, 7, 11, 13], [operator.add, operator.sub, operator.mul, operator.truediv])
labels = { ol[0]: ol[1] for ol in zip(bag[1], "+-*/") }
solutions = 0
for t in get_exptrees(bag):
	try:
		val = eval_exptree(t)
	except:
		continue

	if val == 64:
		solutions += 1
		print(solutions, print_infix(labels, t), "=", eval(print_infix(labels, t)))

Hole mantigi biraz aceleye geldi. Gerekecegini onceden tahmin etseydim belki ugrasmazdim bile; recursion’i komplike bir hale getiriyor. (Arkada sonsuz delik birakip (? + (? + (? + (? + (? + ... dipsiz kuyusuna inmesini engelliyor.) Daha guzel cozumlere acigim.

left/right’i da n-arity operatorlere genelleyecektim de, delik meselesiyle ugrasmaktan vaktim kalmadi.

Simetriler dahil 582 cozum buluyor. Simetrileri ayiklamak gerekse nasil yapilir bilemedim.
Birkac ornek:

1 (3 + (7 + ((5 * 13) - 11))) = 64
2 (3 + (7 + ((13 * 5) - 11))) = 64
3 (3 + (13 + ((5 * 11) - 7))) = 64
4 (3 + (13 + ((11 * 5) - 7))) = 64
5 (3 + ((7 - 11) + (5 * 13))) = 64
6 (3 + ((7 - 11) + (13 * 5))) = 64
7 (3 + ((13 - 7) + (5 * 11))) = 64
8 (3 + ((13 - 7) + (11 * 5))) = 64
9 (3 + (((5 * 11) - 7) + 13)) = 64
10 (3 + (((5 * 13) - 11) + 7)) = 64
573 ((11 - 7) * (13 + 3)) = 64
574 ((11 - 13) * (3 - (5 * 7))) = 64
575 ((11 - 13) * (3 - (7 * 5))) = 64
576 ((13 - 5) * (11 - 3)) = 64
577 ((13 - 11) * ((5 * 7) - 3)) = 64
578 ((13 - 11) * ((7 * 5) - 3)) = 64
579 ((13 - (7 / 3)) * (11 - 5)) = 64.0
580 (((5 * 7) - 3) * (13 - 11)) = 64
581 (((7 * 5) - 3) * (13 - 11)) = 64
582 (((7 / 3) - 13) * (5 - 11)) = 64.0
3 Beğeni