Mẹo chơi gôn trong JavaScript


133

Bạn có mẹo chung nào để chơi golf trong JavaScript? Tôi đang tìm kiếm những ý tưởng có thể được áp dụng cho các vấn đề về mã golf nói chung ít nhất là cụ thể đối với JavaScript (ví dụ: "xóa nhận xét" không phải là một câu trả lời).

Lưu ý: Cũng xem Mẹo chơi gôn trong ECMAScript 6 trở lên


Tôi đã thực sự tự hỏi, nó có được phép đưa các biến trong toàn cầu (tiết kiệm var) không? Và mã golf JavaScript có phải là một hàm hoặc xuất ra một cái gì đó trực tiếp không? Tôi thành thật nghĩ rằng điều này có thể làm cho nhiều sự khác biệt.
pimvdb

1
@primvdb: Được phép, nhưng bạn phải cẩn thận vì nó có thể gây ra tác dụng phụ nếu một hàm được gọi nhiều lần và nó đang thao túng các biến toàn cục hoặc nếu đó là hàm đệ quy.
mellamokb

Câu trả lời:


108

Fancy cho vòng lặp

bạn có thể sử dụng vòng lặp tiêu chuẩn theo những cách không chuẩn

for ( a; b; c )

về cơ bản là tương đương với:

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

Vì vậy, một mẹo hay là viết mã của bạn bằng một whilevòng lặp, và sau đó chia nó thành các a,b,cphần trong một forvòng lặp.

Một vài ví dụ tôi đã viết :

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

Xâu chuỗi setters của bạn

Nếu bạn đang khởi tạo hoặc đặt lại nhiều giá trị, hãy xâu chuỗi giá trị cho tất cả các biến cần:

a=b=1;

Đúc ngầm

Đừng kiểm tra các loại của bạn, chỉ cần sử dụng chúng như chúng là. parseInt()chi phí 10nhân vật. Nếu bạn cần bỏ chuỗi, hãy sáng tạo:

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;

Tránh dấu chấm phẩy

JavaScript có chèn nửa dấu chấm tự động. Sử dụng nó thường xuyên và tốt.

Một lớp lót

Lưu vào dấu ngoặc bằng cách đẩy càng nhiều càng tốt vào các dòng đơn hoặc tham số:

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

Toán tử tăng / giảm

a = a - 1;
foo(a);

foo(a);
a = a - 1;

có thể dễ dàng được viết lại như

foo(--a);

foo(a--);

tương ứng.

Sử dụng thishoặc selfthay vì windowtrong bối cảnh toàn cầu

tự giải thích tiết kiệm 2 ký tự.

Sử dụng ký hiệu ngoặc để truy cập thuộc tính lặp lại

Đây chắc chắn là một hành động cân bằng giữa chiều dài tên tài sản và số lượng truy cập. Thay vì gọi a.longFunctionName()bằng ký hiệu dấu chấm hai lần, sẽ ngắn hơn để lưu tên và gọi hàm thông qua ký hiệu ngoặc:

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

-vs-

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

điều này đặc biệt hiệu quả với các chức năng như document.getElementByIdcó thể được giảm xuống d[e].

Ghi chú:

Với ký hiệu ngoặc, chi phí là 6 + name.lengthký tự lần đầu tiên. Mỗi lần truy cập tiếp theo có một chi phí của các 3ký tự.

Đối với ký hiệu dấu chấm, tất cả các truy cập chi phí name.length + 1(+1 cho các .ký tự).

Sử dụng phương pháp này nếu 6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1).

len = chiều dài tên tài sản
i = truy cập tối thiểu để tận dụng

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

Số lượng truy cập cũng có thể trải rộng trên nhiều đối tượng. Nếu bạn truy cập .length4 lần trở lên trên các mảng khác nhau, bạn có thể sử dụng cùng một biến giữ chuỗi 'length'.


