Mẹo chơi gôn bằng <tất cả các ngôn ngữ>


81

Mục đích của bài này là để thu thập tất cả các mẹo chơi golf có thể dễ dàng áp dụng <all languages>thay vì một cụ thể.

Chỉ đăng câu trả lời rằng logic của nó có thể được áp dụng cho phần lớn các ngôn ngữ

Xin vui lòng, một mẹo cho mỗi câu trả lời


5
"Đa số" theo số liệu nào?
đã ngừng quay ngược chiều

2
@leftaroundabout theo số liệu của cùng một từ
ajax333221

8
Vấn đề là nhiều ngôn ngữ là những ngôn ngữ thử nghiệm (thường tồn tại trong thời gian ngắn) với các mô hình rất không điển hình, trong đó các biểu thức lập trình điển hình không có ý nghĩa gì cả. Vì vậy, "phần lớn tất cả các ngôn ngữ" hầu như không thể thực hiện được. Bạn nên hạn chế nó theo một cách nào đó, ví dụ như "phần lớn các ngôn ngữ được sử dụng thường xuyên trên codegolf.SE". Hiện tại, các câu trả lời trông khá giống "phần lớn các ngôn ngữ có nguồn gốc từ xa", nhưng những câu trả lời, mặc dù phần lớn tất cả các được viết đều được viết bằng chúng, không phải là phần lớn các ngôn ngữ .
đã ngừng quay ngược chiều

3
leftroundabout, tôi đoán tất cả chúng ta đều biết ý nghĩa của chúng. Đây là về phần lớn tối ưu hóa độc lập với ngôn ngữ, tức là những thứ không chỉ hữu ích trong Brainfuck mà có thể cả Python, C, Java và Fortran cùng một lúc. Những ý tưởng chung mà bạn có thể áp dụng trong nhiều ngôn ngữ hoạt động tương tự nhau. Tôi không nghĩ cần phải chính xác và cụ thể trong các mẹo và câu hỏi CW. Đây là về việc giúp đỡ người khác chơi gôn, không phải là chọc giận họ.
Joey

14
Hy vọng không ai tạo ra một ngôn ngữ gọi là <all languages>...
mbomb007

Câu trả lời:


72

Hợp nhất các vòng

Bạn thường có thể hợp nhất hai vòng lặp hoặc hai vòng lặp lồng nhau thành một.

Trước:

for (i=0; i<a; i++) foo();
for (i=0; i<b; i++) bar();

Sau:

for (i=0; i<a+b; i++) i<a?foo():bar();

xấu xí các vòng vẫn không giống nhau. @Gaffi nói đúng.
kaoD

5
@kaoD, trong cả hai trường hợp foođược gọi là alần, barđược gọi là blần. Điều này là do trong "sau", vòng lặp chạy a+blần, acuộc gọi đầu tiên foo, cuộc gọi tiếp theo bar.
ugoren

Tôi đang xem xét lại điều này (nhiều, rất nhiều sau này) và bây giờ tôi không hiểu câu hỏi của mình. Tôi có thể không hiểu hoạt động trước đây? Cách tôi nhìn thấy nó bây giờ, nó có ý nghĩa.
Gaffi

1
Ái chà, tôi đọc cái đó rất khuya. Bạn đúng!
kaoD

3
Rất giống nhau: for(y=0;y<Y;++y)for(x=0;x<X;++x)thường có thể trở thành for(i=0;i<X*Y;++i)với xthay thế bởi i%Xythay thế bởi i/X.
Lynn

62

Chỉ cần đề cập đến rõ ràng:

Câu hỏi lựa chọn thuật toán của bạn và thử một cái gì đó hoàn toàn mới.

Khi chơi golf (đặc biệt là các vấn đề khó hơn dẫn đến các chương trình dài hơn) tất cả quá thường xuyên, bạn có thể dính vào con đường bạn chọn đầu tiên mà không thử các tùy chọn cơ bản khác . Tất nhiên, bạn có thể vi golf một hoặc một vài dòng tại một thời điểm hoặc một phần của ý tưởng tổng thể, nhưng thường không thử một giải pháp hoàn toàn khác.

Điều này đặc biệt đáng chú ý ở Đánh 495 (Kaprekar) khi đi lệch khỏi thuật toán thực tế và tìm kiếm các mẫu bạn có thể áp dụng để có được kết quả tương tự ngắn hơn trong nhiều ngôn ngữ (không phải J).

