Temel kodlu ifade verme


21

Arka fon

Bazı olası geleceklerde, dünya sayısal sistemlerini ondalık basamağa (10 ya da 10 b10) başka bir basamağa (ikili b2, sekizli b8, onaltılı b16ya da hatta tekdüze b1, ki bu durumda batırdık!) Dönüştürecektir . Böylece, bu olası dünyayı değiştiren etkinliğe hazırlanırken, tüm programlarınızı temel almaya karar verdiniz. Bu , mevcut sayı sabitlerini değiştirmek için sadece tekil 0s ve 1s operatörleri ile birlikte kullanılarak yapılabilir .

Ancak, tek bir sorun var: Değiştirecek bir sürü programınız var ve her sayının manuel olarak bir ifadeye dönüştürülmesi haftalar alacaktır! Bu nedenle, hangi ifadenin her bir sayıyı değiştirmesi gerektiğine karar vermek için bir program (veya işlev) yazmaya karar veriyorsunuz.

Giriş

Giriş pozitif bir tamsayı olacaktır. Kodunuz gerekmektedir 1000 arasında herhangi bir tamsayı kadar idare edebilmek.

(Kodunuz ondalık basamakları ve / veya negatif girişleri destekliyorsa, aşağıdaki Skorlara bakın.)

Çıktı

Kodunuz, girişi en az bir dilde değerlendiren bir ifade çıkarmalıdır. Bu herhangi bir dilde olabilir; programınızın veya işlevinizin yazıldığı ile aynı olması gerekmez. Ayrıca, bu ifadenin tam bir program veya işlev olması gerekmez.

Netlik açısından çıktı şu işlemlerden herhangi birini içerebilir:

  • artış / azalış
  • ekle / topla
  • çıkarma / olumsuzlama
  • çarpın / çift (yalnızca doğrudan sayı içermiyorsa 2!)
  • böl / modulo
  • üsler / logaritmalar
  • square / sqrt (yine, bunlar doğrudan sayı içermiyorsa 2!)
  • bitsel işlemler (bOR, bAND, bNOT, bXOR, bit değişimleri)
  • değişkenleri ayarlama / alma
  • yığın manipülasyonu

Sen olabilir değil kullanmak eval()veya çıktıda herhangi benzer fonksiyonlar. Ayrıca çıktıda yukarıda belirtilenlerin dışında bir işlem yapan işlevleri kullanamazsınız.

Oh, ve bir şey daha: Çıktının mümkün olduğu kadar çok sayıda temelde geçerli olmasını istediğimizden, içerebileceği tek sayı sabiti 0ve 1. Gibi Numaralar 10(on), izin verilmeyen bir şekilde dil yorumladığını sürece 1ve 0. Sayıları içeren dizelerin kullanılmasına, CJam'in A- K(temsil eden 10- 20) gibi karakterlerin kullanımına izin verilmez .

Test-vakalar

(Tüm çıktılar JavaScript’tedir, ancak diğer dillerde de çalışabilir.)

Giriş 1:

2

Mümkün çıkış 1:

1+1

Giriş 2:

13

Mümkün çıkış 2:

(a=1+1+1)*a+a+1

Giriş 3:

60

Mümkün çıkış 3:

(b=(a=1+1+1+1)*a)*a-a

Giriş 4:

777

Mümkün çıkış 4:

(c=(b=((a=1+1+1+1)*a-a+1)*a)*a+b)+c+c-a+1

Giriş 5:

1000

Mümkün çıkış 5:

Math.pow((a=1+1+1)*a+1,a)

puanlama

Bu zorluğun amacı, kodunuzun çıktısını mümkün olduğunca kısaltmaktır. Puanınız bu şekilde hesaplanacaktır:

  • Temel puan: 1 ila 1000 arasında tamsayılar için tüm çıktıların ortalama bayt sayısı.

  • Ondalık puan: Kodunuz en az 3 ondalık basamağı destekliyorsa, bu, her seferinde artan 0.001ve sonunda başlayan ve biten sayılar dizisinin tüm çıktılarının ortalama bayt sayısıdır . Ardından bu puanın% 50'sini çıkarın.10001.0010.001, 1.002, 2.003...998.999, 1000.000

  • Negatif skor: kodunuzu negatif sayılar ve sıfır destekliyorsa, bu tüm tamsayılar çıkışların ortalama bayt sayısıdır -1000için 0. Ardından bu puanın% 10'unu çıkarın.

(Bunları hesaplamanın en kolay yolu büyük olasılıkla içinde programınız / işlevinizle birlikte bir döngü olacaktır.)

Nihai puanınız, yukarıdaki formüllerden hangisinin geçerli olduğu ortalamasıdır.

Çıktı deterministik değilse (yani biraz rasgele; aynı girdiyle birden fazla çalıştırma birden fazla benzersiz çıktı üretir), o zaman her girdi için puan CPU'mdaki on çalıştırma üzerindeki en büyük çıktı tarafından belirlenir.

Ayrıca gelecekte bilgisayar verilerinin ne kadar değerli olacağını bilmediğiniz için, jeneratör kodunuzun bayt sayısı 512 bayttan az olmalıdır.

