Wskazówki dotyczące gry w golfa w JavaScript

133

Jakie masz ogólne wskazówki dotyczące gry w golfa w JavaScript? Szukam pomysłów, które można by zastosować do problemów z golfem w kodzie, które są przynajmniej w pewnym stopniu specyficzne dla JavaScript (np. „Usuń komentarze” nie jest odpowiedzią).

Uwaga: Zobacz także Porady dotyczące gry w golfa w ECMAScript 6 i nowszych

mellamokb
źródło
Zastanawiałem się, czy można umieszczać zmienne w globalnych (zapisach var)? I czy kod JavaScript do golfa powinien być funkcją, czy wyświetlać coś bezpośrednio? Szczerze uważam, że może to mieć duże znaczenie.
pimvdb
1
@primvdb: Jest to dozwolone, ale musisz być ostrożny, ponieważ może powodować skutki uboczne, jeśli funkcja jest wywoływana wiele razy i manipuluje zmiennymi globalnymi lub jeśli jest funkcją rekurencyjną.
mellamokb

Odpowiedzi:

108

Fancy For Loops

możesz użyć standardowej pętli dla niestandardowych sposobów

for ( a; b; c )

jest zasadniczo równoważny z:

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

więc dobrą sztuczką jest napisanie kodu w whilepętli, a następnie podzielenie go na a,b,cczęści w forpętli.

Kilka przykładów , które napisałem :

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);

Połącz swoje setery

Jeśli inicjujesz lub resetujesz wiele wartości, połącz wartość ze wszystkimi potrzebnymi zmiennymi:

a=b=1;

Implicit Casting

Nie sprawdzaj typów, po prostu używaj ich takimi, jakie są. parseInt()kosztuje 10postacie. Jeśli chcesz odrzucić ciąg, bądź kreatywny:

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;

Unikaj średników

JavaScript ma automatyczne wstawianie średników. Używaj go często i dobrze.

Jednowarstwowe

Zaoszczędź na nawiasach, umieszczając jak najwięcej w pojedynczych wierszach lub parametrach:

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

Operatory inkrementacji / dekrementacji

a = a - 1;
foo(a);

i

foo(a);
a = a - 1;

można łatwo przepisać jako

foo(--a);

i

foo(a--);

odpowiednio, kolejno.

Użyj thislub selfzamiast windoww kontekście globalnym

oczywiste oszczędności 2 znaków.

Użyj notacji w nawiasach, aby uzyskać dostęp do powtarzanych właściwości

Jest to z pewnością równowaga między długością nazwy nieruchomości a liczbą dostępów. Zamiast wywoływać a.longFunctionName()dwukrotnie notację kropkową, krótsze jest zapisanie nazwy i wywołanie funkcji za pomocą notacji nawiasowej:

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

-vs-

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

jest to szczególnie skuteczne w przypadku funkcji, document.getElementByIdktóre można zredukować do d[e].

Uwaga:

Przy zapisie w nawiasie 6 + name.lengthza pierwszym razem koszt to znaki. Każdy kolejny dostęp ma koszt 3znaków.

W przypadku notacji kropkowej wszystkie wejścia kosztują name.length + 1(+1 dla .) znaków.

Użyj tej metody, jeśli 6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1).

len = długość nazwy właściwości
i = minimalny dostęp, aby skorzystać

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

Liczba dostępów może również obejmować wiele obiektów. Jeśli uzyskujesz dostęp .length4 lub więcej razy na różnych tablicach, możesz użyć tej samej zmiennej przechowującej ciąg 'length'.

zzzzBov
źródło
5
c = ~~a-~~bpowinno być c = ~~a+~~b. Ponadto możesz |0na przykład niejawnie rzutować na liczbę całkowitą, używając Math.random()*6|0.
mellamokb
7
Tańsze jest przymuszanie łańcucha do liczby za pomocą operatora jednoargumentowego plus. Jeśli ai bsą ciągami, możesz zrobić, +a+baby przekonwertować na liczbę i dodać je.
Peter Olson,
8
Przysięgam, że kiedyś użyję d- -bw moim kodzie ...
John Dvorak,
4
+ a + b nie działa (przynajmniej na moim ...) // a = „1”, b = „1”, + a + b // daje „11”
imma
2
W przypadku „Użyj funkcji Array-Access do powtarzania wywołań funkcji”, jeśli używasz funkcji więcej niż dwa razy na tym samym obiekcie , to nieco krótsze jest przypisanie funkcji do nowego elementu, takiego jaka.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender
131

