Mẹo chơi golf trong dc


18

Bạn có lời khuyên chung nào cho việc chơi golf trong dc ?

dc là một tiện ích máy tính cho UNIX / Linux có trước ngôn ngữ C. Tôi quan tâm đến cách làm cho các chương trình dc (tính toán?) Của tôi ngắn hơn. Tôi đang tìm kiếm những ý tưởng có thể được áp dụng cho nói chung ít nhất là một chút cụ thể cho dc (ví dụ: xóa bình luận không phải là một câu trả lời hữu ích)

Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.


7
Sử dụng Marvel thay thế.
Bạch tuộc ma thuật Urn

Câu trả lời:


6

Câu lệnh if-then-other

Giả sử chúng ta muốn kiểm tra điều kiện a==b(hãy để abđược lưu trữ trong các thanh ghi có tên tương ứng của chúng).

biên tập:
[         # Everything is wrapped in one big macro
  [         # An inner macro for our *then* part
              # <-- Stuff to execute if a==b here
  2Q          # Then quit the inner and outer macro
]sE       # `E' is for Execution register ;)
la lb =E  # if a==b, execute E
          # if E is executed, it will quit the whole macro, so the rest is never reached:
          # <-- Stuff to execute if a!=b here
]x        # End macro; Execute

Hãy (foo)là một người giữ chỗ, cho mục đích ngưng tụ:

[[(then)2Q]sE(condition)E(else)]x

Khá chắc chắn rằng đây là nhỏ gọn nhất nếu tuyên bố có thể (cũng được nêu ở đây ).