İki haftadaki en düşük skor (30 Eylül'de) kazanan ilan edilecek. Kazanan için tebrikler, @ThomasKwa !


Liderler Sıralaması

Cevabınızın doğru göründüğünden emin olmak için, lütfen bu başlık ile başlayın:

# Language name/Other language name, X points

XCevabınızın puanı nerede . Örnek:

# CJam/Pyth, 25.38 points

Herhangi bir sorunuz veya öneriniz varsa, lütfen bana bildirin. İyi şanslar!


Bekletilen değişkenleri 0veya 1varsayılan olarak kullanabilir miyim ?
Dennis,

@Dennis Bununla bir problem görmüyorum, bu yüzden devam et!
ETHProductions

Temel 2 ile varsayılan temel arasında temel dönüştürme yapamayacağımı farz ediyorum.
Mavi,

@muddyfish Hayır, çıktıda baz dönüşümüne izin verilmez.
ETHProductions,

Sanırım aynı zamanda böyle bir şeyi kullanmamıza izin verilmiyor Integer.parseInt("1000", 1+1+1+1+1+1+1+1+1+1)? Ben eminim parseIntkullanan tek izin işlemleri ;-)
Paulo Ebermann

Yanıtlar:


10

Python / Zilog Z80 makine kodu, 11.653 11.488

import math,numpy as np
def R(n):
    if n==0:return []
    if n<0:return -R(-n)
    e=int(math.log(n,2))
    if n >= 5/3 * 2**e:
        return np.append(2**(e+1),-R(2**(e+1)-n))
    return np.append(2**e,R(n-2**e))

def strR(n):
    b = R(n)
    s = ""
    if n==0:return s
    e=max(abs(b))
    while e:
        if e in b:s+="#"
        elif -e in b:s+="+"
        s+=")"
        e//=2
    return s[:-1]

Bonuslar: Negatif sayılar.

hlKayıt çiftinin başlangıçta 0 tutacağını ve sonucu döndürdüğünü varsayar hl.

Sadece bu üç talimat kullanılır:

ASCII   Hex    Instruction
--------------------------
#       23     inc hl
)       29     add hl,hl
+       2B     dec hl

Minimum ağırlık dengeli ikili ikili gösterim BBR2'de küçük bir değişiklik kullanıyoruz . BBR2, ağırlığı (sıfır olmayan basamak sayısı) en aza indirdiğinden, ancak ağırlığı ve bit kaydırma sayısını en aza indirmek istediğimiz için algoritmadaki bir sabiti - den 3/2değiştiririz 5/3.

Puanı hesaplamak ve doğrulamak için bu kodu kullanın:

def verify(n):
v = 0
for c in strR(n):
    if c=="#":v += 1
    elif c=="+":v -= 1
    else: v *= 2
return v==n

print(0.5*(sum([len(strR(n)) for n in range(1,1001)])/1000 + \
           sum([len(strR(n)) for n in range(-1000,1)])/1001 * 0.9))

print(all([verify(n) for n in range(-1000,1001)]))

Örnek çıktı:

strR(486)
         '#)))))+)+))+)'

Veya montajda:

inc hl \ add hl,hl \ add hl,hl \ add hl,hl \ add hl,hl \ add hl,hl \ dec hl \ add hl,hl \ dec hl \ add hl,hl \ add hl,hl \ dec hl \ add hl,hl

Daha fazla örnek program:

-256  +))))))))
-255  +))))))))#
-254  +)))))))#)
-253  +)))))))#)#
-252  +))))))#))
-251  +))))))#))#
-250  +))))))#)#)
-249  +)))))#)))+
-248  +)))))#)))
-247  +)))))#)))#
-246  +)))))#))#)
-245  +)))))#))#)#
-244  +)))))#)#))
-243  +)))))#)#))#
-242  +))))#)))+)
-241  +))))#))))+

  -5  +))+
  -4  +))
  -3  +)+
  -2  +)
  -1  +
   0  
   1  #
   2  #)
   3  #)#
   4  #))
   5  #))#

Olası optimizasyonları: OP kuralları olduğunu inc hve dec hdoğrudan üst Byte'ını talimatlar hl, yasadışı, ancak sla hve belgelenmemiş sl1 h(üzerinde 1 ile sol bit vardiya hbir o vardiya 0ve 1sırasıyla) izin verilir. sla hve sl1 hher biri iki bayttır, ancak bazen çıktıyı kısaltabilirler.


Çok güzel, şimdiye kadar en düşük! Sanırım bu, saf makine kodunun kullanışlı olduğu bir örnek. ;)
ETHproductions 17:15

2
+1 bu muhtemelen yenilmezdir. Ayrıca, makine kodunu kullanma dehası için (büyük ölçüde 8 bit komut seti ve bazı 16 bit yazmaçlara sahip bir CPU'da.)
Level River St

Nasıl +tercüme edileceği tuhaf dec. Olumsuz örnekleri yanlış okudum.
ETHProductions

9

CJam / CJam, 143.263 42.713 28.899 23.901 21.903 20.468

ri
[
    ['X\2b1>e`{~{"1)*)"*}{_({(')*1\"m<"}{"1)*"*}?}?}/]s
    "X1)*"/"1)"*
    "1)1)*"/"1)))"*
    "X1)m<"/"1)))"*
    _"1)"/("1):Y"+\'Y*+
]
{,}$0=