Nhược điểm là bạn có thể giải quyết điều tương tự nửa tá lần. Nhưng nó hoạt động thực sự trong tất cả các ngôn ngữ ngoại trừ HQ9 + (trong đó việc tìm một cách khác để xuất Hello World sẽ hơi vô ích).


12
+1 Ngoài việc tốt cho việc chơi golf, đây là bài tập tốt cho bất kỳ lập trình viên nào trong nhiều tình huống thực tế!
Gaffi

52

Sử dụng phát triển dựa trên thử nghiệm

Nếu mã phải xử lý các đầu vào khác nhau, sau đó viết các bài kiểm tra toàn diện và giúp dễ dàng chạy tất cả chúng một cách nhanh chóng. Điều này cho phép bạn thử biến đổi rủi ro một bước bé tại một thời điểm. Chơi golf sau đó trở nên giống như tái cấu trúc với ý định đồi trụy.


4
Tôi sử dụng một spinoff của phương pháp này. Vì các vấn đề thường khá đơn giản, tôi viết một chương trình thực hiện công việc. Thông thường, đây là "có thể chơi golf", vì vậy nó ngắn gọn, nhưng các dòng mới, v.v. Tôi sao chép tệp này vào một vị trí mới và đánh golf nó, kiểm tra từng lúc và sau đó các chương trình trả về cùng một giá trị cho một số đầu vào được chọn. Nếu tôi từng mắc lỗi khi để lại cho tôi một chương trình bị hỏng, không có ký ức về những gì tôi đã thay đổi và không hiểu gì về tác phẩm golf của mình, tôi có một cái gì đó của "đặc tả" được lưu làm nguồn tham khảo.
shiona

2
Tôi thích phương pháp này, đó là một lý do mà tôi có xu hướng bao gồm các bộ kiểm tra toàn diện cho tất cả các vấn đề tôi viết.
Joey

@RubberDuck Nguyên tắc Đừng lặp lại chính mình thường được tuân thủ nghiêm ngặt.
Jonathan Frech

48

Cố gắng giảm các câu lệnh logic

Ví dụ: nếu ABlà booleans và ngôn ngữ của bạn đối xử với booleans như số ở một mức độ nào đó A and (not B)A>Btương đương. Ví dụ trong Python

if A and not B:
    foo()

giống như:

if A>B:
    foo()

3
Tôi chưa bao giờ nghĩ về điều đó.
cjfaure

27
B>A or foo()sẽ là một cách thậm chí ngắn hơn để diễn đạt điều này, tận dụng việc đánh giá lười biếng các biểu thức boolean để đảm bảo nó chỉ tính toán mọi thứ khi cần.
scragar

5
@scragar: Đúng, nhưng đây không phải là điểm của mẹo này. (Đó là một mẹo độc lập có giá trị mặc dù.)
Wrzlprmft

3
@scragar, B>A or foosẽ đánh giá foonếu B==Ađó không phải là những gì chúng ta muốn. (Phải không?)
msh210

2
Ngoài ra, nếu bạn có điều kiện dài hạn (ví dụ với 5/6 tham số), bạn có thể sử dụng bảng Chân lý và bản đồ Karnaugh để tìm biểu thức boolean ngắn nhất cho nó
Katenkyo

33

Khởi tạo các biến bằng các giá trị bạn đã có.

Thay vì x=1, hãy thử tìm một cái gì đó đã bằng 1.
Ví dụ: giá trị trả về của hàm: printf("..");x=0;-> x=!printf("..");. Dễ nhất là 0, bởi vì bạn luôn có thể phủ định hoặc khi tất cả những gì bạn cần là giá trị đúng (và không quan tâm nếu đó là 1 hoặc 19).


4
trong C, bạn có thể sử dụng argc từ chính là 1. xem: codegolf.stackexchange.com/questions/1034/reinvent-the-for-loop/iêu
std''OrgnlDave

1
@ std''OrgnlDave, Đúng, nhưng câu hỏi này là về những điều phổ biến cho tất cả các ngôn ngữ.
ugoren

33

Sử dụng unary ~cho x+1x-1

Thủ thuật này áp dụng cho các ngôn ngữ có toán tử phủ định bitwise unary ~và toán tử phủ định thông thường unary -.

Nếu chương trình của bạn, tình cờ, chứa biểu thức -x-1, bạn có thể thay thế nó ~xđể lưu byte. Điều này không xảy ra quá thường xuyên, nhưng hãy xem điều gì xảy ra nếu chúng ta phủ định ( -) cả hai biểu thức: x+1bằng -~x! Tương tự, x-1bằng ~-x. (Hãy nghĩ về cách các dấu ngã: bên phải +, bên trái là -.)