5
c = ~~a-~~bnên c = ~~a+~~b. Ngoài ra, bạn có thể ngầm định chuyển sang số nguyên bằng cách sử dụng |0, ví dụ Math.random()*6|0.
mellamokb

7
Nó rẻ hơn khi ép buộc một chuỗi thành một số với toán tử unary plus. Nếu ablà chuỗi, bạn có thể làm +a+bđể chuyển đổi thành số và thêm chúng.
Peter Olson

8
Tôi thề tôi sẽ sử dụng d- -bmã của mình một ngày nào đó ...
John Dvorak

4
+ a + b không hoạt động (ít nhất là của tôi ...) // a = "1", b = "1", + a + b // cho "11"
imma

2
Đối với "Sử dụng truy cập mảng cho các cuộc gọi chức năng lặp lại" nếu bạn đang sử dụng chức năng nhiều hơn hai lần trên cùng một đối tượng , thì ngắn hơn một chút là gán chức năng cho một thành viên mới nhưa.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender

131

Chia nhỏ với các số để lưu các dấu ngoặc kép:

"alpha,bravo,charlie".split(",") // before
"alpha0bravo0charlie".split(0)   // after

2
Nó hoạt động và tôi đã sử dụng nó cho nhiều chữ số.
Isiah Meadows

12
Lol điều này thực sự khá sáng tạo
NiCk Newman

9
trong ES6 điều này không còn quan trọng nữa, bạn chỉ có thể làm.split`...`
David Archibald

"alpha,bravo,charlie".split`,`
Kamil Kiełczewski

56

Sử dụng toán tử dấu phẩy để tránh niềng răng (cũng áp dụng cho C ):

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

Thay vì

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

đó là một ký tự dài hơn.


2
Là dấu chấm phẩy cần thiết ở cuối mẫu đầu tiên?
wjl

4
@wjlafrance: Nó sẽ chỉ không được yêu cầu nếu nó ở cuối của một lớp lót.
mellamokb

48

Tạo số ngẫu nhiên ngắn hơn

Nếu bạn cần một boolean ngẫu nhiên ( 0hoặc 1):

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

Nếu bạn cần một số nguyên ngẫu nhiên 0 <= n < 1337:

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

Điều này hoạt động vì a Dateđược lưu trữ nội bộ trong JavaScript dưới dạng số mili giây kể từ một epoch, do đó, new Datenó đang bị ép buộc 123somebignumber456khi bạn cố gắng thực hiện phép toán số nguyên trên nó.

Tất nhiên, những con số "ngẫu nhiên" này thực sự sẽ không phải là ngẫu nhiên, đặc biệt nếu bạn gọi chúng nhiều lần liên tiếp, vì vậy hãy ghi nhớ điều đó.


1
Chỉ cần nhớ câu trả lời này trong khi đọc thêm các lập trình viên giả dối tin vào thời gian : 21. Nếu bạn tạo hai đối tượng ngày ngay cạnh nhau, chúng sẽ biểu thị cùng một lúc. (một trình tạo Heurrorms tuyệt vời) .
Sebastian Simon

39

Bạn có thể sử dụng hình thức nghĩa đen của get / set để tránh sử dụng từ khóa 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)

phần getter / setter thực sự hữu ích. thx
gion_13

1
Trên thực tế, thậm chí tốt hơn là một phương thức đối tượng, nếu bạn chỉ sử dụng nó <= 2 lần. Mặt khác, các chức năng mũi tên tốt hơn nhiều trong việc cắt giảm các ký tự, vì chúng phục vụ gần như cùng một mục đích và các lớp hiếm khi hữu ích trong mã golf.
Isiah Meadows

nếu hỗ trợ là chức năng mũi tên quan trọng không được hỗ trợ trong fx. tức là11
Jim Wolff

35