Dzielenie liczbami, aby zapisać cytaty:

"alpha,bravo,charlie".split(",") // before
"alpha0bravo0charlie".split(0)   // after
ajax333221
źródło
2
Działa i użyłem go do wielu cyfr.
Isiah Meadows
12
Lol, to jest naprawdę dość kreatywne
NiCk Newman
9
w ES6 to już nie ma znaczenia, możesz po prostu to zrobić.split`...`
David Archibald
"alpha,bravo,charlie".split`,`
Kamil Kiełczewski
56

Użyj operatora przecinka, aby uniknąć nawiasów klamrowych ( dotyczy również C ):

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

Zamiast

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

który jest o jedną postać dłuższy.

mellamokb
źródło
2
Czy średnik jest konieczny na końcu pierwszej próbki?
wjl
4
@wjlafrance: Nie byłoby wymagane tylko, jeśli znajduje się na końcu jednego linijki.
mellamokb,
48

Krótsze generowanie liczb losowych

Jeśli potrzebujesz losowej wartości logicznej ( 0lub 1):

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

Jeśli potrzebujesz losowej liczby całkowitej 0 <= n < 1337:

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

Działa to, ponieważ a Datejest przechowywane wewnętrznie w JavaScript jako ilość milisekund od epoki, więc new Datejest przymuszane, 123somebignumber456gdy próbujesz wykonać na nim matematykę całkowitą.

Oczywiście te „losowe” liczby naprawdę nie będą tak losowe, zwłaszcza jeśli wywołujesz je wiele razy w krótkich odstępach czasu, więc miej to na uwadze.

Klamka
źródło
1
Właśnie zapamiętałem tę odpowiedź podczas czytania Więcej programiści wierzą w czas : „21. Jeśli utworzysz dwa obiekty daty obok siebie, będą one reprezentować ten sam czas. (fantastyczny generator Heisenbuga) ” .
Sebastian Simon
39

Możesz użyć dosłownej formy obiektu get / set, aby uniknąć używania słowa kluczowego 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)

źródło
część gettera / setera była naprawdę pomocna. thx
gion_13
1
W rzeczywistości jeszcze lepsza jest metoda obiektowa, jeśli użyjesz jej <= 2 razy. Z drugiej strony, funkcje strzałek są znacznie lepsze w wycinaniu znaków, ponieważ służą prawie do tego samego celu, a klasy rzadko są przydatne w kodzie golfowym.
Isiah Meadows
jeśli wsparcie jest ważne, funkcje strzałek nie są obsługiwane w FX. ie11
Jim Wolff
35

Ten jest mniej znany i rzadziej używany, ale może być imponujący, jeśli zostanie użyty we właściwej sytuacji. Rozważ funkcję, która nie przyjmuje argumentów i zawsze zwraca inną liczbę po wywołaniu, a zwrócona liczba zostanie wykorzystana w obliczeniach:

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

Zwykle możesz skrócić tę funkcję, używając jednuliterowej nazwy zmiennej:

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];

Lepszym sposobem na zmniejszenie długości jest nadużycie valueOf, co daje oszczędność 2 znaków na każde wywołanie. Przydatne, jeśli wywołasz funkcję więcej niż 5 razy:

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];
Andy E.
źródło
8
Lub możesz to zrobić w taki sposób, jak jeden z następujących: let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)lub odpowiednio let a=Array(7).map((_,i)=>i*Math.random()|0+5)36 lub 42 bajty.
Isiah Meadows
Czy można go wymienić r()lub skrócić?
NiCk Newman
3
r={valueOf:Math.random}To po prostu genialne: D
ETHprodukcje
1
@Isiah, cóż, możesz to zrobić teraz :-D
Andy E
32

Wykorzystanie operatorów zwarć

Zamiast długich ifinstrukcji lub operatorów trójskładnikowych możesz użyć &&i ||skrócić swój kod. Na przykład:

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

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

może zostać

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

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

||Operator jest często używany w ten sposób do ustawiania wartości domyślnych:

evt = evt || window.event;

To jest tak samo jak pisanie

if (!evt)
    evt = window.event;

Tworzenie powtarzających się ciągów za pomocą Array