Điều này rất hữu ích, bởi vì trong tất cả các ngôn ngữ tôi có thể nghĩ rằng có các toán tử này, chúng có độ ưu tiên cao hơn hầu hết các toán tử. Điều này cho phép bạn lưu vào dấu ngoặc đơn. Xem cách chúng tôi lưu bốn byte ở đây:

(x+1)*(y-1)     ==>    -~x*~-y

30

Bóp khoảng trắng

Biết các quy tắc cho khoảng trắng trong ngôn ngữ của bạn. Một số dấu chấm câu, hoặc các ký tự khác, có thể không cần bất kỳ khoảng trắng xung quanh. Hãy xem xét hàm shell Bourne này :

f () { echo a; echo b; }

Trong vỏ Bourne, ();là các ký tự đại diện và không cần khoảng trắng xung quanh. Tuy nhiên, {}là các từ và cần khoảng trắng trừ khi chúng nằm cạnh các siêu ký tự. Chúng tôi có thể chơi gôn 4 chỗ bên cạnh ();, nhưng phải giữ khoảng trống giữa {echo.

f(){ echo a;echo b;}

Trong Common LispPicoLisp , ()là các ký tự đại diện. Xem xét mã này để tìm trung bình của hai số:

(/ (+ a b) 2)

Chúng tôi có thể chơi golf 2 chỗ.

(/(+ a b)2)

Một số ngôn ngữ có quy tắc kỳ lạ và tinh tế cho khoảng trắng. Hãy xem xét chương trình Ruby này, nó in tổng và tích của một dòng số nguyên.

#!ruby -an
i=$F.map &:to_i
puts"#{i.reduce &:+} #{i.reduce &:*}"

Mỗi người &cần một không gian trước chính nó. Trong Ruby, i=$F.map &:to_icó nghĩa là i=$F.map(&:to_i)nơi &vượt qua một tham số khối. Nhưng, i=$F.map&:to_icó nghĩa là i=$F.map.&(:to_i)nơi &một toán tử nhị phân.

Sự kỳ lạ này xảy ra trong các ngôn ngữ, như Perl hoặc Ruby, sử dụng dấu câu mơ hồ. Nếu nghi ngờ, hãy sử dụng REPL hoặc viết các chương trình ngắn để kiểm tra các quy tắc khoảng trắng.


1
Tại sao cần phải có khoảng trắng giữa "{" và "echo", nhưng không phải giữa ";" và "tiếng vang"?
Ryan

3
Tôi đã sử dụng các thuật ngữ từ hướng dẫn sử dụng cho OpenBSD sh (1), trong đó nói rằng "{" là một từ dành riêng và ";" là một siêu nhân vật. Bởi vì điều này, "{echo" là một từ nhưng "; echo" là hai từ. Các hướng dẫn khác có thể giải thích điều này khác nhau. Ngoài ra, zsh shell Z có các quy tắc khác nhau.
hạt nhân

28

gán chức năng cho tên mới nếu được sử dụng nhiều lần

x = SomeLongFunctionName
x(somedata)
x(somemoredata)
etc

Chỉ khi chúng ta sử dụng đủ các cuộc gọi đến x.
elipszilon

28

Tên biến thư đơn

Bạn có 52 người trong số họ; sử dụng tất cả Đừng ngại thử các cách tiếp cận khác nhau và so sánh độ dài. Biết ngôn ngữ và các phím tắt / chức năng thư viện cụ thể có sẵn.


8
26 cho các ngôn ngữ không phân biệt chữ hoa chữ thường. :-)
Gaffi

12
Thường xuyên $_có thể được sử dụng như định danh.
Griffin

4
@Gaffi: Và quá đủ cho các ngôn ngữ cho phép định danh Unicode, trừ khi tác vụ giới hạn bạn ở ASCII hoặc đếm byte thay vì ký tự.
hammar

Nếu bạn đang đếm byte thay vì unicode thì sử dụng ascii mở rộng có thể là cách để nén ~ 120 số nhận dạng khác nếu bạn cần chúng (không phải là đối với tập lệnh golf, bạn vẫn cần nhiều hơn 26)
scragar

2
@là tên biến hợp lệ trong T-SQL, sử dụng nó thay vì @a.
BradC

25

Sử dụng toán tử có điều kiện.

Một toán tử có điều kiện