Bonus yoktur.

Çevrimiçi deneyin: örnek çalışma | puan hesap makinesi | doğrulama

Örnek çalıştırmalar

   1 X
   2 1)
   3 1))
   4 1)))
   5 1))))
   6 1))1)*
   7 1))1)*)
   8 X1))m<
   9 1)))1)*)
  10 1))))1)*
  11 1))))1)*)
  12 1))1)m<
  13 1))1)*1)*)
  14 1))1)*)1)*
  15 1))1)*)1)*)
  16 X1)))m<
  17 X1))m<1)*)
  18 1)))1)*)1)*
  19 1)))1)*)1)*)
  20 1))))1)m<
 981 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*Y*)
 982 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*)Y*
 983 1):Y)Y*)Y*)Y*Y*)Y*Y*)Y*)Y*)
 984 1):Y)Y*)Y*)Y*Y*)Y*)Y)m<
 985 1):Y)Y*)Y*)Y*Y*)Y*)Ym<Y*)
 986 1):Y)Y*)Y*)Y*Y*)Y*)Y*Y*)Y*
 987 1):Y)Y*)Y*)Y*Y*)Y*)Y*Y*)Y*)
 988 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Ym<
 989 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*Y*)
 990 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*)Y*
 991 1):Y)Y*)Y*)Y*Y*)Y*)Y*)Y*)Y*)
 992 1):Y)Y*)Y*)Y*)Y)))m<
 993 1):Y)Y*)Y*)Y*)Y))m<Y*)
 994 1):Y)Y*)Y*)Y*)Y)m<Y*)Y*
 995 1):Y)Y*)Y*)Y*)Y)m<Y*)Y*)
 996 1):Y)Y*)Y*)Y*)Ym<Y*)Ym<
 997 1):Y)Y*)Y*)Y*)Ym<Y*)Y*Y*)
 998 1):Y)Y*)Y*)Y*)Ym<Y*)Y*)Y*
 999 1):Y)Y*)Y*)Y*)Ym<Y*)Y*)Y*)
1000 1):Y)Y*)Y*)Y*)Y*Y*)Y)m<

Sözüm, bu hızlı oldu! Linkler Firefox'ta çalışmıyor.
ETHproductions

Bu kod golf olmadığından, her birini %daha uzun bir ifadeyle değiştirdim. Bağlantılar şimdi çalışmalı.
Dennis,

Giriş 34 verir. Hangi giriş daha iyi çalışır
Kishan Kumar

2
@KishanKumar Doğrulama, tüm 1000 olası girişi sınar. Çıktı 1 , karşılaştırmanın başarılı olduğunu gösterir.
Dennis,

Bazı örnek çıktılar ekleyebilir misiniz?
Paŭlo Ebermann 16:15

3

ß / BrainFuck, 34.201 puan

ß kaynağı (194B):

E='++[------>+<]>++'°\c[1]<0°{E&='.'µA=ß"-ß°°c[1]),'')µE&='+++'°/B=1°(A[0]°\A[B]='.'°{µE&='--.++'°]E&=ß~A'+',A[B])&'.'&ß~A'-',A[B])°}°)°'ß"&E,'+-')+ß"&E,'-+')>0µE=ß"'ß"'E,'-+',''),'+-','')°!€E)

Birisi ilgileniyorsa, bir açıklama ekleyeceğim. BF çıktısı zaten oldukça optimize edilmiş, fakat uygulamak için kalan 318B ß kodunu kullanabilirim.

  • döngü yerleştirme optimizasyonu,
  • daha fazla 8bit taşma kısayolu,
  • operatör çarpışma giderme .

Örnekler:

Pencerelerde çalıştırma:

$ sharps encode.ss 42
++[------>+<]>+++++++++.--.--

$ sharps encode.ss -42
++[------>+<]>++.+++++++.--.--

$ sharps encode.ss 1.427
++[------>+<]>++++++.---.++++++.--.+++++.-------

$ sharps encode.ss -946.427
++[------>+<]>++.++++++++++++.-----.++.--------.++++++.--.+++++.-------

Linux'da çalışan:

$ WINEDEBUG=-all wine sharps source.ss -4.72
++[------>+<]>++.+++++++.------.+++++++++.-----.--

Çevrimiçi BF yorumlayıcısında doğrulayın .

Skorlar:

  1. Baz ortalama = 37.495.
  2. Ondalık ortalama = 60.959 * 0.5 = ~30.48.
  3. Olumsuz avg. = 38.4765234765235 * 0.9 = ~34.629
  4. Yukarıdakilerin ortalaması, son puan = (37.495 + 30.48 + 34.629)/3 = 34.201.

1
İnsanların yarattığı yeni dilleri görmeyi her zaman seviyorum. :) Puan dağılımı için teşekkürler! Ondalık bölüme daha fazla bonus koymak istiyorum, bu yüzden indirimi% 40'tan% 50'ye değiştirdim.
ETHProductions,

