JavaScript'te golf oynamak için ipuçları


133

JavaScript'te golf oynamak için hangi genel ipuçlarınız var? Genel olarak golf problemlerini kodlamak için uygulanabilecek fikirleri arıyorum, en azından biraz JavaScript'e özgü (örneğin, "yorumları kaldır" bir cevap değil).

Not: Ayrıca bkz . ECMAScript 6 ve daha üstü için Golf İpuçları


Aslında merak ediyordum, değişkenleri global (tasarruflar var) içine koyma izni var mı? JavaScript golf kodu bir işlev mi olmalı yoksa doğrudan bir şey mi çıktı? Dürüst olmak gerekirse, bunun çok fazla fark yaratabileceğini düşünüyorum.
pimvdb

1
@primvdb: Buna izin verilir, ancak dikkatli olmalısınız, çünkü bir işlev birden çok kez çağrılırsa ve genel değişkenleri değiştiriyorsa veya özyinelemeli bir işlevse yan etkilere neden olabilir.
mellamokb

Yanıtlar:


108

Döngüler İçin Süslü

Döngü standardını standart olmayan yollarla kullanabilirsiniz

for ( a; b; c )

esasen şuna eşittir:

a;
while ( b )
{
  ...
  c;
}

Bu yüzden iyi bir hile kodunuzu bir whiledöngü ile yazmak ve bir döngü içindeki a,b,cparçalara forbölmektir.

Birkaç örnek Yazdığım :

for(x=y=n;!z;x--,y++)z=i(x)?x:i(y)?y:0
for(a=b=1;b<n;c=a+b,a=b,b=c);

Setlerinizi zincirleyin

Birden fazla değer başlatıyor veya sıfırlıyorsanız, değeri gereken tüm değişkenlere zincirleyin:

a=b=1;

Örtük Döküm

Tiplerinizi kontrol etmeyin, sadece oldukları gibi kullanın. parseInt()maliyet 10karakterleri. Bir dizgiden çıkmanız gerekiyorsa, yaratıcı olun:

a='30';
b='10';
c = a + b; //failure
c = parseInt(a) + parseInt(b) //too long

c = -(-a-b); //try these
c = ~~a+~~b;
c = +a+ +b;
c = a- -b;

Noktalı virgüllerden kaçının

JavaScript'in otomatik yarı-kolon eklemesi vardır. Sık sık ve iyi kullanın.

Tek gömlekleri

Tek satırlara veya parametrelere olabildiğince vurarak desteklerden tasarruf edin:

a( realParam1, realParam2, fizz='buzz' )

Artış / Azaltma operatörleri

a = a - 1;
foo(a);

ve

foo(a);
a = a - 1;

kolayca yeniden yazılabilir

foo(--a);

ve

foo(a--);

sırasıyla.

Global bağlamda kullanın thisveya selfyerinewindow

açıklayıcı 2 karakter tasarruf.

Mülkiyet erişimini tekrarlamak için parantez notasyonu kullanın

Bu kesinlikle özellik adı uzunluğu ve erişim sayısı arasında dengeleyici bir eylemdir. Bunun yerine çağıran a.longFunctionName()iki kez nokta gösterimi ile, bu adı kaydetmek ve ayraç aracılığı işlevi çağırmak için daha kısa:

a.longFunctionName(b)
a.longFunctionName(c)
//42

-vs-

a[f='longFunctionName'](b)
a[f](c)
//34

bu özellikle document.getElementByIddüşürülebilen işlevlerde etkilidir d[e].

Not:

Braket notasyonu ile maliyet 6 + name.lengthilk defa karakterdir. Her takip eden erişimin bir 3karakter maliyeti vardır .

Noktalı gösterim için, tüm erişilen maliyetler name.length + 1(+1 .) karakterleridir.

Eğer bu yöntemi kullanın 6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1).

len = özellik adının uzunluğu
i = yararlanmak için minimum erişim

len | i 
========
1   |  
2   |  
3   | 7 
4   | 4 
5   | 3 
6   | 3 
7   | 3 
8+  | 2 