bool ? condition_true : condition_false

có lợi hơn, tính cách khôn ngoan, hơn là một tuyên bố IF .

if(a>b){r=a;}else{r=b;}

có thể được viết như

r=a>b?a:b;

25
a&&b||cThay vào đó, các ngôn ngữ không có ternary có thể sử dụng . Hơi dài, nhưng vẫn ngắn hơn một if.
Michael Kohl

Sau đó, một lần nữa, một số không thể sử dụng một trong hai tùy chọn (VBA xuất hiện trong đầu), nhưng cả hai vẫn là những gợi ý tốt. :-)
Gaffi

1
Gaffi: VBA có Iff, mặc dù đó là một chức năng, do đó phải chịu sự đánh giá của tất cả các đối số.
Joey

Sử dụng ternary trong if statement cũng có thể rất hữu íchif(a ? b : c)
Jojodmo

4
@MichaelKohl lưu ý rằng a&&b||ccó thể trở lại ckhi ađúng là iff blà sai, một trường hợp nhỏ, nhưng chúng ta không nên quên điều đó ^^
Katenkyo

24

Viết một lời giải thích về mã của bạn

Viết một lời giải thích buộc bạn phải xem xét kỹ lưỡng từng phần của mã của bạn một lần nữa và làm cho suy nghĩ và lựa chọn của bạn bằng cách viết một đoạn văn rõ ràng. Khi làm như vậy, bạn có thể thấy rằng các cách tiếp cận khác nhau là có thể có thể tiết kiệm một số byte hoặc bạn đưa ra các giả định trong tiềm thức mà không nhất thiết phải giữ.

Mẹo này tương tự như Câu hỏi bạn chọn thuật toán và thử một cái gì đó hoàn toàn mới ; tuy nhiên, tôi đã thấy rằng bước thực sự viết ra cách mỗi phần được cho là hoạt động đôi khi rất quan trọng để nhận thức về các lựa chọn thay thế.

Như một phần thưởng, các câu trả lời bao gồm một lời giải thích thú vị hơn đối với những người dùng khác và do đó có nhiều khả năng được nâng cao hơn.


23

Kiểm tra kỹ số lượng nhân vật của bạn

Nghe có vẻ không có trí tuệ, nhưng bằng cách cẩn thận, bạn có thể "cứu" một vài nhân vật bằng cách không thực sự làm gì cả!

Nếu bạn đang sử dụng Windows, bạn có thể nhập \r\nthay vì chỉ \rhoặc \nkhi bạn nhấn Return - thêm một byte cho mỗi dòng! Xoay các ký tự điều khiển chỉ để kiểm tra lại khi bạn không làm điều này.

Trong Notepad ++, bạn có thể chuyển đổi tất cả các \r\nkết thúc dòng thành chỉ \rbằng cách đi đến Edit > EOL Conversion > UNIX/OSX Format.

Ngoài ra, hãy đảm bảo bạn không bao gồm bất kỳ khoảng trắng nào trong số ký tự của bạn! Nguồn cấp dữ liệu trên dòng dưới cùng trong mã của bạn cũng không quan trọng, do đó sẽ không cần phải tính.


Tôi không nghĩ rằng tôi đã từng thấy một trường hợp mà điều này thực sự được tính đến ...
Jacob

4
Tôi vừa mới gặp vấn đề này (vì sao tôi lại thêm nó).
Sean Latham

21

Đọc kỹ câu hỏi

Chơi gôn mã cũng giống như việc hiểu câu hỏi (những gì được hỏi và những gì không được hỏi, mặc dù nó sẽ được ngụ ý trong bất kỳ cài đặt nào khác) như việc tạo ra mã mà chỉ có thể đáp ứng những gì được hỏi.

Bất kỳ đầu vào nào ngoài những gì được yêu cầu rõ ràng không cần phải xử lý. Nếu có một số trường hợp thử nghiệm và không có yêu cầu chung, mã của bạn chỉ có thể hoạt động trong những trường hợp đó. Vân vân.


15
Tôi nghĩ một tiêu đề tốt hơn ở đây sẽ là "Đừng xử lý các trường hợp cạnh không bắt buộc". Cụm từ "Cố gắng tìm ra sơ hở" mang đến những cách để tránh làm những gì được chỉ định thông qua việc diễn giải lại các quy tắc một cách nghệ thuật, trong khi những gì bạn đang cung cấp chỉ là lời khuyên tốt không nên thực hiện quá mức giải pháp của bạn.
Jonathan Van Matre

