Mẹo chơi gôn theo đợt


14

Windows Batch (CMD) có lẽ là ngôn ngữ ít phù hợp nhất để chơi gôn.

Tránh các ký tự dòng mới . Nếu bạn đang tìm mã ngắn nhất tính theo byte, trái ngược với ký tự, bạn sẽ muốn loại bỏ tất cả các trả về vận chuyển không cần thiết (ký tự dòng mới = 2 byte). Bạn có thể sử dụng &thao tác để thực hiện việc này, cắt bớt một byte cho mỗi lệnh.

echo Hello&echo World.

Đặt biến . Khi cài đặt biến bằng các công tắc, settrình phân tích cú pháp sẽ bỏ qua khoảng trắng.

set /a a+=1
set /p b="User Input: "
:: Will be handled the same as..
set/aa+=1
set/pb="User Input: "

Lưu ý rằng các quy tắc phân tích cú pháp tương tự không áp dụng cho tất cả các lệnh - như một ví dụ, cho các vòng lặp yêu cầu khoảng trắng. Ngoại trừ giữa set, string, or command(tức là những gì bên trong ngoặc) và từ do.

for /f %%a in (file.txt)do ...

Biểu thức toán học đơn giản . Ngoài ra, hãy chú ý biểu thức mà tôi đã sử dụng để tăng trong set /alệnh. Đối với các biểu thức toán học đơn giản sử dụng += -= *= /=thay vì (ví dụ) set /a a=%a%+1.

Tập hợp đầu ra lệnh . Để có được đầu ra của một lệnh, đôi khi có thể hữu ích khi xuất và đọc từ một tệp, trong đó bạn có thể đã sử dụng một vòng lặp for để thu thập đầu ra:

for /f %%a in ('echo test') do set a=%%a
:: Can be shortened to
echo test>f&set/pa=<f

echo testgửi thiết bị xuất chuẩn đến một tệp có tên f, >fbắt đầu một lệnh mới &và nhận nội dung của tệp trong một biến set/pa=<f. Rõ ràng điều này không phải lúc nào cũng hữu ích. Nhưng nó có thể là khi tất cả những gì bạn cần là một dòng đầu ra.

Đầu ra lệnh . Khi chặn đầu ra lệnh, sử dụng @trước các lệnh, trừ khi bạn cần triệt tiêu hơn 9 lệnh, trong trường hợp đó, sử dụng @echo offkhi bắt đầu tập lệnh của bạn. @echo offdài 9 byte và do đó thường sẽ tiết kiệm được nhiều byte hơn với các tập lệnh dài hơn.

Các lệnh thường làm nhiều hơn chỉ là những gì rõ ràng - hãy nghĩ về những gì các lệnh của bạn đang làm. Ví dụ; nếu bạn cần đặt một biến và lặp lại một biến khác, thay vì:

set a=OUTPUT
echo %a%
echo test>f
set /p b=<f

Bạn có thể sử dụng lệnh set với công /ptắc để xuất %a%cho bạn.

set a=OUTPUT
echo test>f
set /p b=%a%<f

Hoàn toàn chơi gôn ...

set a=OUTPUT&echo test>f&set/pb=%a%<f

Một vài ví dụ - Đếm tổng của tất cả các chữ số - phỏng đoán của Goldbach .

Bất kỳ lời khuyên nào khác đều được đánh giá cao hơn - tôi sẽ tiếp tục cập nhật điều này nếu tôi nghĩ về bất cứ điều gì khác.


16
Xin vui lòng gửi các phần trả lời của điều này như là một câu trả lời, không phải là một phần của câu hỏi.
Không phải Charles

@Charles Tôi khá chắc chắn làm thế nào tôi đã thực hiện đây là một định dạng có thể chấp nhận được cho một 'câu hỏi mẹo'. Những người khác có thể thêm câu trả lời với lời khuyên của riêng họ.
mở cửa

Câu trả lời:


4

Quầy

Bất cứ khi nào bạn có một biến sẽ hoạt động như một bộ đếm bắt đầu từ 0bạn có thể muốn viết

set count=0
set/acount+=1

; tuy nhiên, bạn có thể loại bỏ các dòng đầu tiên bởi vì bất cứ khi nào set/ađược sử dụng với một biến unset, giá trị của nó được coi là0