@ETHproductions Evet, bunun için çevrimiçi bir tercüman kurmayı deneyeceğim. Yaklaşık 435 tane yüksek derecede soyut operatör vardır, ek 9,9k tanımlanabilir ;-). Hesaplamayı düzelttim (umarım).
mınxomaτ 17:15

3

Ruby / Ruby, 29.77885

31.873 * 0.9 (negatif) 30.872 (pozitif).

Temel strateji simetrik taban 3 gösterimidir ("dengeli üçlü"), yani rakamlar -1,0,1yerine0,1,2

#function
f=->n{m=n  
  a='0' 
  7.times{|i|
    r=m%3;r-=r/2*3
    m=(m-r)/3
    #produce expression: replace 0 with (0*x+-1)
    #only add 0*x if there are higher base 3 digits to follow.
    #only add (..+-1) if the current base 3 digit is nonzero. 
    a.sub!('0',['','(','('][r]+(m.abs>0?'0*x':'')+['','+1)','-1)'][r])
  }
  #tidy up expression
  a.sub!('(-1)*','-')          #remove internal (-1)*
  a.sub!('(+1)*','')           #remove internal (+1)*
  a[-1]==')' && a=a[1..-2]     #remove unnecessary global brackets
  a.sub!('x','(x=1+1+1)')      #find the first x and define it as 1+1+1=3
  #special cases for small numbers 
  n.abs<8 && a=n==0?'0':['','1'+'+1'*(n-1).abs,'-1'*n.abs][n<=>0] 
  a 
}

#call like this
(1..1000).each{|p|
b=f.call(p)
puts b

İşte temizleme işleminden önce 0 - 40 arası çıktı

(+1)
((+1)*x-1)
(+1)*x
((+1)*x+1)
(((+1)*x-1)*x-1)
((+1)*x-1)*x
(((+1)*x-1)*x+1)
((+1)*x*x-1)
(+1)*x*x
((+1)*x*x+1)
(((+1)*x+1)*x-1)
((+1)*x+1)*x
(((+1)*x+1)*x+1)
((((+1)*x-1)*x-1)*x-1)
(((+1)*x-1)*x-1)*x
((((+1)*x-1)*x-1)*x+1)
(((+1)*x-1)*x*x-1)
((+1)*x-1)*x*x
(((+1)*x-1)*x*x+1)
((((+1)*x-1)*x+1)*x-1)
(((+1)*x-1)*x+1)*x
((((+1)*x-1)*x+1)*x+1)
(((+1)*x*x-1)*x-1)
((+1)*x*x-1)*x
(((+1)*x*x-1)*x+1)
((+1)*x*x*x-1)
(+1)*x*x*x
((+1)*x*x*x+1)
(((+1)*x*x+1)*x-1)
((+1)*x*x+1)*x
(((+1)*x*x+1)*x+1)
((((+1)*x+1)*x-1)*x-1)
(((+1)*x+1)*x-1)*x
((((+1)*x+1)*x-1)*x+1)
(((+1)*x+1)*x*x-1)
((+1)*x+1)*x*x
(((+1)*x+1)*x*x+1)
((((+1)*x+1)*x+1)*x-1)
(((+1)*x+1)*x+1)*x
((((+1)*x+1)*x+1)*x+1)

Ve temizlikten sonra

0
1
1+1
1+1+1
1+1+1+1
1+1+1+1+1
1+1+1+1+1+1
1+1+1+1+1+1+1
(x=1+1+1)*x-1
(x=1+1+1)*x
(x=1+1+1)*x+1
((x=1+1+1)+1)*x-1
((x=1+1+1)+1)*x
((x=1+1+1)+1)*x+1
(((x=1+1+1)-1)*x-1)*x-1
(((x=1+1+1)-1)*x-1)*x
(((x=1+1+1)-1)*x-1)*x+1
((x=1+1+1)-1)*x*x-1
((x=1+1+1)-1)*x*x
((x=1+1+1)-1)*x*x+1
(((x=1+1+1)-1)*x+1)*x-1
(((x=1+1+1)-1)*x+1)*x
(((x=1+1+1)-1)*x+1)*x+1
((x=1+1+1)*x-1)*x-1
((x=1+1+1)*x-1)*x
((x=1+1+1)*x-1)*x+1
(x=1+1+1)*x*x-1
(x=1+1+1)*x*x
(x=1+1+1)*x*x+1
((x=1+1+1)*x+1)*x-1
((x=1+1+1)*x+1)*x
((x=1+1+1)*x+1)*x+1
(((x=1+1+1)+1)*x-1)*x-1
(((x=1+1+1)+1)*x-1)*x
(((x=1+1+1)+1)*x-1)*x+1
((x=1+1+1)+1)*x*x-1
((x=1+1+1)+1)*x*x
((x=1+1+1)+1)*x*x+1
(((x=1+1+1)+1)*x+1)*x-1
(((x=1+1+1)+1)*x+1)*x
(((x=1+1+1)+1)*x+1)*x+1

Ben buna "dengeli üçlü" dendiğine inanıyorum.
lirtosiast 17:15

@ThomasKwa sayesinde düzenlenebilir
Seviye Nehri ST

3

Ceylon / Ceylon, 49.86 40,95 puan

Üçüncü versiyon, jeneratör için Ceylon 1.2 ve 509 baytlık kod kullanır:

import ceylon.language{S=String,I=Integer,e=expand}S q(I n)=>n==0then"0"else(n<0then"-"+p(-n,"-")else p(n,"+"));variable Map<[I,S],S>c=map{};S p(I n,S s){S v=c[[n,s]]else(n<8then s.join([1].repeat(n)))else(let(a="+-".replace(s,""))e(e{for(x in 2..8)let(l=(n^(1.0/x)).integer){for(r in l:2)if(r>1)let(w=r^x){if(w-n<n)"("+p(r,"+")+")^("+p(x,"+")+")"+(w<n then s+p(n-w,s)else(n<w then a+p(w-n,a)else""))}}}).reduce<S>((x,y)=>x.size<y.size then x else y))else"";c=[n,s]in c then c else map{[n,s]->v,*c};return v;}

Bu, 35.22 puana iniyor, ancak bunu başlık satırına koymuyorum çünkü Celyon 1.2 yalnızca 29 Ekim'de yayınlandı. Bu algoritmayı Ceylon 1.1'de bu boyutta uygulayabileceğimi sanmıyorum.) Aşağıda daha fazla ayrıntı, burada ikinci sürümünü anlatacağım. (İlk sürüm tarihte görülebilir - yalnızca pozitif sayıları destekledi, ancak 256 bayta sığdı.)