1
Vâng, nhưng việc diễn giải lại các quy tắc một cách nghệ thuật cũng là một phần của việc chơi golf mã! (0 giải pháp char, v.v.)
Tobia

8
Đó sẽ là / nên là một câu trả lời khác nhau, mặc dù. Ví dụ, có một sự khác biệt cơ bản giữa việc triển khai một giải pháp chỉ hoạt động cho int vì OP không yêu cầu hỗ trợ float và câu trả lời in văn bản "bất kỳ số nguyên tố nào lớn hơn 100" bởi vì "bạn không nói rằng nó phải là số nguyên tố thực tế ".
Jonathan Van Matre

Tôi nghĩ rằng một số OP bao gồm thông báo "Các trường hợp thử nghiệm có thể thay đổi, mã của bạn vẫn phải hoạt động sau khi thay đổi" và thực sự thay đổi chúng nếu chúng chỉ thấy một câu trả lời mã hóa cứng cho các testcase.
Erik the Outgolfer

20

Sử dụng các thao tác bitwise để kiểm tra các số từ 0 đến bất kỳ 2 n -1

Có thể là một chút của một trường hợp cạnh, nhưng đôi khi nó có thể có ích. Nó dựa vào thực tế là tất cả các số mà m = 2 n -1 áp dụng đều có n bit ngoài cùng bên phải được đặt thành 1.

Vậy, 7 10 == 00000111 2 , 15 10 == 00001111 2 , 31 10 == 00011111 2 , v.v.

Bí quyết là x&~m. Điều này sẽ trở thành sự thật bất cứ khi nào xkhông giữa 0 và m(bao gồm), và sai khác. Nó lưu 6 byte từ biểu thức tương đương ngắn nhất tiếp theo: x>=0&&x<=mnhưng rõ ràng chỉ hoạt động khi mthỏa mãn 2 n -1.


18

Sử dụng lại các tham số hàm thay vì các biến mới