Erişim sayısı birden fazla nesneyi de kapsayabilir. .lengthFarklı dizilerde 4 veya daha fazla kez erişirseniz , dizgeyi tutan aynı değişkeni kullanabilirsiniz 'length'.


5
c = ~~a-~~bolmalı c = ~~a+~~b. Ayrıca, dolaylı olarak |0, örneğin kullanarak tamsayıya da basabilirsiniz Math.random()*6|0.
mellamokb

7
Bir dizeyi unary plus işleci ile bir sayıya zorlamak daha ucuzdur. Eğer ave bstring iseniz, +a+bsayıya dönüştürmek ve bunları eklemek için yapabilirsiniz.
Peter Olson,

8
Yemin ederim bir d- -bgün kodumda kullanacağım ...
John Dvorak

4
+ a + b çalışmıyor (en azından benimki ...) // a = "1", b = "1", + a + b // "11" veriyor
Ocak'ta

2
Eğer aynı nesne üzerinde iki defadan fazla kullanıyorsanız, işlevi tekrarlamak için Array-Access işlevini kullanmak için, işlevi biraz daha kısa olan şey, fonksiyonu a.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender


56

Parantezden kaçınmak için virgül operatörünü kullanın ( C için de geçerlidir ):

if(i<10)m+=5,n-=3;

Onun yerine

if(i<10){m+=5;n-=3}

bir karakter daha uzun.


2
İlk örnek sonunda noktalı virgül gerekli midir?
WJL

4
@wjlafrance: Sadece bir astarın sonundaysa gerekli olmaz.
mellamokb

48

Daha kısa rastgele sayı üretimi

Rasgele bir boole ( 0veya 1) ihtiyacınız varsa :

new Date&1 // equivalent to Math.random()<0.5

Rastgele bir tamsayıya ihtiyacınız varsa 0 <= n < 1337:

new Date%1337 // equivalent to Math.floor(Math.random()*1337))

Bu Date, a'nın bir çağdan beri milisaniyelik miktar olarak dahili olarak JavaScript'te depolanması nedeniyle çalışır , bu nedenle tamsayı matematiği yapmaya çalıştığınızda new Datezorlanır 123somebignumber456.

Tabii ki, bu "rastgele" sayılar gerçekten de rasgele olmayacak, özellikle hızlı bir şekilde art arda birden çok kez çağırırsanız, aklınızda bulundurun.


1
Sadece bu cevabı hatırlarken Daha fazla yalancı programcı zamana inanıyor : “21. Yan yana iki tarih nesnesi oluşturursanız, aynı zamanı temsil ederler. (fantastik bir Heisenbug jeneratörü) ” .
Sebastian Simon

39

Anahtar sözcüğü kullanmaktan kaçınmak için hazır bilgi / set nesnesini kullanabilirsiniz function.

var obj = {
  get f(){
    console.log("just accessing this variable runs this code");
    return "this is actually a function";
  },
  set f(v){
    console.log("you can do whatever you want in here, passed: " + v);
  }
};

1 && obj.f; // runs obj.[[get f]]
obj.f = Infinity; // runs obj.[[set f]](Infinity)

alıcı / ayarlayıcı kısmı gerçekten yardımcı oldu. thx
gion_13 14.03.2012

1
Aslında, daha iyi bir nesne yöntemi, sadece <= 2 kez kullanırsanız. Öte yandan, ok işlevleri neredeyse aynı amaca hizmet ettikleri için karakterleri azaltmada çok daha iyidir ve sınıflar golf kodunda nadiren kullanışlıdır.
Isiah Meadows,

eğer destek önemliyse, ok işlevleri fx'te desteklenmez. ie11
Jim Wolff

35

Bu daha az bilinen ve daha az kullanılan ancak doğru durumda kullanılırsa etkileyici olabilir. Argüman almayan ve çağrıldığında her zaman farklı bir sayı döndüren bir işlev düşünün; döndürülen sayı bir hesaplamada kullanılır:

var a = [ 
    Math.random()*12|0,
    Math.random()*11|0,
    Math.random()*10|0,
    /* etc... */ 
];

Normalde, tek harfli bir değişken adı kullanarak bu işlevi kısaltabilirsiniz:

var r=Math.random,a=[r()*12|0,r()*11|0,r()*10|0,r()*9|0,r()*8|0,r()*7|0,r()*6|0,r()*5|0];

Uzunluğu azaltmak için daha iyi bir yol kötüye kullanmaktır valueOf, bu da her sorgulamada 2 karakterlik bir tasarruf sağlar. Fonksiyonu 5 defadan fazla ararsanız kullanışlıdır:

var r={valueOf:Math.random},a=[r*12|0,r*11|0,r*10|0,r*9|0r*8|0,r*7|0,r*6|0,r*5|0];

8
Veya şunlardan herhangi birini istediğiniz gibi yapabilirsiniz: let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)veya let a=Array(7).map((_,i)=>i*Math.random()|0+5)sırasıyla kaydedilmiş 36 veya 42 bayt.
Isiah Meadows

Değiştirmek r()veya kısaltmak mümkün mü ?
NiCk Newman,

3
r={valueOf:Math.random}Bu sadece bir dahi: D
ETHproductions 22:06

1
@Isiah, evet, bunu şimdi yapabilirsiniz :-D
Andy E

32

Kısa devre operatörlerinden yararlanmak

Uzun ififadeler yerine ya da üçlü operatörleri kullanmak yerine kodunuzu kullanabilir &&ve ||kısaltabilirsiniz. Örneğin:

var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);

return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;

olabilir

var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);

return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

||Operatör sıklıkla varsayılan ayarı için bu şekilde kullanılır:

evt = evt || window.event;

Bu yazıyla aynı

if (!evt)
    evt = window.event;

Dizi kullanarak tekrarlı dizeler oluşturma

Belirli bir karakter uzun bir dize başlatmak istiyorsanız, bunu n + 1 uzunluğunda bir dizi oluşturarak yapabilirsiniz ; burada n , karakteri tekrarlamak istediğiniz sayıdır:

// Create a string with 30 spaces
str = "                              ";

// or
str = Array(31).join(" ");

İp ne kadar büyük olursa tasarruf o kadar büyük olur.

Ayrıştırma numaraları

Bir sayı türüne yalnızca bir sayı olan bir dize türünü birleştirirken veya yerine birleştirme yaparken kullanın +ve ~işleçler :parseFloat()parseInt()

var num = "12.6";
parseFloat(num) === +num;  // + is 10 characters shorter than parseFloat()

var num2 = "12"
parseInt(num2) === +num2;   // + is 8 characters shorter than parseInt()

var num3 = "12.6"
parseInt(num3) === ~~num3;  // ~~ is 7 characters shorter than parseInt()

var num4 = "12.6"
parseInt(num4) === num4|0;  // |0 is 7 characters shorter than parseInt()

Dikkatli olun, diğer türler bu operatörlerle birleştirilebilir (örneğin trueolur 1), boş bir dize veya sadece beyaz boşluk içeren bir dize olur 0. Bununla birlikte, bazı durumlarda bu yararlı olabilir.


6
Dizi kullanarak tekrarlı dizeler oluşturmak için +1 - bunun hakkında düşünmemiştim.
mellamokb

4
Tekrarlayan dizeler oluşturmak için ES6'da kullanabilirsinizstr.repeat(count)
Oriol

26

Değişken ilklendirmeyi kullanıcı girişi için bilgi istemi () çağrısına sokun

n=prompt(i=5);     // sets i=5 at the same time as getting user input

kullanmak yerine

n=prompt();i=5;

Yan etki olarak, 1 karakter kaydedilirken bilgi istemi penceresinde giriş değerini görüntüler.


12
Bu, bağımsız değişkenleri kabul etmeyen herhangi bir işleve de uygulanabilir.
Casey Chu,

3
İşlev bağımsız değişkenleri kabul ettiğinde bile [1,2,3].join('',i=5), bir çift teli kaydettiği durumlarda olduğu gibi faydalı olabilir .
DocMax

3
@DocMax: Bunun için virgül operatörünü kullanabilirsiniz - i=5,[1,2,3].join().
Konrad Borowski