İkinci versiyon

Şimdi negatif tamsayıları (ve 0) destekleyen ve genellikle ek olarak kullanarak biraz daha kısa çıktılar veren ikinci sürüm -. (Bu sürüm aslında izin verilen uzunluğu kullanır, ilki 512 yerine 256 baytın altında kalmaya çalıştı.)

String proof(Integer n) {
    if (n == 0) { return "0"; }
    if (n < 0) { return "-" + p(-n, "-"); }
    return p(n, "+");
}
String p(Integer n, String sign) {
    if (n < 9) {
        return sign.join([1].repeat(n));
    }
    value anti = (sign == "+") then "-" else "+";
    value root = ((n^0.5) + 0.5).integer;
    return "(" + p(root, "+") + ")^(1+1)" +
       ( (root^2 < n) then sign + p(n - root^2, sign) else
         ((n < root^2) then anti + p(root^2 - n, anti) else ""));
}

Kodun uzunluğu 487, bu nedenle daha sonra daha fazla optimizasyon için hala biraz boşluk var. (Ayrıca, boşluk ve uzun değişken adları şeklinde birçok rezerv vardır.)

Puanlama:

Total positive: 42652
Average positive:42.652
Total negative: 43653
Average negative: 43.60939060939061
With bonus:39.24845154845155
Overall score: 40.95022577422577

Bazı örnek çıktılar:

   27:  21: (1+1+1+1+1)^(1+1)+1+1
   28:  23: (1+1+1+1+1)^(1+1)+1+1+1
   29:  25: (1+1+1+1+1)^(1+1)+1+1+1+1
   30:  27: (1+1+1+1+1)^(1+1)+1+1+1+1+1
   31:  29: (1+1+1+1+1+1)^(1+1)-1-1-1-1-1
   32:  27: (1+1+1+1+1+1)^(1+1)-1-1-1-1
   33:  25: (1+1+1+1+1+1)^(1+1)-1-1-1
   34:  23: (1+1+1+1+1+1)^(1+1)-1-1

  -27:  22: -(1+1+1+1+1)^(1+1)-1-1
  -28:  24: -(1+1+1+1+1)^(1+1)-1-1-1
  -29:  26: -(1+1+1+1+1)^(1+1)-1-1-1-1
  -30:  28: -(1+1+1+1+1)^(1+1)-1-1-1-1-1
  -31:  30: -(1+1+1+1+1+1)^(1+1)+1+1+1+1+1
  -32:  28: -(1+1+1+1+1+1)^(1+1)+1+1+1+1
  -33:  26: -(1+1+1+1+1+1)^(1+1)+1+1+1
  -34:  24: -(1+1+1+1+1+1)^(1+1)+1+1


  993:  65: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1+1)^(1+1)+1+1+1+1+1
  994:  63: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1-1-1
  995:  61: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1-1
  996:  59: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1-1
  997:  57: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1-1
  998:  55: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)-1
  999:  53: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)
 1000:  55: ((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)-(1+1+1+1+1)^(1+1)+1

 -993:  66: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1+1)^(1+1)-1-1-1-1-1
 -994:  64: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1+1+1
 -995:  62: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1+1
 -996:  60: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1+1
 -997:  58: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1+1
 -998:  56: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)+1
 -999:  54: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)