1
Ví dụ, trong C, hàm chính của bạn luôn được truyền số lượng đối số được cung cấp cho chương trình (là 1 - tên chương trình - theo 'mặc định') vì vậy với main(i){...bạn giờ đây có một biến có giá trị là 1 mà không cần phải làm bất kỳ bài tập. 2 ký tự được lưu ở đó ..
Griffin

6
Tôi nghĩ rằng nó khá cụ thể đối với các ngôn ngữ C. Script không cần khai báo và trong hầu hết các ngôn ngữ được biên dịch, việc xác định một biến không dài hơn xác định tham số.
ugoren

trong java khi cần một mảng bên trong một hàm có cùng loại với một tham số, bạn có thể lưu một vài byte bằng cách đặt tham số đó là cuối cùng và biến nó thành tham số vararg; (được sử dụng để cạo một số byte trên hàm để tìm từ dài nhất trong câu)
masterX244

18

Lớn hơn / ít hơn để lưu một chữ số:

//use:
if(n>9){A}else{B}
//instead of:
if(n<10){B}else{A}

Chỉ cần nhớ trao đổi mã từ ifsang elsevà họ sẽ thực hiện chính xác điều tương tự (hoặc chuyển đổi các mặt của bất đẳng thức)!

Lưu ý: điều này có thể được áp dụng với bất kỳ sức mạnh nào của 10 và các tiêu cực của chúng:...-100, -10, 10, 100...

(liên kết nguồn)


Tôi không chắc tôi hiểu điểm này. Điều này làm giảm từ gì?
Gaffi

@Gaffi bạn lưu một ký tự và họ thực hiện chính xác như vậy
ajax333221

so với cái gì thay thế? Xin lỗi, không cố tỏ ra cố chấp, tôi không hiểu. (newb, ở đây, dường như ...)
Gaffi

1
Ah tôi thấy. Hoạt động trên bất kỳ chuyển đổi số nguyên nào từ 9 đến 10, 99 sang 100, v.v ... Xin lỗi đã khiến tôi mất quá nhiều thời gian! (Tôi chỉ nói số nguyên, vì tôi có thể thấy một vấn đề với n = 9.5 ...)
Gaffi

8
Ngoài ra trong một số ngôn ngữ (nếu được hỗ trợ) nếu số của bạn đủ lớn / nhỏ, ký hiệu khoa học thực sự có thể giúp bạn tiết kiệm một số ký tự thay thế: if(n>99999)vsif(n<1e5)
scragar

16

Sử dụng> và <thay vì> = và <=

Khi kiểm tra đối với các giá trị nguyên được mã hóa cứng, hãy sử dụng ><thay vì >=<=nếu có thể. Ví dụ: sử dụng

if(x>24&&x<51)

Là 2 byte ngắn hơn so với sử dụng

if(x>=25&&x<=50)

3
Liên quan: Nếu bạn chắc chắn một kết quả không thể âm tính, bạn có thể sử dụng <1thay vì ==0kiểm tra bằng không (hoặc >0thay vì !=0kiểm tra nhân đôi).
Kevin Cruijssen

1
Bạn không nên thêm một lưu ý về việc xlà một số nguyên?
Zacharý

15

Tránh phá vỡ vòng lặp sớm

Nếu chạy qua một vòng lặp để kiểm tra 1 hoặc nhiều phiên bản kiểm tra boolean, nó có thể tạo ra một chương trình hiệu quả hơn để thoát khỏi vòng lặp trên giá trị thực đầu tiên. Tuy nhiên, loại bỏ ngắt và lặp qua tất cả các lần lặp cho phép mã ngắn hơn.

int main() {
bool m = false;
int n = 1000;
for (int i = 0; i < n; i++) {
if (i >= 100) {
m = true;
break; // remove this line
}
} 
return 0;
}

5
Bạn cũng có thể đơn giản hóa ifcâu lệnh đi trong những trường hợp này : m|=i>=100. (Và bạn cũng có thể đơn giản hóa i>=100để i>99trong trường hợp này nhưng đó không phải là rất phù hợp ở đây)
marinus

15

sử dụng -thay vì!=

để so sánh số:

Nếu a bằng b, a-bkết quả 0là sai. Bất cứ điều gì khác hơn 0là sự thật; vì vậy,
nếu được sử dụng trong ngữ cảnh boolean, a-b<=>a!=b

Nếu bạn sử dụng nó với if/elsehoặc với toán tử ternary, điều này cũng có thể giúp bạn tiết kiệm một byte cho sự bình đẳng:
a==b?c:d<=>a-b?d:c


12

Chia chuỗi cho mảng dài

Hầu hết các ngôn ngữ có một cách để tách một chuỗi thành một chuỗi các chuỗi xung quanh một loại mã thông báo nào đó. Điều này chắc chắn sẽ ngắn hơn một mảng bằng chữ một khi độ dài đạt đến ngưỡng phụ thuộc ngôn ngữ, bởi vì chi phí phụ trên mỗi chuỗi sẽ là một bản sao của mã thông báo một ký tự thay vì (ít nhất) hai dấu phân cách chuỗi.

Ví dụ: trong GolfScript

["Foo""Bar""Baz""Quux"]  # 23 chars

trở thành

"Foo
Bar
Baz
Quux"n/  # 20 chars

Đối với một số ngôn ngữ, ngưỡng thấp nhất là một chuỗi. Ví dụ: trong Java

new String[]{"Foo"}  // 19 chars

trở thành

"Foo".split("~")  // 16 chars

6
Ngoại lệ đáng chú ý là Ruby, cung cấp một chuỗi các chuỗi ký tự tự động phân tách trên các khoảng trắng với chi phí là hai byte : %w{Foo Bar Baz Quux}.
Martin Ender

1
Perl cung cấp một cái gì đó tương tự: qw(Foo Bar Baz Quux)trở thành một danh sách các chuỗi.
BenGoldberg

12

Hiểu những gì người khác đã làm

Ngoài việc vui vẻ, nếu bạn kiểm tra mã của người khác, đôi khi bạn có thể khám phá ra một thuật toán tốt mà bạn không nghĩ tới hoặc một mẹo (đôi khi là một thuật toán rõ ràng) mà bạn bỏ qua.

Đôi khi, có một câu trả lời mà bạn có thể dịch sang ngôn ngữ khác và được hưởng lợi từ những điều tốt đẹp của ngôn ngữ khác.


10

biết ưu tiên nhà điều hành của bạn

Bất cứ khi nào bạn kết hợp một số biểu thức, hãy kiểm tra bảng ưu tiên toán tử cho ngôn ngữ của bạn để xem liệu bạn có thể sắp xếp lại thứ để lưu dấu ngoặc hay không.

Ví dụ:

  • Trong tất cả các ngôn ngữ mà tôi biết, các toán tử bitwise có độ ưu tiên cao hơn các toán tử boolean: (a&b)&&ckhông cần dấu ngoặc đơn: a&b&&ccũng như (a*b)+ckhông.
  • a+(b<<c)có thể được viết lại như a+b*2**c.
    Điều đó không lưu bất cứ điều gì cho ví dụ này, nhưng nó sẽ clà một số nguyên nhỏ (<14).
  • Hoạt động Bitwise có một ưu tiên thấp hơn hầu hết phép tính số học, vì vậy nếu ngôn ngữ của bạn ngầm phôi boolean để int, bạn có thể tiết kiệm một byte trên a<b&&c<dvới a<b&c<d(trừ khi bạn cần đánh giá ngắn mạch)

7

Vòng lặp ngắn hơn

Nếu bạn có các Xcâu lệnh {bên trong }vòng lặp for của mình, bạn có thể di chuyển các X-1câu lệnh (bên trong )vòng lặp for sau dấu chấm phẩy thứ hai for(blah;blah;HERE)để lưu 3 byte. (phân tách các câu bằng cách sử dụng dấu phẩy ,)

Thay vì

for(int i=0;i<9;){s+=s.length();println(i++);}

bạn có thể di chuyển một trong các câu lệnh vào (dấu ngoặc của vòng lặp for )trong khi bỏ câu lệnh kia

for(int i=0;i<9;println(i++))s+=s.length();

và lưu 3 byte (đã lưu thêm 1 byte nhờ @ETH Productstions)


Đơn giản thôi,

thay vì

for(blah;blah;){blah 1;blah 2;...;blah X}

di chuyển các tuyên bố xung quanh để bạn kết thúc với điều này

for(blah;blah;blah 2,...,blah X)blah 1;

và lưu 3 byte


@ETHproductions Cảm ơn bạn đã chơi gôn :)
Kritixi Lithos