@GlitchMr: Yapabilirim, ancak karakter kaydetmiyor. Çoğu zaman daha temiz olacağına katılıyorum. Şu an bir tanesini bulamamama rağmen siparişimin bir karakter kurtaracağı durumlar olabileceğini düşünüyorum (ve yanlış da olabilirim).
DocMax

@DocMax Yalnızca ASI'den yararlanıyorsanız.
Isiah Meadows,

24

Döngüler için yuvalanmış birleştirme:

// before:
for(i=5;i--;)for(j=5;j--;)dosomething(i,j)

// after:
for(i=25;i--;)dosomething(0|i/5,i%5)

i/ İçin farklı değerlere sahip örnek j:

// before:
for(i=4;i--;)for(j=7;j--;)dosomething(i,j)

// after:
for(i=28;i--;)dosomething(0|i/7,i%7)

(A değiştirdim) küçük bir yazım hatası, ama çok zekice! Bunun sadece aynı uzunlukta iç içe döngüler üzerinde çalışacağını unutmayın (yanılmıyorsam).
Camilo Martin,

1
@CamiloMartin Hayır, ilmeklerin eşit uzunlukta olmaları gerekmez. Elde edilen yineleme sayısı şudur i*jve bölme / modül operatörleri ive j.
sessiz

@ user113215 Haklısın, harika! :) Bir örnek eklemek için cevabı değiştirdim.
Camilo Martin

23

Unicode kısayolları

Büyük bir golf mücadelesinde yerleşik bir cehennem kullanıyorsanız, her mülkü bir karakter eşdeğeri olarak kullanabilirsiniz:

[Math,Number,S=String,Array].map(b=>
    Object.getOwnPropertyNames(b).map((p,i)=>
        b.prototype[S.fromCharCode(i+248)]=b[p]
    )
)

Yukarıdaki kodu yürüttükten sonra şu şekilde kullanabilirsiniz:
"foo".Č(/.*/,'bar') // replaces foo with bar

Bu, 118 bayta mal olduğundan, belirli durumlarda yararlı olmayabilir

Tarayıcıya bağlı olabilir ve with(Array){join(foo),...}değişkenlerin kullanılan özellikler olarak tanımlanmasından daha kısa mı yoksa en az mı olduğundan emin değilim with(Array){j=join,m=map...}, ancak yine de bahsetmeye değer.

    Math        Number              String              Array

ø   toSource    prototype           prototype           prototype
ù   abs         NaN                 quote               join
ú   acos        POSITIVE_INFINITY   substring           reverse
û   asin        NEGATIVE_INFINITY   toLowerCase         sort
ü   atan        MAX_VALUE           toUpperCase         push
ý   atan2       MIN_VALUE           charAt              pop
þ   ceil        MAX_SAFE_INTEGER    charCodeAt          shift
ÿ   clz32       MIN_SAFE_INTEGER    contains            unshift
Ā   cos         EPSILON             indexOf             splice
ā   exp         isFinite            lastIndexOf         concat
Ă   floor       isInteger           startsWith          slice
ă   imul        isNaN               endsWith            filter
Ą   fround      toInteger           trim                isArray
ą   log         parseFloat          trimLeft            lastIndexOf
Ć   max         parseInt            trimRight           indexOf
ć   min         length              toLocaleLowerCase   forEach
Ĉ   pow         name                toLocaleUpperCase   map
ĉ   random      arguments           normalize           every
Ċ   round       caller              match               some
ċ   sin                             search              reduce
Č   sqrt                            replace             reduceRight
č   tan                             split   
Ď   log10                           substr  
ď   log2                            concat  
Đ   log1p                           slice   
đ   expm1                           fromCharCode    
Ē   cosh                            fromCodePoint   
ē   sinh                            localeCompare   
Ĕ   tanh                            length  
ĕ   acosh                           name    
Ė   asinh                           arguments   
ė   atanh                           caller  
Ę   hypot           
ę   trunc           
Ě   sign            
ě   cbrt            
Ĝ   E           
ĝ   LOG2E           
Ğ   LOG10E          
ğ   LN2         
Ġ   LN10            
ġ   PI          
Ģ   SQRT2           
ģ   SQRT1_2         

Google chrome kullanıyorum ve bunların hepsi tanımsız veriyor.
SuperJedi224

