100'e kadar en az işlem


15

genel bakış

Rakamların bir listesi verildiğinde, 100 yapmak için en az işlemi bulun

Giriş

Sayısal sırada olabilecek veya olmayabilecek bir rakam dizesi. Rakamların sırası değiştirilemez, ancak toplam (toplam) 100'e eşit olacak şekilde her biri arasına artı (+) veya eksi (-) operatörleri eklenebilir.

Çıktı

Eklenen operatör sayısı ve ardından tam basamak ve operatör sırası. İkisi bir boşluk, sekme veya yeni satır sırası ile ayrılabilir.

Örnekler

geçerli

Giriş: 123456789
Çıkış:3 123–45–67+89

Geçersiz
Girdi: 123456789
Çıktı:
6 1+2+34-5+67-8+9
(Bunu daha az işlemle çözmenin yolları vardır)



Tüm rakamları kullanmak zorunda mıyız? Sadece +ve kullanabilir miyiz -? Girişten her zaman yapabileceğimizi varsayabilir miyiz 100?
TheLethalCoder

6
Bazı test senaryoları çok memnuniyetle karşılanacaktır.
Arnauld

2
İşaretlerin ilk basamağa eklenemeyeceğini teyit edebilir misiniz? Yani, giriş verilir 299399, olur -299+399geçerli olması?
Luis Mendo

1
'0' bir rakam mı? Örneğin, '10808' geçerli bir girdi mi? '1 108-08' geçerli bir yanıt mı?
Chas Brown

Yanıtlar:


10

JavaScript (ES6), 153 176 bayt

DÜZENLEME: Sıkı olmayan modda JS, 0 önekli sayısal ifadeleri sekizlik olarak yorumlar (örneğin 017, ondalık olarak 15 olarak ayrıştırılır). Bu, önde gelen sıfırları destekleyen sabit bir sürümdür.

let f =

s=>[...Array(3**(l=s.length,l-1))].map((_,n)=>m=eval((x=s.replace(/./g,(c,i)=>c+['','+','-'][o=(n/3**i|0)%3,j-=!o,o],j=l)).replace(/\b0+/g,' '))-100|j>m?m:(S=x,j),m=l)&&m+' '+S

console.log(f("123456789"))
console.log(f("20172117"))


Güzel, 20172117 girdisi ne olacak?
mdahmoune

@LuisMendo Aslında, beklenen cevap olduğunu düşünüyorum 2-017-2+117. Ancak 017JS'de ondalık sayı olarak 15 veren sekizli bir gösterimdir. Yani şu anki kodum sadece bulur 2-0-17-2+117. Bu sorunu bugün daha sonra çözmeye çalışacağım.
Arnauld

@Arnauld Ah, başka bir çözüm görmemiştim. Yorumumu kaldırma
Luis Mendo

@mdahmoune Bunu getirdiğin için teşekkürler. Şimdi düzeltildi.
Arnauld

3**(l=s.length,l-1) => 3**~-(l=s.length)
l4m2

5

MATL , 37 36 bayt

n'+-'OhZ^!t2\s&SZ)"G@!vXzU100=?@z3M.

Test durumu TIO'da yaklaşık 6 saniye sürer.

Çevrimiçi deneyin!

Nasıl çalışır

n        % Implicitly input a string. Number of elements, say k
'+-'     % Push this string
Oh       % Append char 0. This is treated like ' ' (space)
Z^       % Cartesian power of the three-char string '+- ' raised to k.
         % Gives a matrix where each row is a Cartesian k-tuple
!        % Transpose
t        % Duplicate
2\       % Modulo 2. This turns '+' and '-' into 1, and ' ' into 0
s        % Sum of each column: number of '+' and '-' symbols
&S       % Sort and push the indices of the sorting
Z)       % Apply as column indices. This sorts the columns (k-tuples)
         % by the number of '+' and '-' they contain
"        % For each column, i.e. each k-tuple formed by '+', '-' and ' '
  G      %   Push input string again
  @!     %   Push k-tuple as row vector (string)
  v      %   Concatenate vertically into a 2×k char array
  Xz     %   Remove space (and char 0). Gives a string as result. In this
         %   process, the 2×k array is linearized in column major order 
         %   (down, then across). So the '+' and '-' signs are between 
         %   digits of the input, or at the end
  U      %   Convert to number. This performs the operation determined by
         %   by the '+' and '-' signs and returns the result. A trailing
         %   '+' or '-' sign makes the input invalid, which causes an
         %   empty result
  100=   %   Is it equal to 100?
  ?      %   If so
    @    %     Push current k-tuple
    z    %     Number of nonzeros, i.e. of '+' and '-' signs
    3M   %     Push linearized string without spaces again
    .    %     Break for loop
         %   Implicit end
         % Implicit end
         % Implicitly dispplay stack

Harika, girdi olarak 299399'a ne dersin?
mdahmoune

1
@mdahmoune'un bir 299399çözümü yoktur ve bu nedenle geçerli bir girdi değildir (operatörlerin basamaklar arasında "gitmesi" belirtilmiştir, bu girdi basamaklar arasında olmadığı -299+399yerde gerektirir -).
Jonathan Allan

