Minimum kibrit çubukları ile matematik yapın


15

Meta-arkaplan

Bu, Şaşırtıcı bir soru olarak belirlendi ve anında tepki "iyi, birisi bunu bilgisayarla çözecekti" idi. Bunu çözmek için bir programın ne kadar karmaşık olması gerektiği konusunda bir tartışma vardı. Peki, "bu program ne kadar karmaşık olmalı" hemen hemen tanımı , bu yüzden belki PPCG sorunu çözebilir?

Arka fon

Bir kibrit çöpü denklemi temel olarak normal bir matematiksel denklemdir, ancak basamaklar ve operatörler fiziksel olarak bir masaya kibrit çubukları yerleştirilerek oluşturulur. (Buradaki kibrit çubuklarının temel ilgili özelliği, oldukça katı ve sabit bir uzunluğa sahip olmalarıdır; bazen insanlar pamuklu çubuklar gibi başka nesneleri kullanırlar.)

Bu meydan okuma için, kibrit çöplerinin nasıl düzenlendiğine ilişkin belirli kurallar tanımlamamız gerekmez (bağlantılı meydan okumada olduğu gibi); bunun yerine, belirli bir sayıya göre değerlendirilen bir ifadeyi temsil etmek için kaç tane kibrit çöpüne ihtiyacımız olacağını umuyoruz.

Görev

İşte her biri kibrit çöpünde bir maliyeti olan bir rakam ve matematiksel operatörler alfabesi:

  • 0, 6 kibrit çöpü maliyeti
  • 1, 2 kibrit çöpü maliyeti
  • 2, 5 kibrit çöpü maliyeti
  • 3, 5 kibrit çöpü maliyeti
  • 4, 4 kibrit çöpü maliyeti
  • 5, 5 kibrit çöpü maliyeti
  • 6, 6 kibrit çöpü maliyeti
  • 7, 3 kibrit çöpü maliyeti
  • 8, 7 kibrit çöpü maliyeti
  • 9, 6 kibrit çöpü maliyeti
  • +, 2 kibrit çöpü maliyeti
  • -, maliyet 1 kibrit çöpü
  • ×, 2 kibrit çöpü maliyeti

(İsterseniz, ASCII olmayan karakterleri kullanmaktan kaçınmak için programınızın çıktısında ×olduğu gibi temsil edebilirsiniz *. Çoğu kodlamada, ×daha fazla bayt alır *ve bu nedenle çoğu programın bu kaldıraçtan yararlanmak isteyeceğini düşünürüm .)

Negatif olmayan bir tamsayıyı girdi olarak (herhangi bir makul yolla ) alan ve bu tamsayıyı çıktı olarak değerlendiren bir ifade üreten (yine herhangi bir makul yolla) bir program yazmanız gerekir . Buna ek olarak, ekspresyon aşikar olmayan olmalıdır: en az bir operatör içermelidir +, -ya da ×. Son olarak, çıktınızdaki ifade, spesifikasyona uymayan tüm çıktılar arasında toplam kibrit çöpü maliyeti açısından en ucuz (veya en ucuza bağlı) olmalıdır.

Açıklamalar

  • Bir satırda birden çok basamak çıkararak çok basamaklı sayılar oluşturabilirsiniz (örneğin 11-1, üretmek için geçerli bir çıktıdır 10). Tam olarak kesin olmak gerekirse, elde edilen sayı ondalık olarak yorumlanır. Bu tür bir birleştirme, ara sonuçlar üzerinde çalışan bir işlem değildir; yalnızca orijinal ifadede görünen gerçek rakamlarda.
  • Bu meydan okuma amacıyla. +,, -ve ×infix operatörleridir; solları ve sağları için bir tartışmaya ihtiyaçları var. Bunları önek konumunda +5veya gibi kullanamazsınız -8.
  • Paranteziniz (veya önceliği kontrol etmek için başka bir yolunuz) yok. İfade, tipik varsayılan öncelik kurallarına göre değerlendirilir (önce çarpımlar olur ve ardından toplama ve çıkarma soldan sağa değerlendirilir).
  • Yukarıda listelenenler dışında herhangi bir matematik operatörüne veya sabitine erişiminiz yoktur; "yanal düşünme" çözümleri genellikle Puzzling'de kabul edilir, ancak bir bilgisayarın kendileriyle gelmesini gerektirmek mantıklı değildir ve burada PPCG'de, bir çözümün doğru olup olmadığı objektif olmayı seviyoruz.
  • Her zamanki tamsayı taşma kuralları geçerlidir: çözümünüz, tüm tamsayıların varsayılan olarak sınırsız olduğu dilinizin varsayımsal (veya belki de gerçek) bir sürümünde keyfi olarak büyük tamsayılar için çalışabilmelidir, ancak programınız uygulama nedeniyle uygulamada başarısız olursa bu kadar büyük tam sayıları desteklememek, çözümü geçersiz kılmaz.
  • Aynı rakamı veya operatörü bir kereden fazla kullanırsanız, kibrit çöpü maliyetini her kullandığınızda ödemeniz gerekir (çünkü açıkçası, aynı fiziksel kibrit çöplerini masada iki farklı yerde yeniden kullanamazsınız).
  • Zaman sınırı yoktur; kaba kuvvet çözümleri kabul edilebilir. (Kaba kuvvetten daha hızlı bir çözümünüz varsa, daha uzun olsa bile yayınlamaktan çekinmeyin; alternatif yaklaşımların nasıl karşılaştırıldığını görmek her zaman ilginçtir.)
  • Kodunuzun açıklanması asla gerekli olmasa da, muhtemelen iyi bir fikir olacaktır; çözümlerinin okunması genellikle çok zordur (özellikle yazıldıkları dile aşina olmayan kişiler için) ve nasıl çalıştığını anlamadığınız sürece bir çözümü değerlendirmek (ve dolayısıyla oy vermek) zor olabilir.