O zamanlar çok firefox olmalı. Rahatsızlıktan dolayı özür dileriz.
bebe,

Neden bütün bunlar özel karakterler? Neden sadece yazdırılabilir ASCII kullanmıyorsunuz? (yazmak daha kolay, daha güvenilir ve golf
oynamak

Bu gerçekten işe yaramıyor Mathçünkü bir .prototypeözelliği yok. Kaldırarak Math, hepsini tek baytlık harflere atayan 114 baytlık bir snippet'e bırakmayı başardım. Burada bulabilirsiniz .
ETHProductions,

1
Ayrıca, tüm bu özellikleri , her biri ISO-8859-1 kodlamasında (JS'nin desteklediği) her biri 1 bayt olan À- aralığa taşıma pahasına 106 bayta golf oynayabilirsiniz ÿ. Firefox 50’de bu ne yazık ki bu .localeCompareyöntemi ortaya koyuyor ×, ancak bu genellikle bir sorun olmamalı. kaynak
ETHproductions 21

22

Bir whiledöngüyü bir döngüye dönüştürmek forgenellikle eşdeğerdir:

while(i--);
for(;i--;);

Ancak ikinci formda değişken başlatma birleştirilmiş olabilir:

i=10;while(i--);
for(i=10;i--;);

İkinci formun ilk formdan daha kısa bir karakter olduğuna dikkat edin.


6
Veya daha da iyisi, sadece döngüler için kullanın. Gerçekten bir for döngüsü kullandığımda yaşadığım kadarıyla daha büyük kodlarla sonuçlanmıyor.
Isiah Meadows

22

İstisnai kötüye kullanma

string / karakter değişmezlerinin yasaklanması durumunda, try catch bloğunu kullanabilirsiniz:

try{something0}catch(e){str=e.message.split(0)[0]}

şimdi streşittir"something"

daha fazla dizeye ihtiyaç duyulursa, bir sayı ile zincirleme yapabilirsiniz (örneğin, sıfırlar)

try{something0foo0bar0}catch(e){arr=e.message.split(0)}

şimdi arreşittir["something", "foo", "bar", " is not defined"]


18

Bir değişkeni 1bir döngünün her yinelemesinde (örneğin, bir iç döngü için bir dış döngüde bir değişkeni sıfırlamak) başlatıyorsanız, aşağıdaki gibi ( benim cevabımdan bu soruya ):

for(j=n-2;p=1,j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;
          ^^^^

Böyle bir durumun sonucu beri j++<=nolduğu 1(yanlış olduğunda, döngü artık olsun yürütme durdurmak ve çünkü) gerçek, sadece değişkene doğrudan koşul atayabilirsiniz zaman:

for(j=n-2;p=j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;
          ^^^^^^^^

Bu yöntemi kullanarak genellikle 2 karakter kaydedebilirsiniz . @ugorenBu cevaba yorumlarda fikir için Saygılar .


Başka bir örnek olarak, ben de bu hile uygulanan burada Cevabıma ifadesiyle w=r=++c<S.length4 karakterden toplam tasarruf döngü benim dış içinde.



17

NaN'i kontrol etmeniz gerekiyorsa, kullanmayın isNaN(x), fakat x!=xdaha kısa olan ve aynı zamanda çalışan, kullanmayın.

if(isNaN(x)){
if(x!=x){

Bunun yalnızca işe yaradığını typeof(x) === "number"; örneğin bir dize ise, isNaN("string")döndürür true, ancak "string" != "string"döndürür false. Bunu işaret ettiği için Cyoce'ye teşekkürler!


2
Bu tuhaflığın dahice kullanımı. +1
ETHProductions

Uyarı: Bunlar her zaman eşdeğer değildir: isNaN("string")döner true, oysa "string"!="string"döner false(açıkça)
Cyoce

@Cyoce İyi nokta, teşekkürler! Cevabımı düzenledim.
ProgramFOX

Açıkça if(!x){tespit ediyorsanız , çoğu durumda, hatta gidebilirsiniz NaN.
Hohmannfan

1
Sayıya çevirmek x, +x!=+xeşdeğer isNaN(x), ancak yine de 2 karakterden daha kısa olmasını sağlar. Sonra +"string"!=+"string"doğru döner.
Tomas Langkaas,

15

Dizi toplamı / ürün / bölüm

ES5 : 17 bayt

eval(a.join('+'))

ES6 : 15 bayt

eval(a.join`+`)

Tabii ki +, istediğiniz *ürün , örneğin ürün veya /bölüm için takas edebilirsiniz .


14

Bir sayıyı sıfıra döndürmek için bitsel bir işlem kullanın:

// do this
T=Math.random()*6+1|0

// or do this
T=~~(Math.random()*6+1)

(Kaynak: Rastgele zar devrilme )

Operatör önceliği , programınızda hangisinin daha kısa olacağını belirler.


2
Bu, bir dize girişini bir tamsayıya, yani n=prompt()|0.
mellamokb

1
bitwise math.floor ile karşılaştırıldığında da süper hızlı: jsperf.com/floor-vs-bitwise
vsync

@vsync: Garip. Math.floor’un Chrome 11.0.696.77’de yaklaşık iki kat daha hızlı bitmesini sağlıyorum.
mellamokb

çok garip. benim için Chrome'da hem aşağı yukarı hem de daha az aynı hızda ve süper hızlı, ancak FF'de bit yönünde Chrome'dan çok daha hızlı ve Math.floorçok yavaş ... neredeyse kullanmamalıyım.
vsync

Yorumları güncel tutmak için mevcut Fx'te ikisi de hızlı ve eşit. Çevre koduyla karşılaştırıldığında, ilk etapta bir darboğaz olması muhtemel değildir ...
FireFly

14

Döngü Ucu I

Son kullanım 1tarihini değiştirerek, döngü yaparken karakter kaydedebilirsiniz i:

//not so god
for(i=0;i<3;i++){
  alert(i);
}

//best
for(i=0;i<3;){
  alert(i++);
}

Not: ile --de çalışır (ancak sonsuz döngüden kaçınmak için döngüyü buna göre değiştirin)


Döngü Ucu II

Artırma işleci ve değerleriyle oynayarak bir karakteri kaydedebileceğiniz bazı senaryolar vardır:

for(i=0;i++<9;)
for(i=0;++i<10;)

Not: Örneğin ne zaman dikkat etmeniz gerekir 0 to -1. ve 9 to 10, 99 to 100, karakteri kaydetmenin bir yolunu bulana kadar oynayın


13

Kullanım ^yerine !=ya ==bir tam sayıya karşılaştırırken

//x!=3?a:b
  x^3?a:b

//x==3?a:b
  x^3?b:a

Çağrıları yerleşik Math işlevlerine daha kısa ifadelerle değiştirme

//Math.ceil(n)
  n%1?-~n:n

//Math.floor(n)
  ~~n
  0|n

//Math.abs(n)
  n<0?-n:n

//Math.round(n)
  n+.5|0

//Math.min(x,y)
  x<y?x:y

//Math.max(x,y)
  y<x?x:y

2
Alternatif olarak, tamsayılar -yerine basitçe kullanabilirsiniz !=; Örneğin, n!=1?a:beşittirn-1?a:b
vrugtehagel

10

Kayda değer bir şey, bazı durumlarda baytları burada saklamak için bazı durumlarda sıfır yerine bir dize kullanabilmenizdir:

s='';for(i=0;i++<9;)s+=i
for(i=s='';i++<9;)s+=i
// s="123456789", i=10

1
Konsolda "" ++ 'ı denedim, işe yarayıp yaramadığını merak ettim, elbette önce bir değişken olmalı. Teşekkürler!
Vartan

10

Çok basit olanı, öyle olsa bile, hiç kimse bundan bahsetmemişti.

Kullanıyorsanız Math.min()veya Math.max()bunu yaparak 6 karakterden tasarruf edebilirsiniz:

Math.min(a,b)  // 13 chars
a<b?a:b        //  7 chars

Math.max(a,b)
a>b?a:b

10

yuvarlatma

Alternatiflerin Math.floor()gönderildiğini biliyorum , peki ya diğerleri?

Döşeme:

Math.floor(x) //before
0|x           //after

Yuvarlama:

Math.round(x) //before
0|x+.5        //after

Tavan:

Math.ceil(x) //before
x%1?-~x:x    //after - credits to @Tomas Langkaas

1
Tavanını 0|x+1bulmak istediğiniz sayı bir tamsayıysa , sadece 1 ekler. A (çoğunlukla) güvenli bir alternatif 0|x+1-1e9, ancak bu yalnızca üç bayt daha kısa.
ETHProductions

@ETHproductions demek istemiyor musun 0|x+1-1e-9?
Mama Fun Roll

Oops, evet. Gösterdiğin için teşekkürler. (Bazı nedenlerden dolayı yapamam @ (kullanıcı adınız) ...)
ETHproductions

Muhtemelen, çünkü kullanıcı adım karakterleri alt üst oluyor :)
Mama Fun Roll

1
Tavan için x%1?-~x:x(9 karakter) daha iyi bir alternatiftir. Ancak, döşeme alternatifleri gibi 0|xve ~~xsadece pozitif sayılar için çalışır.
Tomas Langkaas,

9

İki sayı arasında seçim yapmak için ternary operatörünü kullandığınızda ve koşullu bir boole veya sayı olduğunda 1 or 0 , bunun yerine matematik işlemlerini yapabilirsiniz:

(x ? num1 : num2) conclusions:

    1)if num1 equals num2, there ARE savings
    2)if num1 is (+1) or (-1) than num2, there ARE savings
    3)if either num1 or num2 equals to 0, there ARE savings
    4)it is MORE LIKELY to find greater savings on num1>num2 instead of num1<num2
    5)in method (*A) and (*B), savings are NOT GUARANTEED

    a)num1>num2
        i)(num1==(num2+1))
            ex1: (x?5:4) to (x+4)
            ex2: (x?8:7) to (x+7)
        ii)num2==0
            ex1: (x?3:0) to (x*3)
            ex2: (x?7:0) to (x*7)
        iii)
            (*A) or (*B) //one might be shorter

    b)num1<num2
        i)((num1+1)==num2)
            ex1: (x?4:5) to (5-x)
            ex2: (x?7:8) to (8-x)
        ii)num1==0
            ex1: (x?0:3) to (!x*3)
            ex2: (x?0:7) to (!x*7)
        iii)
            (*A) or (*B) //one might be shorter

    c)num1==num2
        i)
            ex1: (x?5:5) to (5)
            ex2: (x?-3:-3) to (-3)

    (*A) use ((x*(num1-num2))+num2)
        ex1: (x?8:4)   to ((x*4)+4)
        ex2: (x?4:8)   to ((x*-4)+8)

        ex3: (x?6:-4)  to ((x*10)-4)
        ex4: (x?-4:6)  to ((x*-10)+6)

        ex5: (x?4:-6)  to ((x*10)-6)
        ex6: (x?-6:4)  to ((x*-10)+4)

        ex7: (x?-5:-9) to ((x*4)-9)
        ex8: (x?-9:-5) to ((x*-4)-5)

    (*B) use ((!x*(num2-num1))+num1)
        ex1: (x?8:4)   to ((!x*-4)+8)
        ex2: (x?4:8)   to ((!x*4)+4)

        ex3: (x?6:-4)  to ((!x*-10)+6)
        ex4: (x?-4:6)  to ((!x*10)-4))

        ex5: (x?4:-6)  to ((!x*-10)+4)
        ex6: (x?-6:4)  to ((!x*10)-6)

        ex7: (x?-5:-9) to ((!x*-4)-5)
        ex8: (x?-9:-5) to ((!x*4)-9)