Và nếu đó forlà tuyên bố cuối cùng, thì nó ;trở thành tùy chọn
elipszilon

7

Sử dụng unary ~cho a-b-1a+b+1

Ngoài các đề xuất của @Lynn về x+1-~x; và x-1~-x , bạn cũng có thể chơi gôn a-b-1a+b+1.

a-b-1    // 5 bytes
a+~b     // 4 bytes

a+b+1    // 5 bytes
a-~b     // 4 bytes

Nó có thể trông giống như một mẹo bạn sẽ không sử dụng thường xuyên, giống như sử dụng ~xthay vì -x-1không xảy ra thường xuyên, nhưng tôi đã sử dụng nó đủ lần để xem đó là một mẹo hữu ích ở đây. Đặc biệt với lập chỉ mục mảng, bạn có thể sử dụng các mục trên trong một số trường hợp.


6

Nén hoặc / và các vệt

Thủ thuật đơn giản mà tôi đã nghĩ ra khi cố gắng tạo ra một chuỗi dài các điều kiện bị xiềng xích bởi ands (hoặc ors, trong trường hợp này chỉ cần thay thế 'tất cả' bằng 'bất kỳ').

Ví dụ:

if a>0 and a<10 and a+b==4 and a+3<1:

Trở thành

if all([a>0,a<10,a+b==4,a+3<1]):

Đó là một điều tuyệt vời, tôi sẽ phải thử nó!
stokastic

4
Những ngôn ngữ có tích all(array-of-Booleans)hợp?
Peter Taylor

3
Ruby có nó. [a>0,a<10,a+b==4,a+3<1].all?
hạt nhân

4
Mặc dù nếu đây là Python, bạn sẽ sử dụng một cái gì đó nhưif 10>a>0 and a+b==4>1>a+3:
Sp3000

@PeterTaylor Haskell cũng vậy
tự hào

6

Dựa vào trình biên dịch để cung cấp hiệu suất cần thiết.

Hãy chắc chắn để biết các tối ưu hóa nào được đảm bảo bởi trình biên dịch và ở mức tối ưu hóa nào, và sử dụng chúng một cách tự do. Và ngay cả khi hiệu suất không phải là một yêu cầu đáng quan tâm , bạn vẫn có thể kiểm tra tối ưu hóa và sau đó chỉ giảm giá một ký tự vì mã của bạn vẫn hợp lệ về mặt kỹ thuật mà không có cờ trình biên dịch.

Hãy xem xét hàm Haskell sau để tính 2 ^ n (bỏ qua thực tế là Haskell đã có toán tử lũy thừa tích hợp hoặc ba) (23 ký tự):

p 0=1;p x=p(x-1)+p(x-1)