Cái này ít được biết đến và ít được sử dụng hơn, nhưng có thể ấn tượng nếu được sử dụng trong tình huống phù hợp. Hãy xem xét một hàm không có đối số và luôn trả về một số khác khi được gọi và số được trả về sẽ được sử dụng trong phép tính:

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

Thông thường bạn có thể rút ngắn chức năng này bằng cách sử dụng tên biến một chữ cái:

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

Một cách tốt hơn để giảm độ dài là lạm dụng valueOf, giúp bạn tiết kiệm 2 ký tự cho mỗi lần gọi. Hữu ích nếu bạn gọi hàm nhiều hơn 5 lần:

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
Hoặc, bạn có thể làm điều đó giống như một trong hai cách sau: let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)hoặc let a=Array(7).map((_,i)=>i*Math.random()|0+5), 36 hoặc 42 byte được lưu tương ứng.
Isiah Meadows

Có thể thay thế r(), hoặc làm cho nó ngắn hơn?
NiCk Newman

3
r={valueOf:Math.random}Đó chỉ là thiên tài: D
ETHproductions

1
@Isiah, vâng, bạn có thể làm điều đó ngay bây giờ :-D
Andy E

32

Tận dụng lợi thế của các nhà khai thác ngắn mạch

Thay vì các ifcâu lệnh dài hoặc sử dụng các toán tử ternary, bạn có thể sử dụng &&||rút ngắn mã của mình. Ví dụ:

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

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

có thể trở thành

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

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

Các ||nhà điều hành thường được sử dụng theo cách này để thiết lập giá trị mặc định:

evt = evt || window.event;

Điều này giống như viết

if (!evt)
    evt = window.event;

Tạo các chuỗi lặp đi lặp lại bằng Array

Nếu bạn muốn khởi tạo một chuỗi dài của một ký tự cụ thể, bạn có thể làm như vậy bằng cách tạo một mảng có độ dài n + 1 , trong đó n là số lần bạn muốn lặp lại ký tự:

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

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

Chuỗi càng lớn, tiết kiệm càng lớn.

Phân tích số

Sử dụng +~toán tử thay vì parseFloat()hoặc parseInt()khi kết hợp một loại chuỗi chỉ là một số thành một loại số:

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

Mặc dù vậy, hãy cảnh giác, các loại khác có thể được kết hợp với các toán tử này (ví dụ, truesẽ trở thành 1) một chuỗi trống hoặc một chuỗi chỉ chứa khoảng trắng sẽ trở thành 0. Điều này có thể hữu ích trong một số trường hợp, tuy nhiên.


6
+1 cho Tạo chuỗi lặp lại bằng Array - chưa nghĩ về chuỗi đó.
mellamokb

4
Để tạo các chuỗi lặp đi lặp lại, trong ES6 bạn có thể sử dụngstr.repeat(count)
Oriol

26

Khởi tạo biến lén vào lệnh gọi () để nhận đầu vào của người dùng

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

thay vì sử dụng

n=prompt();i=5;

Là một hiệu ứng phụ, nó sẽ hiển thị giá trị đầu vào trong cửa sổ nhắc trong khi lưu 1 ký tự.


12
Điều này cũng có thể được áp dụng cho bất kỳ chức năng nào không chấp nhận đối số.
Casey Chu

3
Ngay cả khi hàm chấp nhận đối số, nó có thể hữu ích, như [1,2,3].join('',i=5)trong trường hợp nó lưu một cặp dấu ngoặc.
DocMax

3
@DocMax: Bạn có thể sử dụng toán tử dấu phẩy cho rằng - i=5,[1,2,3].join().
Konrad Borowski

@GlitchMr: Tôi có thể, nhưng nó không lưu bất kỳ ký tự nào. Tôi đồng ý rằng hầu hết thời gian sẽ sạch hơn. Tôi nghĩ rằng vẫn có thể có trường hợp đơn đặt hàng của tôi có thể cứu một char, mặc dù tôi không thể đưa ra một cái vào lúc này (và tôi cũng có thể sai).
DocMax