Not: Buna ek olarak, gereksiz kaldırmak gerekir 0-, +0, +-vb

Not 2: Çalışması için olması gerektiği (x) !== (x?1:0)gibi izole edilmiş bir durum vardır . Ancak, bu durumda sadece iyi çalışıyor.xtypeof === "number"(-x)

Not3: Tasarruf bulamazsanız, yalnızca eski olanı kullanın.(x?y:z)

Daha önce, B yönteminin A'yı geçemeyeceğini düşünmüştüm, ancak istisnalar var:

(x?97:100) //original

(-3*x+100)
(3*!x+97)

Bizim için basitleştirmeyi yapan bir github projesi yarattım ( jsFiddle demo )


@ ajax333221 void 0(bir işlev değil, bir anahtar kelimedir) bir değer değildir, sadece döndürür undefined.
Camilo Martin

@CamiloMartin haklısın, ben de şimdi bu cevabın noktasını görüyorum, a
fakat

@ ajax333221 Evet, aslında bana kod golf ile ilgili komik olan şey, en iyi hilelerin çoğunun yalnızca yaptığınız o şey için işe yaraması ve birisinin köşe çözümleriyle bu köşe davalarından birini bulmak için çok akıllıca davranması: D Böylece, yok olması ... yorumları silmek
Camilo Martin