Zafer koşulu

Bir zorluğu olarak, daha az bayt ile yanıtlar daha iyi kabul edilir. Bununla birlikte, her zamanki gibi, diğer yaklaşımlardan daha ayrıntılı olsalar bile, farklı yaklaşımlarla veya belirli dillerde yanıtlar yayınlamaktan çekinmeyin; golfün amacı gerçekten belirli bir programı ne kadar optimize edebileceğinizi görmek ve bu şekilde bir şeyler yapmak bize optimize etmek için birçok potansiyel program sunuyor. Bu yüzden, biri tamamen farklı bir yaklaşım veya tamamen farklı bir dil kullanarak bir çözüm sunar ve çok daha kısa bir cevap alırsa cesaretiniz kırılmamalıdır; cevabınızın daha iyi optimize edilmiş olması ve daha fazla beceri göstermesi iyi olabilir ve PPCG'deki seçmenler genellikle bunu takdir eder.


Tanrım, ele almamız gereken en yüksek sayı nedir? Şu anki girişimim TIO'da ... belki 20'nin ötesine geçmeyecekti.
Sihirli Ahtapot Urn

@ carusocomputing: Teoride keyfi olarak yüksek , ancak pratikte makul bir süre içinde 20'den fazla alamazsanız, bu tamamen kabul edilebilir.

4
Test durumunuz var mı?
Luke

Bunun tek bir operasyon olmasını ve çoklu yarışmalara yayılmasını diliyorum. Çarpma bölen bir sorundur, ancak toplama ve çıkarma eklemek işleri gerçekten zorlaştırır. Çalışan bir çözümüm var ama toplama ve çıkarma için değil; mükemmel çalışmasını sağlamak sıkıcı olacaktır.
Sihirli Ahtapot Urn

@carusocomputing: O zaman bu meydan okumayla ilgileniyor olabilirsiniz . Çarpma ile mücadelenin sadece önemli ölçüde farklı olduğundan ve iyi bir puan almak için oldukça farklı çözüm teknikleri gerektirdiğinden şüpheleniyorum.

Yanıtlar:


1

Python2, 1̶9̶8̶ ̶b̶y̶t̶e̶s̶ 182 bayt teşekkürler math_junkie sayesinde

def f(n,c=dict(zip('0123456789+-*',map(int,'6255456376212'))),e=[(0,'')]):
 while 1:
    v=(m,s)=min(e);e.remove(v)
    try:
     if eval(s)==n:return s
    except:0
    e+=[(m+c[x],s+x)for x in c]

Bu algoritma +ve önek sürümlerini hariç tutmak için hiçbir şey yapmaz -, ancak onların infix muadillerinden daha kötü, ya da daha sonra aramada görüneceklerdir. Anahtar kelime bağımsız değişkenini emutabl olarak kullandığından, oturum başına birden çok kez çağrılırsa geçersiz sonuçlar verir. Bunu düzeltmek için f(n, e=[(0,'')])sadece yerine kullanın f(n). Dört aralıklı girintilerin sekmeleri temsil ettiğine dikkat edin, bu yalnızca Python 2 ile çalışacaktır.

Ayrıca oldukça büyük sayılar için bile hızlı çalışan ungolfed ve optimize edilmiş bir versiyonum var:

from heapq import heappop, heappush