işaretler tek eklenebilir Eğer @mdahmoune arasındaki (meydan okuma metni söylediği gibi) hane, ben hiçbir çözüm olduğunu düşünüyorum. İlk basamağa da eklenebilirlerse, çözümdür -299+399ve bu durumda kodumda küçük bir değişikliğe ihtiyacım var .
OP'den

Ayrıca önce her iki olması gerekiyordu sanki dikkat çekicidir ve aralarında daha sonra örnek 123456789bir operatör sayısını olmalıdır 4değil 3.
Jonathan Allan

@mdahmoune OP işaretlerin sadece rakamlar arasında olabileceğini doğruladı. Bu yüzden kodum doğru ve 299399geçersiz bir girdi çünkü OP'nin de açıkladığı gibi, her girdinin en az bir çözümü olmalı
Luis Mendo

3

[Python 2], 164156 bayt

from itertools import*
f=lambda N:min((len(s)-len(N),s)for s in(''.join(sum(zip(N,p+('',)),()))for p in product(('+','-',''),repeat=len(N)-1))if eval(s)==100)

Çevrimiçi deneyin!

N'yi bir basamak dizisi olarak kabul edin; bir tuple döndürür (numOps, expressionString).

Temelde diğerleriyle aynı yaklaşım; "=" 1322 "için tek tek" vakaları "oluşturmak için itertools.product kullanır," case "olur ('-','','+')ve" 1-32 + 2 "değerini değerlendirir.