Jeśli chcesz zainicjować długi ciąg określonego znaku, możesz to zrobić, tworząc tablicę o długości n + 1 , gdzie n jest liczbą powtórzeń znaku:

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

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

Im większy ciąg, tym większa oszczędność.

Parsowanie liczb

Użyj operatorów +i ~zamiast parseFloat()lub parseInt()podczas koalescencji typu ciągu, który jest tylko liczbą do typu liczby:

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()

Uważaj jednak, inne typy mogą być łączone z tymi operatorami (na przykład truemogłyby stać się 1) pustym łańcuchem lub łańcuchem zawierającym tylko białe znaki 0. Może to jednak być przydatne w pewnych okolicznościach.

Andy E.
źródło
6
+1 za tworzenie powtarzających się ciągów za pomocą macierzy - nie myślałem o tym.
mellamokb
4
Aby utworzyć powtarzające się ciągi, w ES6 możesz użyćstr.repeat(count)
Oriol
26

Podejmij inicjalizację zmiennej do wywołania prompt () w celu uzyskania danych wejściowych od użytkownika

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

zamiast używać

n=prompt();i=5;

Jako efekt uboczny wyświetla wartość wejściową w oknie zachęty, zapisując 1 znak.

mellamokb
źródło
12
Można to również zastosować do dowolnej funkcji, która nie przyjmuje argumentów.
Casey Chu,
3
Nawet gdy funkcja przyjmuje argumenty, może być użyteczna, jak [1,2,3].join('',i=5)w przypadkach, gdy zapisuje parę nawiasów klamrowych.
DocMax
3
@DocMax: Możesz użyć do tego operatora przecinka - i=5,[1,2,3].join().
Konrad Borowski
@GlitchMr: Mógłbym, ale nie zapisuje żadnych znaków. Zgadzam się, że przez większość czasu będzie czystsze. Myślę, że nadal mogą zdarzyć się przypadki, w których moje zamówienie może uratować znak, chociaż nie mogę go teraz wymyślić (i mogę się mylić).
DocMax,
@DocMax Tylko jeśli korzystasz z ASI.
Isiah Meadows
24

Połącz zagnieżdżone dla pętli:

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

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

Przykład z różnymi wartościami i/ j:

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

// after:
for(i=28;i--;)dosomething(0|i/7,i%7)
Kae Verens
źródło
(Zredagowałem) drobną literówkę, ale bardzo sprytną! Zauważ, że będzie to działać tylko na zagnieżdżonych pętlach o tej samej długości (chyba że się mylę).
Camilo Martin,
1
@CamiloMartin Nie, pętle nie muszą być równej długości. Wynikowa liczba iteracji jest taka, i*ja operatory podziału / modułu pobierają indywidualne wartości ii j.
quietmint,
@ user113215 Masz rację, super! :) Zredagowałem odpowiedź, aby podać przykład.
Camilo Martin,
23

Skróty Unicode

Jeśli używasz piekielnie wbudowanej nieruchomości podczas dużego wyzwania golfowego, możesz aliasować każdą właściwość do ekwiwalentu jednej postaci:

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

Po wykonaniu powyższego kodu możesz go użyć w następujący sposób:
"foo".Č(/.*/,'bar') // replaces foo with bar

Kosztuje to 118 bajtów, więc może nie być przydatne w niektórych sytuacjach

Może być zależny od przeglądarki i nie jestem pewien, czy jest krótszy with(Array){join(foo),...}lub definiuje zmienne jako używane właściwości, with(Array){j=join,m=map...}ale nadal warto o tym wspomnieć.

    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         