Vấn đề là - nó chậm kinh khủng, nó chạy theo thời gian theo cấp số nhân. Điều này có thể làm cho mã của bạn không thể kiểm chứng hoặc không thực hiện bất kỳ ràng buộc hiệu suất nào được đưa ra bởi câu hỏi. Bạn có thể bị cám dỗ sử dụng một biến tạm thời hoặc một hàm được gọi ngay lập tức theo nghĩa đen để tránh các lệnh gọi hàm lặp lại (25 ký tự):

p 0=1;p x=(\y->y+y)$p$x-1

Nhưng trình biên dịch đã có thể làm điều đó cho bạn, bạn chỉ cần đặt -Olàm cờ biên dịch! Thay vì chi tiêu một vài ký tự bổ sung cho mỗi trang web để loại bỏ các biểu hiện phụ phổ biến theo cách thủ công, chỉ cần yêu cầu trình biên dịch thực hiện tối ưu hóa cơ bản cho bạn tổng cộng một hoặc hai ký tự trong toàn bộ chương trình.


@ETHproductions yep, xin lỗi, tôi đã làm
John Dvorak

Không phải là ví dụ đầu tiên chỉ là p(x-1)*2?
Cyoce

5

Có thể hơi rõ ràng nhưng ...

Sử dụng các giá trị trả về của toán tử

Hãy nhớ rằng toán tử gán trả về một giá trị!

Ví dụ: nếu bạn muốn thêm y vào x và sau đó kiểm tra xem x có lớn hơn thứ gì không, bạn có thể làm

if(25<x+=y)

thay vì

x+=y;if(x>25)

Hoặc có thể bạn muốn tìm độ dài của chuỗi sau khi cắt nó:

strlen(s=trim(s))

Thay vì

s=trim(s);strlen(s)

Trong ngôn ngữ nào bạn có thể thực hiện chuyển nhượng trong một cuộc gọi? hoặc đó là một từ khóa arg?
mèo

2
Tôi nghĩ các bài tập là các biểu thức (với giá trị mới của biến được gán là giá trị biểu thức của chúng) trong ít nhất C, C ++, C # và Java. a = (b=c)+1;đặt bthành c, và sau đó đặt athành b+1.
Lynn

@Lynn Hãy thử a=1+b=c. Và bạn có thể thêm PHP và JavaScript vào danh sách của bạn.
Tít

2
Ruby làm điều này tốt nhất. Nó mang lại cho người =vận hành quyền ưu tiên cao hơn ở bên trái so với bên phải, do đó, 1+x=2là hợp lệ và được đánh giá là3
Cyoce

@Cyoce afaik nó Cách đó trong tất cả các ngôn ngữ mà một bài tập là một biểu thức.
Tít

5

Sử dụng phiên bản ngôn ngữ / trình biên dịch / quirks môi trường / tính năng mới

Điều này đặc biệt hữu ích cho các , nhưng có thể được áp dụng cho các thách thức khác. Đôi khi, một lỗi trình biên dịch có thể đánh bại một byte, một lỗi thực thi có thể cho phép bạn lưu một vài ký tự hoặc một tính năng thực sự gây chảy máu có thể cải thiện điểm số của bạn.


4

Kết hợp nhiều / lồng nhau nếu kiểm tra bằng And / Hoặc khi có thể.

I E:

if (a && (b || c)) {

}

thay vì:

if (a) {
    if (b) {
        //Do Stuff
    } elseif (c) {
        //Do same stuff
    }
}

5
Ngoài ra, sử dụng các điều kiện bitty ( &, `|) để loại bỏ nhiều ký tự hơn.
FUZxxl

2
Mặc dù sử dụng bitwise &thay vì &&loại bỏ 1 ký tự trong một số trường hợp, nó làm rối tung quyền ưu tiên của toán tử và bạn sẽ phải đặt dấu ngoặc đơn để làm cho nó hoạt động. Sử dụng nó một cách khôn ngoan.
DollarAkshay 04/07/2015

4

Tìm cách tốt hơn để khởi tạo các biến của bạn

Một số câu trả lời khác đã tiến gần đến việc đề cập đến vấn đề này rồi, nhưng trong nhiều ngôn ngữ (được gõ đúng?), Nó ngắn hơn để khởi tạo xthành chuỗi rỗng như:

x:=""

hoặc xlà rune trống (char) như:

x:=''

hơn

var x string

var x rune

Sử dụng các giá trị từ trước rõ ràng là được ưa thích, nhưng không dễ dàng như vậy.

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.