-1000:  56: -((1+1+1+1+1+1)^(1+1)-1-1-1-1)^(1+1)+(1+1+1+1+1)^(1+1)-1

    1:   1: 1
    2:   3: 1+1
    3:   5: 1+1+1
    4:   7: 1+1+1+1
    5:   9: 1+1+1+1+1
    6:  11: 1+1+1+1+1+1
    7:  13: 1+1+1+1+1+1+1
    8:  15: 1+1+1+1+1+1+1+1
    9:  13: (1+1+1)^(1+1)
   10:  15: (1+1+1)^(1+1)+1

    0:   1: 0
   -1:   2: -1
   -2:   4: -1-1
   -3:   6: -1-1-1
   -4:   8: -1-1-1-1
   -5:  10: -1-1-1-1-1
   -6:  12: -1-1-1-1-1-1
   -7:  14: -1-1-1-1-1-1-1
   -8:  16: -1-1-1-1-1-1-1-1
   -9:  14: -(1+1+1)^(1+1)
  -10:  16: -(1+1+1)^(1+1)-1

Gördüğünüz gibi, negatif olanlar her zaman birer bayttır (öncü -) karşılık gelen pozitiflerden daha uzundur.

Temel fikir önceki programla aynıdır: hedef numaramızın yanında bir kare bulun ve kökenini ve kalanını tekrar tekrar temsil edin. Ama şimdi karemizin hedef sayıdan biraz daha büyük olmasına izin veriyoruz, bu da geri kalanı negatif yapıyor. ( +0.5Algoritmayı düzeltmek için farklı bir sabit olarak değiştirilebilir, ancak buradaki zaten optimum olanı vurdum - hem 0,4 hem de 0,6 daha kötü sonuçlar veriyor.)

Negatif değerleri negatif yapmak için (ve aksi takdirde pozitif olanlarla aynı yapıya sahip olmak için, operatörü geçeriz) sign özyinelemeli fonksiyonumuza geçiririz p- ya "+"da "-".) Bunu önemsiz durumlarda (yani n <9) marangoz için de kullanabiliriz. Kalan pozitifse geri kalanı ise, kalan ise tersi işaretini kullanın.

proofİşlev kolları (0 özel bir durum olan) bir başlangıç işareti, pfonksiyon yineleme ile, fiili çalışma yapar.

Ceylon 1.2 için üçüncü versiyon

import ceylon.language { S=String, I=Integer,e=expand }

// output a base-proof Ceylon expression for an integer
// (i.e. using only 0 and 1 as digits).
//
// Question: http://codegolf.stackexchange.com/q/58084/2338
// My Answer:  http://codegolf.stackexchange.com/a/58122/2338
//
// The goal is to produce an expression as short as possible, with
// the code staying under 512 bytes in length.
//
// This approach is to represent a positive integer as a square
// of a positive integer plus some remainder (where the remainder
// can be negative), and for negative integers replace the + on the
// outer level by -.

S q(I n) =>
        n == 0 then "0"
        else (n < 0 then "-" + p(-n, "-")
            else p(n, "+"));

// cache for values of p
variable Map<[I, S],S> c = map { };

// Transforms a positive number into a base-proof term, using
// the given sign for the summation on the outer level.
S p(I n, S s) {
    S v =
    // look into the cache
            c[[n, s]] else (
        // hard-code small numbers
        n < 8 then s.join([1].repeat(n)))
            else
    // do the complicated stuff
    (let (a = "+-".replace(s,""))
            e(e {
                    for (x in 2..8) // try these exponents
                        let (l = (n ^ (1.0 / x)).integer) // \[ sqrt[exp]{n} \] in LaTeX
                            { for (r in l:2) // lowerRoot, lowerRoot + 1
                                    if (r > 1)
                                        let (w = r ^ x)
                                            { if (w-n < n) // avoid recursion to larger or same number
                                                    // format the string as  r^x + (n-w)
                                                    "(" + p(r, "+") + ")^(" + p(x, "+") + ")" +
                                                            (w < n then s + p(n - w, s)
                                                                else (n < w then a + p(w - n, a)
                                                                    else ""))
                                            } } })
            // and now find the shortest formatted string
                .reduce<S>((x, y) => x.size < y.size then x else y))
    // this should never happen, but we can't tell the compiler
    // that at least some of the iterables are non-empty due to the if clause.
            else "";

    // this builds a new cache in each step – quite wasteful,
    // as this also happens when the value was found in the cache,
    // but we don't have more characters remaining.
    //// c = map { [n, s] -> v, *c };
    ///better way:
     c = [n,s] in c then c else map{[n,s]->v, *c}; 
    return v;
}

Golf edilmiş sürüm (yani yorumlar ve boşluk kaldırıldı) tam olarak 509 bayt kodunda üstte yayınlandı.

Bu, ikinci versiyondakiyle aynı temel prensibi kullanır, fakat sadece kareler yerine, daha yüksek sayı güçleri kullanmaya çalışır (2'den 8'e kadar olan üsleri dener) ve en kısa sonucu kullanır. Ayrıca sonuçları önbelleğe alır, aksi halde bu birçok özyinelemeli çağrı ile daha büyük sayılar için kabul edilemez derecede yavaş olacaktır.

puanlama:

Total positive: 36622
Average positive: 36.622
Total negative: 37623
Average negative: 37.58541458541458
With bonus:33.826873126873124
Overall score: 35.22443656343656