set/acounter+=1

Khối mã

Có một số cách bạn có thể cạo một vài byte khi bạn phải sử dụng các khối mã.

Bất cứ khi nào bạn mở một khối mã, bạn không cần phải chèn ngắt dòng trước dòng mã đầu tiên trong khối đó. Các dấu ngoặc đơn đóng cũng không phải nằm trên một dòng của chính nó.

If %a%==%b% (
     echo true
) else (
    echo false
)

có thể chơi gôn

If %a%==%b% (echo true)else (echo false)

In mà không cần dòng mới

Mô hình chung cho việc này là

echo|set/p=text

nhưng, bạn có thể lưu 2 byte thay đổi echothànhcd

cd|set/p=text

2
@ ankp-morpork Này, tôi hơi muộn. Nhưng tôi muốn thông báo cho bạn rằng iftuyên bố có thể được đánh gôn hơn nữa. Cách tốt nhất nên là:if %a%==%b% (echo true)else echo false
stevefestl 16/07/17

3

Ampersands

Mặc dù & làm cho mã có vẻ ngắn hơn, vì nó sử dụng ít dòng hơn, nhưng nó sử dụng nhiều ký tự như một dòng mới. Điều này có nghĩa rằng

echo a&echo b

miễn là

echo a
echo b

để mã của bạn có thể đọc được mà không lãng phí ký tự.

Có thể có ngoại lệ vì một số trình soạn thảo văn bản kết hợp nguồn cấp dữ liệu và trả về carridge cho mỗi dòng mới.


Tôi đã bao gồm điều này trong bài viết gốc vì một dòng mới tính hai byte trong mỗi trình soạn thảo văn bản tôi sử dụng. Cảm ơn đã thêm làm rõ này.
khai mạc

2
Nguồn cấp dữ liệu trả về carraige của Window là hai ký tự và nhiều trình soạn thảo văn bản sẽ tính nó là hai, nhưng khi tôi mới bắt đầu trả lời các câu hỏi về golf, một trong những ý kiến ​​còn lại nói rằng trong các kết thúc dòng PPCG luôn được tính là một ký tự.
Jerry Jeremiah

2
Các nguồn cấp dữ liệu theo phong cách Unix sẽ chỉ hoạt động tốt trong các tập lệnh CMD, ít nhất là trong các phiên bản gần đây của Windows.
dùng2428118

1
Trên thực tế, CMD thậm chí còn xóa các ký tự CR trước khi phân tích cú pháp: stackoverflow.com/questions
40464699 / Giả

3

In trực tiếp kết quả tính toán số

Nếu thử thách yêu cầu bạn xuất ra một số cần tính toán, bạn có thể sử dụng cmd/c set/ađể xuất kết quả tính toán trực tiếp thay vì lưu phép tính và sau đó lặp lại số đó. Thí dụ:

@set/a a=%1+%2
@echo %a%

trở thành

@cmd/cset/a%1+%2

Chỉnh sửa: Rõ ràng không có khoảng trống nào là cần thiết cả, tiết kiệm thêm 2 byte.


2

Trì hoãn mở rộng

Thay vì sử dụng thời lượng dài, setLocal enableDelayedExpansionbạn có thể sử dụng cmd /v on(hoặc cmd/von) sẽ khởi động trình thông dịch mới với tính năng mở rộng biến bị trì hoãn được bật.

Tôi vẫn chưa thực hiện điều này vì vậy tôi không có bất kỳ ví dụ nào, nhưng bạn có thể sử dụng kết hợp với công /ctắc này. Thí dụ:

@cmd/von/cset test=test^&echo !test!

Lưu ý việc sử dụng carat trước ký hiệu. nếu bạn cần sử dụng nhiều ký hiệu hoặc bất kỳ ký tự đặc biệt nào khác, bạn có thể tốt hơn hết là bao quanh mọi thứ sau khi /cchuyển đổi trong dấu ngoặc kép:

@cmd/von/c"set test=test&set test1=test1&echo !test! !test1!"

Phương pháp này cũng có ưu điểm là chỉ phải sử dụng một @ký tự để che dấu tất cả đầu vào, và do đó có thể được sử dụng mà không phải /vonlà một cách thay thế ngắn hơn cho @echo off(hoặc nhiều @ký hiệu).