@DocMax Chỉ khi bạn đang tận dụng lợi thế của ASI.
Isiah Meadows

24

Kết hợp lồng cho các vòng lặp:

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

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

Ví dụ với các giá trị khác nhau cho 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)

(Tôi đã chỉnh sửa một) lỗi đánh máy nhỏ, nhưng rất thông minh! Lưu ý rằng điều này sẽ chỉ hoạt động trên các vòng lặp lồng nhau có cùng độ dài (trừ khi tôi sai).
Camilo Martin

1
@CamiloMartin Không, các vòng lặp không cần phải có độ dài bằng nhau. Số lần lặp kết quả là i*jvà các toán tử chia / mô đun lấy các giá trị riêng lẻ của ij.
quietmint

@ user113215 Bạn nói đúng, tuyệt vời! :) Tôi đã chỉnh sửa câu trả lời để bao gồm một ví dụ.
Camilo Martin

23

Phím tắt Unicode

Nếu bạn sử dụng địa ngục của một tài sản tích hợp trong một thử thách chơi gôn lớn, bạn có thể đặt bí danh cho mỗi tài sản tương đương với một ký tự:

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

Sau khi thực thi mã ở trên, bạn có thể sử dụng nó như thế này:
"foo".Č(/.*/,'bar') // replaces foo with bar

Cái này có giá 118 byte, vì vậy nó có thể không hữu ích trong một số trường hợp nhất định

Nó có thể phụ thuộc vào trình duyệt và tôi không chắc liệu nó có ngắn hơn with(Array){join(foo),...}hoặc xác định các biến là thuộc tính được sử dụng hay không with(Array){j=join,m=map...}nhưng nó vẫn đáng được đề cập.

    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         

Tôi đang sử dụng google chrome và tất cả đều không xác định.
SuperJedi224

Nó phải rất cụ thể firefox rồi. Xin lỗi vì sự bất tiện.
bebe

Tại sao tất cả những nhân vật đặc biệt này? Tại sao không sử dụng ASCII có thể in? (dễ gõ hơn, đáng tin cậy hơn và chỉ 1 byte khi chơi gôn)
Cyoce

Điều này không thực sự hoạt động Mathvì nó không có .prototypethuộc tính. MathMặc dù vậy, việc gỡ bỏ , tôi đã xoay sở để đưa đoạn mã này xuống một đoạn mã 114 byte, gán tất cả chúng cho các chữ cái một byte. Bạn có thể tìm thấy nó ở đây .
Sản phẩm ETH

1
Bạn cũng có thể đánh golf giải pháp của tôi tới 106 byte với chi phí di chuyển tất cả các thuộc tính này sang phạm vi À- ÿ, vẫn là 1 byte trong mã hóa ISO-8859-1 (mà JS hỗ trợ). Trong Firefox 50, điều này không may đưa .localeComparephương thức vào ×, nhưng đó thường không phải là một vấn đề. nguồn
ETHproductions 3/12/2016

22

Chuyển đổi một whilevòng lặp thành một forvòng lặp thường tương đương:

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

Nhưng hình thức thứ hai có thể có khởi tạo biến kết hợp:

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

Lưu ý mẫu thứ hai ngắn hơn một ký tự.


6
Hoặc, thậm chí tốt hơn, chỉ sử dụng cho các vòng lặp. Thực sự không có trường hợp sử dụng vòng lặp for cho mã lớn hơn, theo như tôi đã trải nghiệm.
Isiah Meadows

22

Lạm dụng ngoại lệ

trong trường hợp chuỗi ký tự / ký tự bị cấm, bạn có thể sử dụng khối thử bắt:

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

bây giờ strbằng"something"

nếu cần thêm chuỗi, bạn có thể xâu chuỗi nó bằng một số (ví dụ: số không)

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

bây giờ arrbằng["something", "foo", "bar", " is not defined"]


18