bebe
źródło
Używam Google Chrome, a wszystkie dają niezdefiniowane.
SuperJedi224
Musi być więc bardzo specyficzny dla firefox. Przepraszam za niedogodności.
bebe
Dlaczego te wszystkie znaki specjalne? Dlaczego nie skorzystać z ASCII do wydruku? (łatwiejszy do
wpisania
To tak naprawdę nie działa, Mathponieważ nie ma .prototypeatrybutu. MathJednak po usunięciu udało mi się zagrać w golfa do fragmentu o długości 114 bajtów, który przypisuje je wszystkim jednobajtowym literom. Możesz go znaleźć tutaj .
ETHproductions
1
Możesz także zagrać w golfa w moim rozwiązaniu do 106 bajtów kosztem przeniesienia wszystkich tych właściwości do zakresu À- ÿktóry jest nadal 1 bajtem w kodowaniu ISO-8859-1 (który obsługuje JS). W przeglądarce Firefox 50 .localeComparemetoda ta jest niestety włączona ×, ale zwykle nie powinno to stanowić problemu. źródło
ETHproductions
22

Przekształcanie whilepętli w forpętlę jest często równoważne:

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

Ale druga forma może mieć zmienną inicjalizację połączoną:

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

Zauważ, że druga forma jest o jeden znak krótsza niż pierwsza forma.

mellamokb
źródło
6
Lub nawet lepiej, po prostu użyj do pętli. Tak naprawdę nie ma przypadku, w którym użycie pętli for daje większy kod, o ile się zorientowałem.
Isiah Meadows
22

Nadużywanie wyjątków

w przypadku, gdy literały łańcuchowe / znakowe są zabronione, możesz użyć bloku try catch:

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

teraz strjest równy"something"

jeśli potrzeba więcej ciągów, możesz połączyć go łańcuchem z liczbą (np. zerami)

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

teraz arrjest równy["something", "foo", "bar", " is not defined"]

bebe
źródło
18

Jeśli inicjujesz zmienną 1w każdej iteracji pętli (na przykład resetujesz zmienną w zewnętrznej pętli dla wewnętrznej pętli), wykonaj następujące czynności (z mojej odpowiedzi na to pytanie ):

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

Ponieważ wynikiem warunku podobnego j++<=njest 1zawsze, gdy jest on prawdziwy, możesz po prostu przypisać warunek bezpośrednio do zmiennej (ponieważ gdy stanie się fałszem, pętla przestanie działać i nie będzie już miała znaczenia):

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

Za pomocą tej metody można zwykle zapisać 2 znaki . Odnosi się @ugorendo pomysłu w komentarzach do tej odpowiedzi.


W innym przykładzie zastosowałem tę sztuczkę do mojej odpowiedzi tutaj z wyrażeniem w=r=++c<S.lengthw mojej zewnętrznej pętli for, oszczędzając w sumie 4 znaki.

mellamokb
źródło
18

Jeśli możesz zaakceptować określone skrypty Spidermonkey (na razie), możesz użyć funkcji strzałek ECMAScript 6 . Zamiast pisać kod jak poniżej.

a.map(function(x){return x*2}) // function? return?

Możesz to skrócić w ten sposób.

a.map(x=>x*2)
Konrad Borowski
źródło
17

Jeśli potrzebujesz sprawdzić NaN, nie używaj isNaN(x), ale używaj x!=x, który jest krótszy i działa.

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

Zauważ, że działa to tylko, jeśli typeof(x) === "number"; jeśli jest to na przykład ciąg znaków, isNaN("string")zwraca true, ale "string" != "string"zwraca false. Dziękujemy Cyoce za zwrócenie na to uwagi!

ProgramFOX
źródło
2
To genialne wykorzystanie tego dziwactwa. +1
ETHprodukcje
Ostrzeżenie: nie zawsze są one równoważne: isNaN("string")zwraca true, natomiast "string"!="string"zwraca false(oczywiście)
Cyoce
@Cyoce Dobra uwaga, dzięki! Zredagowałem swoją odpowiedź.
ProgramFOX
W wielu przypadkach możesz nawet przejść if(!x){, jeśli wykrywasz NaNjawnie.
Hohmannfan,
1
Przesłanie xna liczbę +x!=+xpowoduje, że jest to równoważne isNaN(x), ale wciąż o 2 znaki krótsze. Następnie +"string"!=+"string"zwraca true.
Tomas Langkaas,
15

Suma tablicowa / produkt / iloraz

ES5 : 17 bajtów

eval(a.join('+'))

ES6 : 15 bajtów

eval(a.join`+`)

Oczywiście możesz zamienić +na dowolne, np. *Na produkt lub /iloraz.

George Reith
źródło
14

Użyj operacji bitowej, aby zaokrąglić liczbę w kierunku zera:

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

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

(Źródło: Losowe przechylanie kości )

Priorytet operatora określa, który program będzie krótszy.

Proszę wstać
źródło
2
Można to również wykorzystać do połączenia ciągu wejściowego z liczbą całkowitą, tj n=prompt()|0.
mellamokb
1
bitwise jest również super szybki w porównaniu do math.floor: jsperf.com/floor-vs-bitwise
vsync
@vsync: Weird. W Chrome 11.0.696.77 otrzymuję matematyka.floor dwa razy szybszą niż bitowa.
mellamokb
bardzo dziwne. dla mnie oba są mniej więcej takie same prędkości i super szybkie w Chrome, ale w FF bitowa jest znacznie szybsza niż Chrome i Math.floorjest strasznie powolna .. prawie nie należy używać, powiedziałbym.
vsync
Aby komentarze były aktualne, w bieżącym kursie oba są szybkie i prawie równe. Nie to, że będzie to przede wszystkim wąskie gardło w porównaniu do otaczającego kodu ...
FireFly
14

Looping Tip I

Możesz zapisać 1postać podczas zapętlania, zmieniając iostatnio używane:

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

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

Uwaga: działa --również z (ale odpowiednio zmodyfikuj pętlę, aby uniknąć nieskończonego zapętlenia)


Looping Tip II

Istnieją pewne scenariusze, w których można zapisać jedną postać, grając z operatorem i wartościami:

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

Uwaga: na przykład musisz zwrócić uwagę 0 to -1. i 9 to 10, 99 to 100, więc baw się, aż znajdziesz sposób na uratowanie postaci

ajax333221
źródło
13

Użyj ^zamiast !=lub ==podczas porównywania z liczbą całkowitą

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

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

Zastąp wywołania wbudowanych funkcji matematycznych krótszymi wyrażeniami

//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
Tomas Langkaas
źródło
2
Alternatywnie możesz po prostu użyć -zamiast !=liczb całkowitych; Na przykład n!=1?a:bbyłoby równoważne zn-1?a:b
vrugtehagel
10

Warto zauważyć, że w niektórych przypadkach można użyć ciągu zamiast zera, aby zapisać kilka bajtów tu i tam w pętlach:

s='';for(i=0;i++<9;)s+=i
for(i=s='';i++<9;)s+=i
// s="123456789", i=10
Dom Hastings
źródło
1
Próbowałem wcześniej „” ++ w konsoli, zastanawiając się, czy to zadziała, oczywiście najpierw musi być zmienna. Dzięki!
Vartan,
10

Mimo to bardzo prosty, nikt o tym nie wspominał.

Jeśli używasz Math.min()lub Math.max()możesz zapisać 6 znaków, robiąc to:

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

Math.max(a,b)
a>b?a:b
António Almeida
źródło
10

Zaokrąglanie

Wiem, że Math.floor()opublikowano alternatywy , ale co z pozostałymi?

Posadzka:

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

Zaokrąglanie:

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

Sufit:

Math.ceil(x) //before
x%1?-~x:x    //after - credits to @Tomas Langkaas
Mama Fun Roll
źródło
1
Zauważ, że 0|x+1dodaje 1, jeśli liczba, dla której chcesz znaleźć pułap, jest już liczbą całkowitą. Jest (przeważnie) bezpieczna alternatywa 0|x+1-1e9, ale jest to tylko trzy bajty krótsze.
ETHprodukcje
@ETHproductions nie masz na myśli 0|x+1-1e-9?
Mama Fun Roll
Ups, tak. Dzięki za zwrócenie na to uwagi. (Z jakiegoś powodu nie mogę zrobić @ (twoja nazwa użytkownika) ...)
ETHprodukcje
Prawdopodobnie dlatego, że moje znaki użytkownika są do góry nogami :)
Mama Fun Roll
1
Dla pułapu x%1?-~x:x(9 znaków) jest lepszą alternatywą. Jednak, podobnie jak alternatyw podłogowych 0|xi ~~xto działa tylko dla liczb dodatnich.
Tomas Langkaas,
9

W przypadkach, gdy używasz operatora trójskładnikowego do wybierania między dwiema liczbami , a warunek jest albo wartością logiczną, albo liczbą 1 or 0 , możesz zamiast tego wykonać operacje matematyczne:

(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)

Uwaga: Poza tym, trzeba będzie usunąć zbędne 0-, +0, +-itd.

Uwaga 2: istnieje izolowany przypadek, w którym (x) !== (x?1:0), jak xtrzeba , musi typeof === "number"działać. Jednak w przypadku (-x)tego działa dobrze.

Uwaga 3: Jeśli nie znajdziesz oszczędności, po prostu skorzystaj z pierwszej(x?y:z)

Wcześniej myślałem, że metoda B nigdy nie pokona A, jednak istnieją wyjątki:

(x?97:100) //original

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

Stworzyłem projekt github, który upraszcza dla nas ( demo jsFiddle )

mellamokb
źródło
@ ajax333221 void 0(to nie jest funkcja, ale słowo kluczowe) nie jest wartością, po prostu zwraca undefined.
Camilo Martin,
@CamiloMartin masz rację, również teraz widzę sens w tej odpowiedzi, jednak amusi to być 1 lub 0, aby zadziałało
ajax333221,
@ ajax333221 Tak, tak naprawdę zabawną rzeczą w golfowym kodzie jest dla mnie to, że większość najlepszych trików działa tylko dla tej konkretnej rzeczy, którą robisz, i jest tak sprytnie znaleźć jeden z tych narożnych przypadków z rozwiązaniami narożnymi: D By the sposób, nie musisz usuwać komentarzy ...
Camilo Martin,
9

tl; dr: Użyj funkcji ES6!

Funkcje strzałek

Dokument: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Przykład:

s = x => x*x
// s = function (x) {
//   return x * x;
// }
Florent
źródło
Funkcje strzałek zostały wspomniane już 13 października 13 o 15:42 . Ale to for.. ofjest fajne. Nawet krótszy niż for each.. in.
manatwork
2
Składnia rozumienia tablic wydaje się nieprawidłowa. Według dokumentacji powinno być jak w Pythonie b = [s(x) for (x of a)].
manatwork
@manatwork Powyższe próbki działają dobrze w REPL Traceura
Florent
Nie mam pojęcia o Traceur, ale wspomniałeś o ECMAScript i wskazałeś dokumentację Mozilli. Zrozumienie tablic w żadnym z nich nie wygląda tak, jak to napisałeś.
manatwork
1
Wyrażenia tablicowe zostały właściwie wyciągnięte w połowie.
Isiah Meadows,
9

Nadużycie literałów

Ostatnia próbka: Sprawdź, czy "c"wielkie lub małe litery, nie ma znaczenia, jeśli nie litera

"c"<{} // returns false, lower case
"C"<{} // returns true, upper case
l4m2
źródło
3
Jak to działa?
Krowy szarlatają
2
@Cowsquack String({})daje "[object Object]".
Dennis
8

Jak porównać liczbę za pomocą tego, jak liczby zamieniają się w logiczne:

Jeśli zamierzasz sprawdzić, czy coś jest równe liczbie dodatniej , możesz odjąć tę kwotę i odwrócić to, co było w blokach ifi else:

//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();
}