Giriş geçersizse bir ValueError atar (ancak OP'nin geçersiz girişleri garantilemediğini düşünüyorum).


3

PHP, 166 171 bayt

for(;$n<3**$e=strlen($x=$argn);eval("return $s;")-100?:$r[]=sprintf("%2d $s",strlen($s)-$e))for($i=0,$s="",$k=$n++;a&$c=$x[$i];$k/=3)$s.="+-"[$i++?$k%3:2].$c;echo min($r);

Pipo ile çalıştırın -nRveya çevrimiçi test edin .

sonuçları sıralamak için biçimlendirilmiş sayılar kullanır ->
önde gelen boşlukları yazdırabilir (ve 99'dan fazla basamağa sahip girdi için başarısız olabilir; %2ddüzeltilecek sayıyı artırın ).

10 basamaktan fazla değil, 161 bayt

for(;$n<3**$e=strlen($x=$argn);eval("return $s;")-100?:$r[]=(strlen($s)-$e)." $s")for($i=0,$s="",$k=$n++;a&$c=$x[$i];$k/=3)$s.="+-"[$i++?$k%3:2].$c;echo min($r);

Yıkmak

for(;$n<3**$e=strlen($x=$argn); # loop $n up
    eval("return $s;")-100?:        # 2. evaluate term, if 100 then
                                    # prepend number of operations, add to results
        $r[]=sprintf("%2d $s",strlen($s)-$e)
)
                                # 1. create term
    for($i=0,$s="",$k=$n++;         # init variables, increment $n
        a&$c=$x[$i];$k/=3)          # loop through digits/operator index
        $s.="+-"[$i++?$k%3:2].$c;   # prepend operator for base-3 digit (nothing for 2)
echo min($r);                   # print lowest result

3

Jöle , 32 bayt

L’⁾+_ṗż@€
ŒṖÇ€ẎµFV=ȷ2µÐfLÞḢFṄḟ³L

Jelly operatörlerini kullanarak ( _yerine -) gösteren tam bir program .

Not: göstermek için -yerine çıktıda _eklemek (bir şartı) ⁾_-yarasında Fve ( ⁾_-bir karakter çifti değişmezi olduğunu ['_','-']vey diyadik "tercüme" atomu olduğu).

Nasıl?

L’⁾+_ṗż@€ - Link 1, form all sums from a partition: list of lists of characters
                                     e.g. ["12","345","67"]
L         - length                        3
 ’        - decremented                   2
  ⁾+_     - literal ['+','_']
     ṗ    - Cartesian power               ["++","+_","_+","__"]
      ż@€ - zip for €ach (swap @rguments) ["12+345+67","12+345_67","12_345+67","12_345_67"]

ŒṖÇ€ẎµFV=ȷ2µÐfLÞḢFṄḟ³L - Main link: list of characters
ŒṖ                     - all partitions
  Ç€                   - call the last link (1) as a monad for €ach
    Ẏ                  - tighten (flatten by 1 level)
     µ     µÐf         - filter keep if:
      F                -   flatten
       V               -   evaluate as Jelly code (perform the sum)
         ȷ2            -   literal 100
        =              -   equal?
               Þ       - sort by:
              L        -  length
                Ḣ      - head
                 F     - flatten
                  Ṅ    - print that and a newline
                   ḟ³  - filter out the characters from the input
                     L - length (number of operators)
                       - implicit print

Çevrimiçi deneyin!


2

Mathematica, 136 146 149 156 165 166 bayt

#&@@Sort[{StringLength@#-e+9!(ToExpression@#-100)^2,#}&/@StringJoin/@(Riffle[b,#]&)/@Tuples[{"","+","-"},(e=Length[b=Characters@#])-1]]&

{3, 123-45-67+89}Örneğin döndürür .

Test vakasının tamamlanması yaklaşık 0.09 saniye sürer.


2

Piton 2 , 256 230 208 205 172 171 170 165 bayt, yineleme yöntemi

  • 33 teşekkürler Chas Brown
  • Değiştirirken Bir byte kurtardı len(a)tarafındanw
  • Değiştirirken Bir byte kurtardı z-=1;d=ztarafındand=z=z-1
q=[];a=input()
w=len(a);z=n=3**w
while z-n/3:
 d=z=z-1;j=0;b=''
 while d:r=d%3;d/=3;b+=a[j]+chr(r+43)*(d>0!=r-1);j+=1
 if eval(b)==100:q+=[(len(b)-w,b)]
print min(q)

Çevrimiçi deneyin!

Küçük açıklama Taban 3'teki temsili kullanarak, kod rakamları tüm olası kombinasyonlara göre {'+', '-', birleştirme} operatörleriyle araya ekler.

Python 2 , 167 bayt, özyinelemeli yöntem

def f(s):
 if len(s)==1:return[s]
 b=s[0];q=[]
 for z in f(s[1:]):q+=[b+'+'+z,b+'-'+z,b+z]
 return q
a=input()
print min((len(x)-len(a),x)for x in f(a)if eval(x)==100)

Çevrimiçi deneyin!

Bazı çıktılar

"399299"    --> (1, '399-299')
"987654321" --> (4, '98-76+54+3+21')
"1111111"   --> (3, '1+111-1-11')

1
Divmod kullanımını seviyorum! Görebildiğim birkaç golf: list(input())sadece input()bir dize ile değiştirin , çünkü bir dize zaten 6 bayt kaydetmek için tekrarlanabilir; 12 bayt kaydetmek için b.count('+')+b.count('-')ile değiştirin len(b)-len(a); ve değiştirme chr(r+43)ile chr(r+43)*(d>0!=r-1)ve daha sonra çizgiyi silebilir b=b[:-1].replace(',',''), net 15 bayt kaydetmek için ( (d>0!=r-1)eşdeğerdir (d>0 and 0!=r-1)).
Chas Brown

2

Brachylog , 36 bayt

~cịᵐ{|ṅ}ᵐ{+100&{ℕṫ,"+"↻|ṫ}ᵐcbE&kl;E}

Çevrimiçi deneyin!

Bunun yarısından fazlası çıktı formatını tam olarak elde etmektir. Gerçek çekirdek mantık sadece:

15 bayt

~cịᵐ{|ṅ}ᵐ.+100∧

Çevrimiçi deneyin!

Bu [123, –45, –67,89] gibi bir liste döndürür. İfade, öğelerin toplamıdır ve operatör sayısı listenin uzunluğundan 1 daha azdır.

~cLhℕ∧100~+Lneredeyse 12 bayt için çalışıyor ( çevrimiçi deneyin! ) - ancak 10808TIO'da tam 9 haneli girişi işlemek için çok yavaş ve daha da önemlisi, girişler için başarısız - Brachylog, sayıları bölmek için çok zekidir, bu yüzden ' t [108, -08] bölümüne bakınız.


1

Haskell , 180 178 bayt

m#[a]=[[a]]
m#(b:r)|s<-m#r=m(b:)=<<[s,m('+':)s,m('-':)s]
o '-'=(-)
o _=(+)
(p:r)?a|[(b,s)]<-lex r=s?o p a(read b)
_?a=a
g s=minimum[(sum[1|c<-t,c<'0'],t)|t<-map#s,('+':t)?0==100]

Çevrimiçi deneyin! Kullanımı: g "123456789"verim (3,"123-45-67+89").

#olası tüm terimlerin bir listesini oluşturur, ?bir terimi gdeğerlendirir ve 100 olarak değerlendirilen terimleri filtreler ve en az sayıda işlenen ile döndürür.


0

Jöle , 27 bayt

L’““+“_”ṗ⁸żF¥ⱮV⁼ȷ2ƊƇLÞḢṄḟ⁸L

Çevrimiçi deneyin!

Jonathan Allan'ın eski cevabından birkaç ipucu almadığımı söyleyemem. ;-)

Cevabına kıyasla, dil güncellemeleri nedeniyle karşılaştırmayı adil yaparsak, bu beş değil, sadece iki bayt daha kısadır (30):

L’““+“_”ṗ⁸żF¥Ð€V⁼ȷ2$$ÐfLÞḢṄḟ⁸L

Diğer yolu karşılaştırırsak (eski yerine daha yeni sürüm), fark aynıdır (aşağıda görülen 29 bayt olur):

ŒṖżⱮL’⁾+_ṗƲ$€ẎFV=ȷ2ƲƇLÞḢFṄḟ³L
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.