Nếu bạn đang khởi tạo một biến 1trong mỗi lần lặp của vòng lặp (ví dụ: đặt lại một biến trong vòng lặp bên ngoài cho vòng lặp bên trong), như sau (từ câu trả lời của tôi cho câu hỏi này ):

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

Vì kết quả của một điều kiện giống như bất cứ khi nào j++<=n1đúng, bạn chỉ có thể gán điều kiện trực tiếp cho biến (vì khi nó trở thành sai, vòng lặp sẽ ngừng thực thi và sẽ không còn quan trọng nữa):

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

Bạn thường có thể lưu 2 ký tự bằng phương pháp này. Trân trọng @ugorencho ý tưởng trong các ý kiến ​​cho câu trả lời đó.


Đối với một ví dụ khác, tôi cũng áp dụng thủ thuật này cho câu trả lời của mình ở đây với biểu thức w=r=++c<S.lengthở vòng lặp ngoài của tôi, lưu tổng cộng 4 ký tự.


18

Nếu bạn có thể chấp nhận các tập lệnh cụ thể của Spidermonkey (hiện tại), bạn có thể sử dụng các hàm mũi tên ECMAScript 6 . Thay vì viết mã như sau.

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

Bạn có thể rút ngắn nó như thế này.

a.map(x=>x*2)

17

Nếu bạn cần kiểm tra NaN, không sử dụng isNaN(x), nhưng sử dụng x!=x, ngắn hơn và cũng hoạt động.

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

Lưu ý rằng điều này chỉ hoạt động nếu typeof(x) === "number"; nếu đó là một chuỗi chẳng hạn, isNaN("string")trả về true, nhưng "string" != "string"trả về false. Cảm ơn Cyoce đã chỉ ra điều này!


2
Đó là một thiên tài sử dụng cách giải quyết này. +1
Sản phẩm ETH

Cảnh báo: những thứ này không phải lúc nào cũng tương đương: isNaN("string")trả về true, trong khi "string"!="string"trả về false(rõ ràng)
Cyoce

@Cyoce Điểm tốt, cảm ơn! Tôi chỉnh sửa câu trả lời của tôi.
Chương trìnhFOX