1
Có lẽ [[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI flà một sự khởi đầu? Các hành động cho tehn và các hoạt động khác nằm trên stack, Imacro "f" hoán đổi chúng và được điều chỉnh theo điều kiện. sau đó đỉnh của ngăn xếp sẽ được thực thi và macro không sử dụng sẽ được thả vào I để dọn sạch ngăn xếp. 2 4chỉ là dữ liệu ví dụ để so sánh. Ngoài ra, [x]sIphần có thể được chuyển sang so sánh, nếu được coi là dễ đọc hơn : [[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI f. Các fví dụ trong sẽ chỉ ra rằng ngăn xếp sạch sẽ sau đó ...

1
Trang của Rosetta Code về Dc đề cập đến 3 hương vị dcvà đó là trang đầu tiên tôi thấy cấu trúc dccủa OpenBSD if-then-else. Tôi nghĩ rằng chúng tôi cần một dcgói quạt có cả 3 hương vị cho tất cả các hệ điều hành chính ... o :-) ... và if-then-elseđề xuất của tôi ở trên không hoạt động trên bản gốc dcvì nó thiếu rlệnh ... :-(

1
Điều gì về: [[(if)2Q]si(condition)i(else)]x- gói toàn bộ mọi thứ trong một macro và phần if bên trong một macro khác bên trong đó, để bạn có thể 2Qthoát khỏi toàn bộ trước khi tiếp cận với phần khác. Vì vậy, nếu bạn muốn làm nếu 1 == 1 sau đó in 1 bản in 2 khác , thì nó sẽ được 1[[1P2Q]si1=i2P]x(chưa được kiểm tra vì tôi không có quyền truy cập vào dc ngay tại đây và bây giờ. Tôi cũng chắc chắn rằng tôi đã thực hiện thủ thuật này trong câu trả lời ở đây trước đây nhưng không thể tìm thấy nó)
daniero

Yup, tôi đã làm toán, đề nghị của tôi ngắn hơn. Với cùng một ví dụ và "ký hiệu" và loại bỏ khoảng trắng, nó khác [/*else*/]sE[[/*then*/]sE]sIlalb=IlExvới [[/*then*/2Q]sIlalb=I/*else*/]x- 6 byte. Vẫn chưa được kiểm tra: P
daniero 17/8/2016

1
Làm tốt lắm, @daniero! Tôi sẽ cập nhật bài viết khi tôi có thời gian, hoặc bạn có thể làm nó nếu bạn muốn.
Joe

5

Bạn có thể lưu dữ liệu đầu vào với d

Bằng cách sử dụng d, sao chép ToS (đầu ngăn xếp), bạn có thể di chuyển đầu vào ra khỏi đường để sử dụng sau, trong khi vẫn có thể sử dụng nó.


@NoOneIsCó thật tuyệt !!! Cảm ơn!
Rɪᴋᴇʀ

5

Mảng

Mặc dù họ đang đau đầu cho người mới bắt đầu, dccung cấp mảng. Họ làm việc như thế này:

value index :a    # store `value' in array linked to top of stack `a', with index `index'
      index ;a    # push a[index] on (main) stack

Như thường lệ, phần tử đầu tiên có chỉ số 0. Mảng có thể hữu ích khi làm việc với các chuỗi, như trong chuỗi SUDSI , đặc biệt là kết hợp với các bộ đếm. Mảng có thể giảm số lần xáo trộn số bạn cần làm (và số lượng bộ đếm và so sánh) nếu bạn muốn chọn một yếu tố cụ thể mà không phá hủy môi trường của bạn. Ví dụ: nếu bạn muốn di chuyển một chồng số vào một mảng, bạn có thể viết một hàm đệ quy sử dụng z(độ sâu ngăn xếp) hoặc z 1-làm chỉ mục, lưu trữ phần tử và kiểm tra xem có z == 0tự chấm dứt hay không.

[z 1- :a z 0 !=F]dsFx    # or I could just write such a function for you :)

Hãy lưu ý những điều sau:

  • Mảng được liên kết với các trường hợp trên ngăn xếp được đặt tên. Nếu bạn đẩy một giá trị mới trên ngăn xếp có một mảng được liên kết với nó, mảng đó cũng sẽ bị "đẩy lùi" và một mảng "mới" sẽ thay thế nó. Mảng cũ sẽ không thể sử dụng được cho đến khi giá trị tương ứng trên ngăn xếp được đặt tên cũng có thể sử dụng được (nghĩa là trên đỉnh ngăn xếp của nó). Đây là một khái niệm phức tạp sẽ được giải thích tốt hơn với một hình ảnh động tốt, nằm ngoài tôi.
  • Bạn có thể lưu trữ các thứ trong một mảng được đặt tên mà không thực sự đẩy một giá trị vào thanh ghi có tên tương ứng. Tuy nhiên, nếu bạn làm điều này, bạn không thể truy cập ngăn xếp / đăng ký với tên đó cho phần còn lại của phiên. dcsẽ sụp đổ.
  • Nếu bạn bật một giá trị ra khỏi ngăn xếp có tên, mọi giá trị trong mảng tương ứng sẽ bị mất không có cảnh báo, không có biện pháp bảo vệ, không có gì. Chỉ cần đi (cũng có thể hữu ích).

Công việc tốt với các mẹo DC!
Rɪᴋᴇʀ

dccó thể đã được cập nhật gần đây và hành vi mảng có thể đã thay đổi một chút liên quan đến sự cố. Không thể xác nhận ngay bây giờ, nhưng tôi nghĩ có gì đó khác lần trước khi tôi sử dụng nó trên Linux.
Joe

1
Nếu bạn cố đọc chỉ mục từ một mảng chưa được đặt, bạn sẽ nhận được 0 và không có lỗi. Điều này có thể rất hữu ích, nhưng cũng đáng lưu tâm nếu bạn có khả năng đặt 0 vào mảng ... Bạn sẽ cần một cách khác để kiểm tra xem chỉ mục đã được chạm vào chưa.
brhfl

5

0 đến sức mạnh thứ n thay vì các điều kiện / macro

Đôi khi bạn có thể cần một cái gì đó như ternary có điều kiện:

A == B ? C : D;

Một cách hay để xử lý việc này được mô tả trong câu trả lời của @ Joe . Tuy nhiên chúng ta có thể làm tốt hơn:

0AB-^E*C+

Trong đó E là D - C.

Điều này kiểm tra sự bằng nhau bằng cách tăng 0 lên sức mạnh của sự khác biệt của hai giá trị. Điều này dẫn đến 1 nếu bằng và 0 khác. Phần còn lại chỉ chia tỷ lệ 1 hoặc 0 cho các giá trị C hoặc D. Điều này hoạt động vìdc cho 0 0 = 1 và 0 n = 0 cho n! = 1.


4

Đôi khi cần phải loại bỏ một số từ ngăn xếp. Một cách để làm điều này là chỉ cần đưa nó vào một biến không sử dụng, tức là st. Tuy nhiên, trong một số trường hợp, bạn có thể đưa nó đến một vài nơi khác, ví dụ: cơ sở đầu vào khi bạn không còn đầu vào số hoặc cho bộ xác định chính xác nếu bạn không có thêm thao tác nào để làm chính xác sẽ tạo ra sự khác biệt. Trong trường hợp trước, sử dụng i. Trong trường hợp sau, sử dụng k.


Nếu đầu ra số không quan trọng, ocũng có thể được sử dụng. Và nếu bất kỳ thứ nào trong số này không quan trọng, chúng có thể được sử dụng làm bộ lưu trữ cũng như loại bỏ - I/ K/ Ogọi lại chúng tương ứng và lưu byte quasa / lavv Các giá trị hợp lệ AFAIK: i2-16; kbất kỳ số nguyên không âm; obất kỳ số nguyên nào lớn hơn 1.
brhfl

4

Chiều dài tính: Z, X, vàz

Zbật ToS và đẩy số chữ số (thập phân) nếu đó là số hoặc số ký tự nếu đó là một chuỗi. Điều này có thể hữu ích để phát hiện độ dài của kết quả (đối với đầu ra đệm) hoặc độ dài chuỗi tính toán. Lưu ý rằng đối với các số, Zđẩy chiều dài kết hợp của phần nguyên và phần phân số.

Xbật ToS và đẩy số chữ số trong phần phân số của số. Nếu ToS là một chuỗi, 0được đẩy.

Để tìm số chữ số trong phần nguyên của số, người ta có thể sử dụng dZrX-. Nếu bạn không thay đổi độ chính xác từ mặc định k==0, việc sử dụng 1/Zsẽ ngắn hơn, nhưng giả sử bạn cần duy trì độ chính xác khác không sau khi thao tác: Kr0k1/Zrkđúng hơn là mỏi mắt.

zđẩy số lượng vật phẩm trên ngăn xếp. Một trong những lệnh yêu thích của tôi, nó không thực sự bật bất kỳ giá trị nào! Nó có thể được sử dụng để tạo ra một chuỗi các số hoặc tăng một bộ đếm. Sử dụng zdnhiều lần (giả sử, khi bắt đầu macro) có thể cho phép một phép tính trên mỗi số tự nhiên hoặc toàn bộ theo thứ tự tăng dần.


Đã từng sử dụng zcho điều này và điều đó trước đây, nhưng chưa bao giờ xảy ra với tôi để sử dụng nó như là một bản hack của một đối thủ xuất sắc
brhfl

4

Chữ số A để Fcó thể được sử dụng thay thế cho những con số từ 10 đến 15. Tuy nhiên họ vẫn phải được xử lý một cách hiệu quả như cơ sở 10 chữ số (giả sử cơ sở đầu vào là 10) khi ở những nơi khác nhau. Nói cách khác, với cơ sở đầu vào 10 FFsẽ không đại diện cho 255, nó sẽ đại diện (15 * 10) + 15hoặc 165.

Trong thực tế này làm việc cho tất cả các chữ số 0để Ftrong bất kỳ cơ sở đầu vào 2để16 . Vì vậy, nếu cơ sở đầu vào là 5, thì 26Esẽ là (2 * 5^2) + (6 * 5) + 1494.

Lưu ý hành vi này có hiệu lực đối với các nguồn GNU chưa sửa đổi. Tuy nhiên, như @SophiaLechner chỉ ra, các distro dựa trên RedHat dường như sử dụng bc-1.06-dc_ibase.patch làm thay đổi hành vi này để các chữ số> = ibase được coi là ibase - 1, bất kể giá trị thực của chúng. Lưu ý rằng TIO dc dường như không có bc-1.06-dc_ibase.patch (mặc dù Fedora 28 _ (ツ) _ /) của nó.


Điều này không hoàn toàn đúng - mặc dù các chữ số đơn phía trên cơ sở đầu vào được hiểu như bạn hy vọng, nếu chữ có nhiều chữ số hoặc thậm chí là dấu thập phân, các chữ số không hợp lệ cho cơ sở được hiểu là (cơ sở 1). Vì vậy, trong cơ sở đầu vào 10 FFđại diện 99, trong cơ sở đầu vào 5 26Egiống như 244, cơ sở 10 74.
Sophia Lechner

@SophiaLechner Bạn có chắc không? tio.run/##S0n@/9/QIJ/L0CCTy82tgMs0k8vIzLXg/38A Những dcphiên bản bạn có đang chạy? Tôi đang sử dụng GNU dc 1.4.1 trên Ubuntu và GNU dc 1.3 trên MacOS
Chấn thương kỹ thuật số

Hấp dẫn. Tôi đang chạy 1.3.95 trên Red Hat và đây là chương trình mẫu của bạn: [slechner @ XXX] $ dc -e '10o 10i FFp 5i 26Ep' 99 74 [slechner @ XXX] $ dc --version dc (GNU bc 1.06 .95) 1.3.95
Sophia Lechner

Argh ... không thể làm cho khối mã hoạt động trong bình luận. Điểm đáng chú ý là FFpđầu ra 99trong 1.3,95. Bạn có thể kiểm tra điều này trong phiên bản MacOS của bạn không?
Sophia Lechner

1
Chắc chắn rồi! Cảm ơn bạn cho tất cả các nghiên cứu.
Sophia Lechner

2

Khi khởi tạo một macro chức năng (chúng tôi sẽ sử dụng F) mà bạn muốn chạy ngay lập tức, hãy sử dụng một cái gì đó giống như dsFxhơn là sFlFx. Các công việc tương tự cho các biến: dsachứ không phải sala.

Nếu bạn cần thực hiện các công việc khác ở giữa lưu trữ và tải (ví dụ sa[other stuff]la:), vẫn xem xét liệu điều trên có khả thi hay không: Nếu bạn để một giá trị trên ngăn xếp trước các hoạt động khác, cuối cùng nó sẽ trở lại đầu trang của những hoạt động?


2

Chỉ cần phát hiện ra điều này một cách tình cờ. Tuy nhiên, một cách khác để tạo số 0 : _.

_là một tín hiệu cho dc rằng các chữ số sau đây là một số âm. Thí dụ:

_3 # pushes -3

Nhưng nếu chúng ta không theo dõi nó với một con số thì sao?

_ # pushes 0...sometimes

Điều này hoạt động khi ký tự không trống tiếp theo sau dấu gạch dưới không phải là một chữ số. Nếu một chữ số theo sau nó, ngay cả sau một dòng mới, nó được hiểu là một dấu âm.

c4 5_6  # -6,5,4
c4 5_ 6 # -6,5,4
c4 5_
6       # -6,5,4 # still a negative sign since the next thing it sees is a digit
c4 5_z  #  3,0,5,4 # if it's followed by a non-digit, it's a 0
c4 5_p6 #  6,0,5,4
c4 _*   #  0 # 4*0=0

1

Nếu nội dung của toàn bộ ngăn xếp cần in ở cuối chương trình, một vòng lặp macro đệ quy có thể được sử dụng để đạt được điều này. Tuy nhiên, nó chỉ ngắn hơn nhiều để sử dụng flệnh.


1

dcđọc đầu vào một dòng tại một thời điểm. Nếu bạn cần đọc trong nhiều mục, thực hiện một mục trên mỗi dòng hoặc yêu cầu ?mỗi dòng phải được đọc hoặc một vòng lặp macro rườm rà. Thay vào đó, nếu tất cả các mục đầu vào có thể được đặt trên một dòng được phân tách bằng dấu cách, thì một dòng? sẽ đọc tất cả các mục đầu vào, đẩy từng mục vào ngăn xếp.

Ví dụ trong seq 10 | dc -e'?f', seqkết quả đầu ra số nguyên 1-10, mỗi dòng một. các ?chỉ sẽ đọc đầu tiên 1mà sẽ được xuất ra khi fbãi toàn bộ stack. Tuy nhiên seq 10 | tr '\n' ' ' | dc -e'?f', trlàm cho các số nguyên đầu vào tách tất cả không gian. Trong trường hợp này, ?nó sẽ đọc tất cả các số nguyên từ dòng trong một lần và fsẽ xuất ra tất cả.


1

Nếu một toán tử bị hạn chế từ nguồn, hãy tạo một cái mới với a

Một vài điều có ích cho tôi đôi khi bây giờ là tránh sử dụng một toán tử cụ thể bằng cách đẩy giá trị ASCII của toán tử, sử dụng ađể chuyển đổi nó thành một chuỗi và sử dụng nó strong một thanh ghi để được thực thi như một macro sau này trên. Ví dụ, tôi cần thực hiện phép chia, nhưng không được phép hoặc cố gắng tránh sử dụng ký tự /. Tôi có thể, thay vào đó làm 47asdvà sau đó trong tương lai khi tôi cần chia 16 cho 4 16 4 ldx,.

  • Điều này sẽ chỉ hoạt động cho các toán tử một ký tự (không thể tạo chuỗi) và sẽ không hoạt động đối với các lệnh như s cần phải được hậu tố bởi một cái gì đó.
  • Điều này thêm khá nhiều byte và do đó chỉ phù hợp khi tránh ký tự cụ thể là cần thiết hoặc bằng cách nào đó có được phần thưởng điểm.

1

Tránh khoảng trắng

Tránh khoảng trắng xuất hiện trong một vài thử thách, và nói chung là dễ dàng dc. Ngoài các chuỗi, thời gian rất cụ thể mà khoảng trắng trở nên cần thiết là khi đẩy nhiều số liên tiếp:1 2 3 . Nếu điều này phải tránh:

  • Thực hiện một macro trống ở giữa: 1[]x2[]x3[]x .
  • Nếu dấu ngoặc nằm ngoài bảng, lưu trữ NOP của macro trước thời hạn: 35asnvà thực hiện ở giữa : 1lnx2lnx3lnx.

Bạn cũng có thể dấu phẩy các số riêng biệt, nếu bạn sẵn sàng đưa ra các dc: ',' (054) unimplementedcảnh báo.
Chấn thương kỹ thuật số

Tôi đã không nghĩ về điều đó - có lẽ áp dụng cho bất kỳ mã thông báo cụ thể nào không giải quyết được lệnh
Cấm
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.