Kullanıcı tarafından belirtilen sayıları kullanarak geçerli bir denklem oluşturma


10

Bu matematik öğretmenlerimin ortaokulda oynadığı bir oyuna dayanıyor. Tahtaya 5 rastgele tek haneli sayı ve ardından rastgele iki haneli bir sayı yazacaktı. İki basamaklı sayıyı vermek için tek basamaklı sayıların 5'inin tümünü kullanan bir denklem oluşturmaya çalışırdık. İşte bunu daha iyi açıklamak için çözümler içeren bazı örnekler:

Input:           Solution:
7 5 4 8 4 34     5*8-7+4/4 = 34
3 1 5 7 6 54     (7+3)*6-5-1 = 54
3 9 2 1 6 87     9*(2+1)*3+6 = 87
2 1 6 9 7 16     (9-7+6*1)*2 = 16
2 4 5 8 6 96     8*(5+6)+2*4 = 96
3 8 4 5 4 49     8*(4+4)-3*5 = 49

Bu zorluk, belirli bir girdi için bu tür denklemleri oluşturabilen bir program yazmaktır. Giriş, komut satırı veya bir komut istemi ile sağlanabilir. 5 tek basamaklı sayı her zaman önce (belirli bir sırada değil), ardından iki basamaklı sayı girilir. Program daha sonra bulduğu bir çözüm denklemini yazdıracaktır; çözüm bulunmayan durumlarla başa çıkmak zorunda değilsiniz. İşlev, denklemde şu işlemleri kullanabilmelidir: toplama, çıkarma, çarpma ve bölme. Ek temel işlemlere izin vermek istiyorsanız, meydan okuma ruhu içinde kaldıkları sürece bu iyidir (olumsuzlama, üs alma ve modül güzel eklemeler olacaktır). İşlem sırası standart matematik kurallarına uyar, bu nedenle gruplama için parantez gerekecektir.

Programlar kod uzunluğuna göre (gerekli boşluk dahil) puanlanacaktır. Not: bölme tam olmalı, yuvarlatılmamalı veya en yakın tam sayıya kesilmemelidir.



Bu çok benzer bir görev, ancak bence ek terim ve ifadelerin nasıl gruplandırıldığına dair herhangi bir kısıtlama, sorunu ilginç bir şekilde farklılaştıracak kadar genişletmelidir. Buna ek olarak, bu farklı çözümler gerektirecek bir kod meydan okuma yerine bir golf meydan okuma.
Sir_Lagsalot

Birleştirme ne olacak? örneğin 7 5 4 8 4 34 verilirse, çıkış 7 + 54/8 * 4 mü verilir?
Patrick Roberts

Yanıtlar:


7

Python 2.7 (284), Python 3.x (253)

from __future__ import division #(Remove for Python 3.x)
from itertools import *
a=raw_input().split()
for i in permutations(a[:-1],5):
 for j in product('+-*/',repeat=5):
  for k,l in combinations(range(1,12,2),2):
   d=''.join(sum(zip(i,j),()))[:-1];d='('+d[:l]+')'+d[l:]
   if eval(d)==int(a[-1]):print d;b

bÇözüm üzerinde bir hata (bilinmeyen işlev çağırma ) verir.

Temel olarak, devasa bir kaba kuvvet. Girdiyi alır, boşluklarıyla böler ( 1 2 -> [1,2]) ve sonra bu listeye izin verir. Her permütasyonda, karakterleri kullanarak 5 uzunluktaki tüm olası dizeleri tekrarlar +-*/. Bu iterasyonların her biri ile, listenin 2 uzunluğunun kombinasyonlarını üretecek [1,3,5,7,9,11], permütasyon ve dizeyi birbirine ( 12345 *-/+- -> 1*2-3/4+5-) birleştirecek ve parantez içine alacaktır . Son olarak, değerlendirir ve cevap ve denklem doğruysa, denklemi yazdırır ve durur.

Bu korkunç derecede verimsizdir, O(n!/(n-5)!)=O(n^5)ancak test girişleri için makul bir sürede çalışır.