A jeśli chcesz porównać z liczbą ujemną (* inną niż -1), po prostu musisz dodać tę liczbę zamiast odejmować.

* cóż, z pewnością możesz użyć x.indexOf(y) + 1, ale w szczególnym przypadku -1masz możliwość korzystania ~x.indexOf(y)zamiast niego.

ajax333221
źródło
8

Użyj niestandardowej funkcji „zamykania wyrażeń” Mozilli, aby zapisać wiele znaków w skrypcie, który musi działać tylko w silnikach SpiderMonkey / Firefox lub Rhino. Na przykład,

function foo(){return bar}

staje się

function foo()bar

Zobacz stronę Przepełnienie stosu, aby uzyskać więcej takich sztuczek.

Proszę wstać
źródło
2
To nie jest Javascript. To STACJA KOSMICZNA !!!
Thomas Eding,
1
ECMAScript 6 na ratunek! ->bar
Ry-
5
ECMAScript 6: let foo = () => bar;ironicznie krótszy niż kod w golfa powyżej.
Isiah Meadows
1
ECMAScript 6: foo=_=>barjeszcze krótszy.
ETHprodukcje
ten link jest zepsuty.
Cyoce
8

Zamiast pisać truemożesz użyć !0.

Wolle Vanillebär Lutz
źródło
4
Podobnie !1dla false.
James M. Lay
10
Jeszcze lepiej, używaj 1dla truei 0dla false, chyba że naprawdę potrzebujesz literalnych wartości.
ETHproductions
8

Przekształcanie w wartość logiczną :

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

Uwaga: To zmienia 0, "", false, null, undefinedi NaNna false(wszystko inne true)

ajax333221
źródło