9 ký tự: @echo off
6 ký tự:@cmd/c

Đối với các tập lệnh dài hơn mà bạn không thể thực hiện trên một dòng, bạn có thể thực hiện các thao tác sau để lưu một số byte:

@!! 2>nul||cmd/q/v/c%0&&exit/b

Hoặc, vô danh:

@!! 2>nul || cmd /q /v on /c %0 && exit/b

Thay thế @echo off&setLocal enableDelayedExpansionbằng ở trên.

Khi bạn lần đầu tiên chạy tập lệnh của bạn !!sẽ không mở rộng, vì vậy bạn nhận được một lỗi vì đó "!!"không phải là một lệnh. Đầu ra lỗi sau đó được dẫn đến nul ( 2>nul). Khi 'lệnh' đầu tiên này thất bại ( ||), nó gọi một thể hiện mới của cmd, nó gọi chính tệp bó (sử dụng /v (on)để kích hoạt mở rộng bị trì hoãn và /qđể tắt tiếng vang). Sau đó !!sẽ mở rộng thành không có gì, vì không có biến được gọi <NULL>. Phần còn lại của kịch bản của bạn sau đó chạy. Sau đó, nó sẽ trở về phiên bản gốc của cmd và &&thoát ( ) với /bđiều kiện để giữ cho cửa sổ mở (lối ra để nó không tiếp tục chạy qua tập lệnh của bạn trong ngữ cảnh của trường hợp cmd đầu tiên, có tiếng vang bật và trì hoãn mở rộng).


Đối với điều này, việc chạy các tệp bó cmd /q /v on /c <filename>chỉ nên được tính là 2 byte vì chúng là hai "cờ" tương tự như các cờ Perl giống như -pIchỉ được tính là 2 byte thêm.
Artyer

1

Chuỗi lặp đi lặp lại

Đặt các khối mã lặp lại trong các biến, trong đó số byte được sử dụng để đặt biến + số byte để xuất biến đó nhỏ hơn số byte để chỉ gọi trực tiếp mã.

Ví dụ: xem: Vẽ các kết hợp có thêm tới 100

Bạn lưu 1 byte cho mỗi lần sử dụng lệnh set, nếu bạn tạo một biến (được đặt tên bằng một ký tự, như "s") có chứa set<space>. Điều này chỉ tạo ra giá trị nếu bạn sử dụng lệnh set hơn 12 lần. (Lưu ý có một ký tự ở cuối chuỗi set s=set).

set s=set 
%s%a=1
%s%b=2
%s%c=3
%s%d=4
%s%e=5
%s%f=6
%s%g=7
%s%h=8
%s%i=9
%s%j=10
%s%k=11
%s%l=12
%s%m=13

Trên đây là 1 byte ngắn hơn ..

set a=1
set b=2
set c=3
set d=4
set e=5
set f=6
set g=7
set h=8
set i=9
set j=10
set k=11
set l=12
set m=13

Đây có lẽ là một ví dụ khá nghèo nàn - nhưng nó được ghi điểm.


1

Bắt đầu một chuỗi

Ký hiệu %var:~start,end%trích xuất một chuỗi con của biến var. Tuy nhiên nếu start0thì bạn có thể bỏ qua nó hoàn toàn. Chúng tôi đã biết rằng bạn có thể bỏ qua ,endnếu bạn muốn phần còn lại của chuỗi, điều này tạo ra %var:~%một từ đồng nghĩa gần như vô dụng %var%, ngoại trừ việc nó trả về ~khi %var%trống. (Có lẽ bạn có thể sử dụng nó trong một bài kiểm tra : if %var:~%==~?)


Tôi thích câu cuối cùng của bạn nhắc nhở chúng tôi điều này sẽ tiết kiệm một số trích dẫn :) +1 cho điều đó.
stevefestl

1

Rút ngắn IF EQUbáo cáo

if %a% equ %b% do_something
if %a%==%b% do_something

Sử dụng ==thay vì equ tiết kiệm 3 byte.


Rút ngắn trích dẫn trong IFbáo cáo

Đây là một cách gọi truyền thống được gọi là "an toàn hơn" if.