1
Tamsayı matematiği bölme kullanılırken yanlış çıktıya neden olabilir. Örneğin, "3 6 8 7 1 29" girdisi "(3 + 8/6) * 7 + 1" 'i verir, bu da 29 değil 31 1/3' e eşittir.
Sir_Lagsalot

(3/6)*8*7+1Bana verir .
beary605

Tamam, kullandığım tercümanla ilgili bir konu olarak tebeşirleyeceğim.
Sir_Lagsalot

3

Scala 368:

2. g = -Line test etmek daha kolaydır, birincisi komut argümanlarını almak için esnektir ve her ikisi de eşit uzunluktadır, bu yüzden sadece ikincisinden sayıyorum - geçen argümanları kaldırmak için kaldırın:

val g=(args.map(_.toDouble))
val g=Array(3,9,2, 1, 6, 87)
val k="+*/-DQ"
val i=(0 to 5)
val f:Seq[(Double,Double)=>Double]=Seq(_+_,_*_,_/_,_-_,(a,b)=>b-a,(a,b)=>b/a)
val h=g.init.permutations;
for(j<-h;o<-i;p<-i;q<-i;r<-i;z=try{f(r)(f(q)(f(p)(f(o)(j(0),j(1)),j(2)),j(3)),j(4))}catch{case _ => 0}
if(z==g(5)))printf("(((%d%c%d)%c%d)%c%d)%c%d=%d\n",j(0),k(o),j(1),k(p),j(2),k(q),j(3),k(r),j(4),g(5))

Örnek çıktı (şu anda bir sorunuz olabilir - sadece bir dakika):

(((5+7)/1)+6)*3=54
(((5-7)D1)*6)*3=54
(((5D7)+1)*6)*3=54
(((5+7)+6)Q1)Q3=54

Bu 5D7 olayına ne dersiniz? D1? Onaltılık mı? S1, S3 var - bu nedir.

Sir_Lagsalot meydan okuma ruhunda yeni temel operasyonlara izin verdi ve evet, bunlar temel operasyonlar, Delta ve Bölüm.

AQb'nin b / a anlamına geldiği ve aDb'nin ba anlamına geldiği için a / b ve ab'den farklıdırlar. Buna Ukrayna notasyonu diyelim.

Yani

(((5-7)D1)*6)*3=54

anlamına geliyor

((1-(5-7))*6)*3=54
 (1-(-2))*6*3
   3*6*3 = 18*3=54

Nasıl ve nedeninin daha ilginç sorusuna: Başlangıçta parantez yerleştirme olasılıkları ve (a + b) -c = a + bc = (a + bc) = ((a + b) ) -c) = (b + a) -c vb. Bu soruya kızabilirsiniz, ancak olası parantez kombinasyonlarını yazarsanız, bazen not sayfasını atar ve gerçekle yüzleşirsiniz: Her zaman 5 değer arasında 4 işlem yaparsınız ve her zaman bunlardan biriyle başlarsınız. Desen her zaman (((_x_)x_)x_)x_ ?= _(x 4 operatörden biriyse) ve zıt yöne (xb) ve (bxa) izin veriyorsa, her olasılığı ele alıyorsunuz demektir.

Şimdi a + b ve a * b için zıt yönlere ihtiyacımız yok, değişmeli. Bu yüzden sadece yön değiştiren D ve Q operatörünü icat ettim. Artık 2 operatöre sahibim, ancak yön değiştirmem gerekmiyor. Peki - Dizi fonksiyonunda yapılır:

 (a,b)=>b-a,(a,b)=>b/a

Benim kavrayışım değerleri Array g'den alır ve a ile e arasında dağıtır, daha sonra işlevi seçmek için 4 dizin seçerim ve daha sonra ilişkili işleç sembolünü seçerim. Ben örnek girdi veri 0 içermezken çıkarma sıfırlar yol açabilir, çünkü div / 0 hataları yakalamak zorunda.


Delta ve Bölüm operatörleri iyidir. Yine de golf yapmayı planlıyorsanız, çıktıya parantez eklemeniz gerekir.
Sir_Lagsalot

Çıktı artık parantez yazdırıyor.
kullanıcı bilinmiyor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.