Trong nhiều trường hợp, bạn thậm chí có thể đi if(!x){, nếu bạn đang phát hiện NaNrõ ràng.
Hohmannfan

1
Truyền xtới số, +x!=+xlàm cho nó tương đương isNaN(x), nhưng vẫn ngắn hơn 2 ký tự. Sau đó, +"string"!=+"string"trả về đúng.
Tomas Langkaas

15

Tổng mảng / sản phẩm / thương số

ES5 : 17 byte

eval(a.join('+'))

ES6 : 15 byte

eval(a.join`+`)

Tất nhiên bạn có thể trao đổi +bất cứ thứ gì bạn muốn, ví dụ, *cho sản phẩm hoặc /thương số.


14

Sử dụng thao tác bitwise để làm tròn một số về 0:

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

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

(Nguồn: Tice xúc xắc ngẫu nhiên )

Ưu tiên toán tử xác định cái nào sẽ ngắn hơn trong chương trình của bạn.


2
Điều này cũng có thể được sử dụng để kết hợp một đầu vào chuỗi thành một số nguyên, nghĩa là , n=prompt()|0.
mellamokb

1
bitwise cũng siêu nhanh so với math.floor: jsperf.com/floor-vs-bitwise
vsync

@vsync: Lạ. Tôi nhận được math.floor nhanh gấp khoảng hai lần trên Chrome 11.0.696.77.
mellamokb

rất kì lạ. Đối với tôi, cả hai đều có tốc độ nhanh hơn hoặc nhanh hơn trong Chrome, nhưng trong FF thì bitwise nhanh hơn Chrome rất nhiều và Math.floorrất chậm ... tôi không nên sử dụng.
vsync

Để giữ cho các bình luận được cập nhật, trong Fx hiện tại, cả hai đều nhanh và gần bằng nhau. Không phải là nó có khả năng là một nút cổ chai ở nơi đầu tiên, so với mã xung quanh ...
FireFly

14

Mẹo vòng tôi

Bạn có thể lưu 1ký tự khi lặp bằng cách thay đổi ilần cuối được sử dụng:

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

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

Lưu ý: hoạt động với --quá (nhưng sửa đổi vòng lặp cho phù hợp để tránh vòng lặp vô hạn)


Mẹo vòng II

Có một số trường hợp nhất định trong đó bạn có thể lưu một ký tự bằng cách chơi với toán tử tăng dần và các giá trị:

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

Lưu ý: bạn cần chú ý khi ví dụ 0 to -1. và 9 to 10, 99 to 100, vì vậy hãy chơi xung quanh cho đến khi bạn tìm được cách cứu nhân vật


13

Sử dụng ^thay vì !=hoặc ==khi so sánh với một số nguyên

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

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

Thay thế các cuộc gọi thành các hàm Toán học tích hợp bằng các biểu thức ngắn hơn

//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
Ngoài ra, bạn có thể chỉ cần sử dụng -thay vì !=cho số nguyên; Ví dụ: n!=1?a:bsẽ tương đương vớin-1?a:b
vrugtehagel

10

Một điều đáng chú ý là bạn có thể sử dụng một chuỗi thay cho số 0 trong một số trường hợp để lưu một vài byte ở đây và ở đó trong các vòng lặp:

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

1
Tôi đã thử "" ++ trong bảng điều khiển trước đó tự hỏi liệu nó có hoạt động không, tất nhiên nó phải ở trong một biến đầu tiên. Cảm ơn!
Vartan

10

Rất đơn giản, ngay cả như vậy, không ai đã đề cập đến nó.

Nếu bạn đang sử dụng Math.min()hoặc Math.max()bạn có thể lưu 6 ký tự bằng cách này:

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

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

10

Làm tròn

Tôi biết rằng các lựa chọn thay thế Math.floor()đã được đăng, nhưng những người khác thì sao?

Sàn:

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

Làm tròn:

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

Trần nhà:

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

1
Lưu ý rằng 0|x+1chỉ cần thêm 1 nếu số bạn muốn tìm trần đã là số nguyên. Một sự thay thế an toàn (chủ yếu) là 0|x+1-1e9, nhưng đây chỉ ngắn hơn ba byte.
Sản xuất ETH

@ETHproductions không có nghĩa là bạn 0|x+1-1e-9?
Mama Fun Roll

Rất tiếc, vâng. Cảm ơn đã chỉ ra rằng. (Vì một số lý do, tôi không thể làm @ (tên người dùng của bạn) ...)
ETHproductions

Có lẽ vì ký tự tên người dùng của tôi bị đảo lộn :)
Mama Fun Roll

1
Đối với trần, x%1?-~x:x(9 ký tự) là một thay thế tốt hơn. Tuy nhiên, giống như các lựa chọn thay thế sàn 0|x~~x, nó chỉ hoạt động cho số dương.
Tomas Langkaas

9

Trong trường hợp bạn đang sử dụng toán tử ternary để chọn giữa hai số và điều kiện là boolean hoặc số 1 or 0 , bạn có thể thực hiện các phép toán thay thế:

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

Lưu ý: Ngoài việc này, bạn sẽ cần phải loại bỏ những không cần thiết 0-, +0, +-, vv

Lưu ý2: có một trường hợp riêng biệt trong đó (x) !== (x?1:0), như là xphải typeof === "number"cho nó hoạt động. Tuy nhiên, trong trường hợp của (-x)nó hoạt động tốt.

Lưu ý 3: Trong trường hợp bạn không tìm thấy tiền tiết kiệm, chỉ cần sử dụng trước đây(x?y:z)