def f(n):
    digits = list('0123456789')
    ops =['+','-','*','']
    costs = dict(zip(digits + ops, [6,2,5,5,4,5,6,3,7,6,2,1,2,0]))
    expressions = [(costs[d], abs(n - int(d)), int(d), d) for d in digits[1:]]
    seen = set()
    while 1:
        cost, d, k, expression = heappop(expressions)
        if d == 0:
            return expression
        for op in ops:
            if op in '+-' and k in seen:
                continue
            for digit in digits:
                if op and digit == '0':
                    continue
                expression1 = expression + op + digit
                k1 = eval(expression1)
                d1 = abs(n - k1)
                if d1 == 0:
                    return expression1
                heappush(expressions, (cost+costs[op]+costs[digit], d1, k1, expression1))
        seen.add(k)

Bazı küçük golfler önerdi: TIO (182 bytes)
matematik bağımlısı

1

PHP, 241 Bayt

Çevrimiçi sürüm

function m($i){for(;$s<strlen($i);)$e+="6255456376"[$i[$s++]];return$e;}foreach($r=range(0,2*$a=$argv[1])as$v)foreach($r as$w)$x[$v+$w]["$v+$w"]=$x[$v*$w]["$v*$w"]=1+$x[$v-$w]["$v-$w"]=m("$v")+m("$w")+1;echo array_search(min($x[$a]),$x[$a]);

Yıkmak

function m($i){
    for(;$s<strlen($i);)$e+="6255456376"[$i[$s++]];return$e; #return the count of the matchstick for an integer
}

foreach($r=range(0,2*$a=$argv[1])as$v) # limit to an input to 300 in the online version
foreach($r as$w)
       $x[$v+$w]["$v+$w"]=  #fill the 2D array in the form [result][expression] = count matchsticks
       $x[$v*$w]["$v*$w"]=
       1+$x[$v-$w]["$v-$w"]=
       m("$v")+m("$w")+1;
echo $k=array_search(min($x[$a]),$x[$a]); # Output expression with a minium of matchsticks
echo"\t".$x[$a][$k]; #optional Output of the count of the matchsticks

Biraz daha iyi performansla yol

function m($i){
for(;$s<strlen($i);)
$e+="6255456376"[$i[$s++]];return$e;} #return the count of the matchstick for an integer
foreach($r=range(0,2*$a=$argv[1])as$v)
foreach($r as$w){$c=m("$v")+m("$w")+1;
if($a==$v+$w)$x["$v+$w"]=1+$c; # fill array if value equal input
if($a==$v*$w)$x["$v*$w"]=1+$c;
if($a==$v-$w)$x["$v-$w"]=$c;}
echo $k=array_search(min($x),$x); # Output expression with a minium of matchsticks
    echo"\t".$x[$k]; #optional Output of the count of the matchsticks

Negatif tamsayıların desteklenmesi

Negatif tamsayılara sahip sürüm

function m($i){
    $e=$i<0?1:0; # raise count for negative integers
    for($s=0;$s<strlen($i);)$e+=[6,2,5,5,4,5,6,3,7,6][$i[$s++]];return$e; #return the count of the matchstick for an integer
}
$q=sqrt(abs($argv[1]));
$l=max(177,$q);
$j=range(-$l,$l); # for second loop for better performance
foreach($r=range(min(0,($a=$argv[1])-177),177+$a)as$v) 
foreach($j as$w){$c=m("$v")+m("$w")+1;  
    if($a==$v+$w)$x["$v+$w"]=1+$c; # fill array if value equal input
    if($a==$v*$w)$x["$v*$w"]=1+$c;
    if($a==$v-$w)$x["$v-$w"]=$c;
    if($a==$w-$v)$x["$w-$v"]=$c; # added for integers <0
}
echo $k=array_search(min($x),$x); # Output expression with a minium of matchsticks
echo"\t".$x[$k]; #optional Output of the count of the matchsticks

Oh snap, bu da negatif sayılar üzerinde çalışıyor!
Sihirli Ahtapot Urn

@ carusocomputing aslında daha az kibrit çubukları ile bir çözüm var olabilir çünkü negatif sayılar sadece çıkarma ile eklenir. bu durumlarda da mutlak değeri kontrol etmeli ve bir tane eklemelisiniz
Jörg Hülsermann

333'ün burada kabul edilebilir olacağını düşünmüyorum, ancak girişin bir işlevi haline getirerek düzeltebilirsiniz. (Program çok daha yavaş çalışabilir, bu nedenle test için sabit kodlu sürümü

1
@ ais523 done 333, 2 * giriş ile değiştirildi
Jörg Hülsermann

1
Dizin dizeleri yapabilirsiniz: $e+="6255456376"[$i[$s++]];.
17'de
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.