if "%a%"=="%b%" do_something

Để rút ngắn tuyên bố này, làm như sau khi đầu vào chỉ có thể là alphanumerical / trống :

if %a%.==%b%. do_something

Tiết kiệm tổng cộng 2 byte.


Những thách thức đòi hỏi đầu ra

Nếu câu hỏi nói lên điều gì đó như:

Xuất ra ít nhất 1 ký tự hiển thị.

sau đó bạn có thể làm điều này:

cd

Các cdlãm thư mục hiện hành để STDOUT.


GOTOmột nhãn hiệu

Đây là một số phương pháp gotolấy nhãn, được sắp xếp theo thứ tự giảm dần của byte.

goto :l
goto l
goto:l

Phương pháp trên tiết kiệm 1 byte.


1
Ngoài ra, bạn có thể thực hiện việc goto:llưu cùng 1 byte có thêm phần thưởng để giữ nguyên dấu hai chấm của bạn
Matheus Avellar

@MeditusAvellar: Tôi đã thêm nội dung phù hợp vào bình luận của bạn
stevefestl

1

Bỏ khoảng trắng giữa lệnh và tham số bằng dấu gạch chéo

Xin lỗi về tiêu đề không thông tin. Điều tôi đang cố gắng nhận được là đối với một số (không phải tất cả) lệnh Windows, bạn có thể bỏ qua khoảng trắng ở giữa tên lệnh / chương trình và tham số, miễn là tham số đó bắt đầu bằng dấu gạch chéo. Ví dụ:

for /f %%G in ...

trở thành

for/f %%G in ...

-1 byte!

Đầu ra đường ống thay vì sử dụng ERRORLEVEL

Sử dụng ERRORLEVEL để xác định xem một lệnh chạy chính xác không phải là phương pháp ngắn nhất hoặc thanh lịch nhất. Thay vào đó, bạn có thể đầu ra đường ống. Điều này hoạt động như sau (hãy nhớ rằng bất kỳ lệnh nào sau &&toán tử chỉ thực thi nếu lệnh trước khi &&chạy mà không có lỗi. ||Mặt khác, bất kỳ lệnh nào sau toán tử sẽ chỉ chạy nếu lệnh trước nó không chạy đúng. Ví dụ của tôi là :

net session>nul
if %errorlevel%==0 (echo 1) else (echo 0)

Điều này có thể được thay thế bằng:

net session>nul&&echo 1||echo 0

-26 byte, wow! Lưu ý rằng điều này không hoạt động với các lệnh như choice, trong đó ERRORLEVEL có giá trị đặc biệt theo một số đầu vào.

Trân trọng,
Gabe


1

Sử dụng dấu ngoặc đơn hiệu quả

Chào bạn lần nữa nhé,

Xin lỗi để gửi một câu trả lời thứ hai nhưng tôi cảm thấy điều này xứng đáng với nó. Tôi đã nhận thấy rằng mọi người thường sử dụng một trong các phương pháp sau để hiển thị đầu ra lệnh mà không hiển thị C:\Windows\System32>echo foodòng pesky đó trước mỗi lệnh.
Phương pháp đầu tiên (sử dụng echo off):

@echo off
echo foo
echo bar
echo foobar
echo barfoo

Phương pháp thứ hai:

@echo foo
@echo bar
@echo foobar
@echo barfoo

Tuy nhiên, cả hai phương pháp này đều không ngắn như sau:

@(echo foo
echo bar
echo foobar
echo barfoo)

Khá tiện dụng phải không? Một lưu ý khác, điều này có thể được sử dụng để dẫn nhiều dòng đầu ra đến một tệp hoặc thiết bị một cách dễ dàng. Ví dụ: mã dài này:

echo foo>file.txt
echo bar>file.txt
echo foobar>file.txt
echo barfoo>file.txt

trở nên ngắn hơn đáng kể:

(echo foo
echo bar
echo foobar
echo barfoo)>file.txt

Cảm ơn đã đọc câu trả lời khá dài này, và tôi hy vọng điều này sẽ giúp bạn. Trân trọng,
Gabe


Đăng nhiều câu trả lời cho các câu hỏi mẹo không phải là xấu.
Erik the Outgolfer
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.