Trước đây tôi nghĩ phương pháp B không bao giờ đánh bại A, tuy nhiên có ngoại lệ tồn tại:

(x?97:100) //original

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

Tôi đã tạo một dự án github để đơn giản hóa chúng tôi ( bản demo jsFiddle )


@ ajax333221 void 0(nó không phải là một hàm, nhưng một từ khóa) không phải là một giá trị, nó chỉ đơn giản trả về undefined.
Camilo Martin

@CamiloMartin bạn nói đúng, giờ tôi cũng thấy điểm trong câu trả lời này, tuy nhiên aphải là 1 hoặc 0 để nó hoạt động
ajax333221

@ ajax333221 Vâng, thực sự, điều thú vị về việc chơi golf với tôi là hầu hết các thủ thuật hay nhất chỉ hoạt động cho điều đặc biệt mà bạn đang làm, và người ta cảm thấy rất thông minh khi tìm thấy một trong những trường hợp góc này với các giải pháp góc: cách này, bạn không phải xóa bình luận ...
Camilo Martin

9

tl; dr: Sử dụng các tính năng ES6!

Chức năng mũi tên

Tài liệu: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_fifts
Ví dụ:

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

Các chức năng mũi tên đã được đề cập vào ngày 13 tháng 10 năm 13 lúc 15:42 . Nhưng đó là for.. ofmát mẻ. Thậm chí ngắn hơn for each.. in.
manatwork

2
Cú pháp hiểu mảng có vẻ là sai. Theo tài liệu nên giống như trong Python : b = [s(x) for (x of a)].
manatwork

@manatwork Các mẫu trên chạy tốt trong REPL của Traceur
Florent

Không biết gì về Traceur, nhưng bạn đã đề cập đến ECMAScript và chỉ vào tài liệu Mozilla. Và mảng hiểu trong không ai trong số họ trông giống như bạn đã viết nó.
thao tác

1
Hiểu mảng đã thực sự được kéo giữa chừng.
Isiah Meadows

9

Lạm dụng chữ

Mẫu gần đây: Kiểm tra xem "c"là chữ hoa hay chữ thường, không quan trọng nếu không phải là chữ cái

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

3
Cái này hoạt động ra sao?
Bò lang băm

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

8

Cách so sánh một số với sự trợ giúp về cách các số biến thành booleans:

Nếu bạn định kiểm tra xem có thứ gì đó bằng số dương không , bạn có thể trừ số tiền đó và đảo ngược những gì bên trong khối ifelsekhối:

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

Và trong trường hợp bạn muốn so sánh với số âm (* khác với -1), bạn chỉ cần thêm số này thay vì trừ đi.

* tốt, bạn chắc chắn có thể sử dụng x.indexOf(y) + 1, nhưng trong trường hợp đặc biệt -1bạn có cơ hội sử dụng ~x.indexOf(y)thay thế.


8

Sử dụng tính năng "đóng biểu thức" không chuẩn của Mozilla để lưu nhiều ký tự trong tập lệnh chỉ cần hoạt động trong các công cụ SpiderMonkey / Firefox hoặc Rhino. Ví dụ,

function foo(){return bar}

trở thành

function foo()bar

Xem trang Stack Overflow để biết thêm các thủ thuật như vậy.


2
Đó không phải là Javascript. Đó là TRẠM KHÔNG GIAN !!!
Thomas Eding

1
ECMAScript 6 để giải cứu! ->bar
Ry-

5
ECMAScript 6 : let foo = () => bar;, ngắn hơn trớ trêu so với mã được chơi ở trên.
Isiah Meadows

1
ECMAScript 6 : foo=_=>bar, thậm chí ngắn hơn.
Sản xuất ETH

liên kết đó bị hỏng.
Cyoce



8

Chuyển đổi thành Boolean :

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

Lưu ý: Điều này thay đổi 0, "", false, null, undefinedNaNđể false(mọi thứ khác để true)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.