9

tl; dr: ES6 özelliklerini kullanın!

Ok fonksiyonları

Doc: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Örnek:

s = x => x*x
// s = function (x) {
//   return x * x;
// }

Ok fonksiyonları 13: 13 Ekim'de saat 15: 42'de zaten belirtildi . Ama bu for.. ofharika. Bile daha kısa for each.. in.
Manatwork

2
Dizi anlama sözdizimi yanlış gibi görünüyor. Göre belgelerinde Python gibi olmalıdır: b = [s(x) for (x of a)].
Manatwork

@manatwork Yukarıdaki örnekler Traceur's REPL
Florent

Traceur hakkında hiçbir fikrim yok, ancak ECMAScript'ten bahsettiniz ve Mozilla belgelerine işaret ettiniz. Ve dizi kavrayışlarından hiçbiri sizin yazdığınız gibi görünmüyor.
Manat çalışması

1
Dizi kavramaları aslında yarıda çekildi.
Isiah Meadows,

9

Kötüye kullanma hazırlıkları

Son örnek: "c"Büyük harf mi yoksa küçük harf mi olduğunu kontrol edin , harf olmaması önemli değil

"c"<{} // returns false, lower case
"C"<{} // returns true, upper case

3
Bu nasıl çalışıyor?
İnekler