Ortadaki büyük girintili yapı, iç içe geçmiş bir let ifadesi olan iç içe geçmiş üç iç içe geçmiş kavramadır. Bunlar daha sonra genişleme işlevini iki kez kullanmaktan çekinmez ve reduceişlev bu dizgelerin en kısa olanını bulur.

Bunu tek bir anlamada yapabilmek için bir özellik isteği sundum.

Kavrama içinde, kökünden r, üsten xve geriye kalandan ( n-wveya w-n) bir ip yaratıyoruz .

letEkspresyonu ve mapişlev Seylan'da 1.2 yenidir. mapyerini olabilirdi HashMap(Ben her yeni giriş yeni bir harita oluşturmak olmaz gibi muhtemelen daha hızlı bile olurdu rağmen, ithalat için daha fazla karakter gerekli olurdu). letGibi ifadeler let (w = r ^ x)kullanılması yararlı yerini almış ifgibi maddesini if(exists w = true then r ^ x)(ve sonra duyduğum iki olmazdı expand511 izin bayt içine uydurma değil, ya aramaları), ancak bu yine de biraz daha uzun olacaktır.

Burada yukarıda seçilenlere karşılık gelen örnek çıktılar, gerçekten küçük sayılar dışında hepsi daha kısadır:

   27:  15: (1+1+1)^(1+1+1)
   28:  17: (1+1+1)^(1+1+1)+1
   29:  19: (1+1+1)^(1+1+1)+1+1
   30:  21: (1+1)^(1+1+1+1+1)-1-1
   31:  19: (1+1)^(1+1+1+1+1)-1
   32:  17: (1+1)^(1+1+1+1+1)
   33:  19: (1+1)^(1+1+1+1+1)+1
   34:  21: (1+1)^(1+1+1+1+1)+1+1

  -27:  16: -(1+1+1)^(1+1+1)
  -28:  18: -(1+1+1)^(1+1+1)-1
  -29:  20: -(1+1+1)^(1+1+1)-1-1
  -30:  22: -(1+1)^(1+1+1+1+1)+1+1
  -31:  20: -(1+1)^(1+1+1+1+1)+1
  -32:  18: -(1+1)^(1+1+1+1+1)
  -33:  20: -(1+1)^(1+1+1+1+1)-1
  -34:  22: -(1+1)^(1+1+1+1+1)-1-1

  993:  39: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1-1-1
  994:  37: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1-1
  995:  35: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1-1
  996:  33: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1-1
  997:  31: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1-1
  998:  29: ((1+1+1)^(1+1)+1)^(1+1+1)-1-1
  999:  27: ((1+1+1)^(1+1)+1)^(1+1+1)-1
 1000:  25: ((1+1+1)^(1+1)+1)^(1+1+1)

 -993:  40: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1+1+1
 -994:  38: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1+1
 -995:  36: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1+1
 -996:  34: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1+1
 -997:  32: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1+1
 -998:  30: -((1+1+1)^(1+1)+1)^(1+1+1)+1+1
 -999:  28: -((1+1+1)^(1+1)+1)^(1+1+1)+1
-1000:  26: -((1+1+1)^(1+1)+1)^(1+1+1)

    1:   1: 1
    2:   3: 1+1
    3:   5: 1+1+1
    4:   7: 1+1+1+1
    5:   9: 1+1+1+1+1
    6:  11: 1+1+1+1+1+1
    7:  13: 1+1+1+1+1+1+1
    8:  13: (1+1)^(1+1+1)
    9:  13: (1+1+1)^(1+1)
   10:  15: (1+1+1)^(1+1)+1

    0:   1: 0
   -1:   2: -1
   -2:   4: -1-1
   -3:   6: -1-1-1
   -4:   8: -1-1-1-1
   -5:  10: -1-1-1-1-1
   -6:  12: -1-1-1-1-1-1
   -7:  14: -1-1-1-1-1-1-1
   -8:  14: -(1+1)^(1+1+1)
   -9:  14: -(1+1+1)^(1+1)
  -10:  16: -(1+1+1)^(1+1)-1

Örneğin, şimdi 1000 = (6 ^ 2-4) ^ 2-5 ^ 2 + 1 yerine 1000 = (3 ^ 2 + 1) ^ 3 değerine sahibiz.


Yanlışlıkla program kısıtlamasını 256 byte olarak hatırladım ... 512 de biraz daha yapılabilir. Bunu sonra deneyeceğim.
Paŭlo Ebermann 16:15

Hayır, yazıyor less than 512. Sou bir max kullanabilirsiniz. 511 bayt;)
mınxomaτ

Bu dili nasıl hiç duymadım?!? : O Ama cidden, mükemmel bir açıklama! Başkalarının cevaplarında kullandıkları teknikleri anlamayı seviyorum. +1
ETHProductions

@ETHproductions Ben sadece burada iki hafta önce burada sitede okudum ve onu sevmeye başladı. Bu yüzden daha iyi tanımak için, burada Ceylon'u kullanarak soruları cevaplamaya çalışıyorum.
Paŭlo Ebermann 17:15

2

Yakut / DC, 20,296 18,414 16,968