2
@Cowsquack String({})verir "[object Object]".
Dennis,

8

Sayıların boole haline dönüşmesi ile sayıların karşılaştırılması:

Bir şeyin pozitif bir sayıya eşit olup olmadığını kontrol edecekseniz , bu miktarı çıkarabilir ve içindeki ifve elseblokların içindekileri tersine çevirebilirsiniz :

//simplified examples:
x==3?"y":"n"; <- 13 Chars
x-3?"n":"y"; <- 12 Chars

//expanded examples:
if(x==3){
    yes();
}else{
    no();
}

if(x-3){
    no();
}else{
    yes();
}

Ve negatif bir sayıyla (* farklı -1) karşılaştırmak istemeniz durumunda , sadece çıkarmak yerine bu sayıyı eklemeniz yeterlidir .

* Eh, elbette kullanabilirsiniz x.indexOf(y) + 1, ancak özel durumda yerine -1kullanmak için fırsat var ~x.indexOf(y).


8

Yalnızca SpiderMonkey / Firefox veya Rhino motorlarında çalışması gereken bir komut dosyasında birçok karakter kaydetmek için Mozilla'nın standart dışı "ifade kapatma" özelliğini kullanın. Örneğin,

function foo(){return bar}

olur

function foo()bar

Bu tür püf noktaları için Yığın Taşması sayfasına bakınız .


2
Bu Javascript değil. Bu bir UZAY İSTASYONU !!!
Thomas Eding

1
ECMAScript 6 kurtarmaya! ->bar
Ry

5
ECMAScript 6: let foo = () => bar;Yukarıdaki golf kodundan ironik olarak daha kısa.
Isiah Meadows

1
ECMAScript 6: foo=_=>bardaha da kısa.
ETHProductions

bu bağlantı koptu.
45’te Cyoce



8

Bir Boole'ye Dönüştürme :

if(b){b=true}else{b=false}
b=b?true:false;
b=b?!0:!1;
b=!!b;

Not: Bu değişiklikler 0, "", false, null, undefinedve NaNhiç false(başka her şey true)

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.