Dinamik program! Bir dc komutu verilen, yeni bir ifade ve bu ifadenin sayısal değerini döndüren işlevlerin listesini tanımlar. Ardından, 1önceden tanımlanmış olandan başlayarak, istenen değere kadar ve ulaşılabilir tüm değerlerin bir listesini oluşturur.

Düzenle:

N-1 için bir fonksiyon eklendi ve algoritmayı çoklu geçişlerden geçirdi. Stabilize etmek için 7 geçişe ihtiyacı var gibi görünüyor. 512 bayt içinde kalabilmek için bazı değişken isimlerini kısaltmak zorunda kaldık.

düzenleme 2:

Ben varken n (n-1) , n (n + 1) ve n ^ 3 için işlevler eklendi . Tam olarak 512 bayta inerek kodu biraz daha kısalttı.

N = gets.to_i

fns = [
  ->(n,s){[n-1,   s+'1-']},
  ->(n,s){[n+1,   s+'1+']},
  ->(n,s){[n*2,   s+'d+']},
  ->(n,s){[n*3,   s+'dd++']},
  ->(n,s){[n*~-n, s+'d1-*']},
  ->(n,s){[n*n,   s+'d*']},
  ->(n,s){[n*-~n, s+'d1+*']},
  ->(n,s){[n*n*n, s+'dd**']},
]

lst = []*(N+1)
lst[0..2] = %w[0 1 1d+]

loop do
  prev = lst.dup

  (1..N).each do |n|
    fns.each do |f|
      m,s = f[n, lst[n]]
      lst[m] = s if m <= N && (lst[m].nil? || lst[m].size > s.size)
    end
  end

  break if lst == prev
end

puts lst[N]

Üretilen sayılar:

Çıktı tamamen beş farklı karakterden oluşur: 1yığındaki 1 değerini iter; dyığının tepesini çoğaltır; +, -ve * iki üst değeri açar ve sırasıyla toplamlarını, farklılıklarını ve ürünlerini iter. Üretilen her ifade, yürütmeden sonra yığına yalnızca bir değer ekler.

   1: 1
   2: 1d+
   3: 1dd++
   4: 1d+d+
   5: 1d+d+1+
   6: 1d+dd++
   7: 1d+dd++1+
   8: 1d+dd**
   9: 1dd++d*
  10: 1d+d+1+d+
  11: 1d+d+1+d+1+
  12: 1dd++d1+*
  13: 1dd++d1+*1+
  14: 1d+dd++1+d+
  15: 1d+d+d*1-
  16: 1d+d+d*
  17: 1d+d+d*1+
  18: 1dd++d*d+
  19: 1dd++d*d+1+
  20: 1d+d+d1+*
  21: 1d+d+d1+*1+
  22: 1d+d+1+d+1+d+
  23: 1d+dd**dd++1-
  24: 1d+dd**dd++
  25: 1d+d+1+d*

...

 989: 1d+d+d*d+d1-*1-1-1-
 990: 1d+d+d*d+d1-*1-1-
 991: 1d+d+d*d+d1-*1-
 992: 1d+d+d*d+d1-*
 993: 1d+d+d*d+d1-*1+
 994: 1d+d+d*d+d1-*1+1+
 995: 1d+d+d*d+d1-*1+1+1+
 996: 1d+d+1+dd**d+1-d+d+
 997: 1d+d+1+d+dd**1-1-1-
 998: 1d+d+1+d+dd**1-1-
 999: 1d+d+1+d+dd**1-
1000: 1d+d+1+d+dd**

1
Oldukça iyi, şimdiye kadar z80 makine kodu dışında her şeyi yenmek (Dennis'in CJam'ı bile!). -Bayt sayısı içinde kalırken bir operatöre ekleyebileceğinizi düşünüyor musunuz ?
ETHProductions

@ETHproductions Bu nasıl? ;) Şimdi negatif sayıları eklemek de zor olmamalı.
daniero 19:15

0

Python 2.6, 78.069 - 66.265 puan

Değeri olana cevabımı göndererek (bu durumda çok fazla değil ... ... ama bu meydan okuma için çıktıyı bit-kaydırılmış değerlerin bir toplamı olarak düşünmenin yeterli olmadığını, rakamların dikkate alınmadığını saymak yeterli değil. 0 veya 1 dışında çıktıda görünebilir). Daha sonra farklı bir çıktı üretme yöntemiyle geri gelebilirim.

Kodun kendisi çok uzun değil (176 karakter):

def f(a):return'+'.join(('(1<<%s)'%['0','+'.join('1'*x)][x>0]).replace('(1<<0)','1')for x in[i for i,e in enumerate(bin(a)[::-1][:-2])if int(e)])
print"".join(f(int(input())))

Doğru ancak ayrıntılı çıktı üretir:

17
1+(1<<1+1+1+1)

800
(1<<1+1+1+1+1)+(1<<1+1+1+1+1+1+1+1)+(1<<1+1+1+1+1+1+1+1+1)

Puanı hesaplayan pasajı:

def f(a):return'+'.join(('(1<<%s)'%['0','+'.join('1'*x)][x>0]).replace('(1<<0)','1')for x in[i for i,e in enumerate(bin(a)[::-1][:-2])if int(e)])
print sum(len("".join(f(i)))for i in range(1000))
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.