เคล็ดลับสำหรับการเล่นกอล์ฟใน dc


18

คุณมีเคล็ดลับทั่วไปสำหรับการเล่นกอล์ฟในdcอย่างไร

dc เป็นยูทิลิตี้เครื่องคิดเลขสำหรับ UNIX / Linux ที่มีมาก่อนภาษา C ฉันสนใจที่จะทำให้โปรแกรม dc (การคำนวณของฉัน) สั้นลง ฉันกำลังมองหาแนวคิดที่สามารถนำไปใช้กับทั่วไปของที่มีความเจาะจงอย่างน้อย dc (เช่นการลบความคิดเห็นไม่ใช่คำตอบที่เป็นประโยชน์)

กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ


7
ใช้ Marvel แทน
Magic Octopus Urn

คำตอบ:


6

คำสั่ง if-then-else

สมมติว่าเราต้องการตรวจสอบสภาพa==b(อนุญาตaและbเก็บไว้ในการลงทะเบียนตามลำดับชื่อ)

แก้ไข:
[         # 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

อนุญาต(foo)เป็นตัวยึดสำหรับจุดประสงค์ในการควบแน่น:

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

ค่อนข้างแน่ใจว่านี่เป็นคอมแพ็คที่สุดถ้าเป็นไปได้ (มีจุดเด่นที่นี่ )


1
อาจ[[thenaction]P][[elseaction]P][r]sI 2 4 =I x sI fจะเป็นการเริ่มต้น? การดำเนินการสำหรับ tehn และอื่น ๆ อยู่บนสแต็กIแมโคร "f" จะทำการสลับและถูกทำให้มีเงื่อนไข จากนั้นส่วนบนสุดของสแต็กจะถูกเรียกใช้งานและแมโครที่ไม่ได้ใช้จะถูกดร็อปใน I เพื่อล้างสแต็ก 2 4เป็นเพียงข้อมูลตัวอย่างในการเปรียบเทียบ อีกทางเลือกหนึ่งส่วนหนึ่งสามารถย้ายไปเปรียบเทียบถ้าถือว่าสามารถอ่านเพิ่มเติมได้ที่:[x]sI ในตัวอย่างเพียงจะแสดงทททสแต็คที่สะอาดหลังจากนั้น ...[[thenaction]P][[elseaction]P] 4 4 [r]sI =I x sI ff

1
หน้า Rosetta รหัสเกี่ยวกับ Dcกล่าวถึง 3 รสชาติdcและนั่นก็คือหน้า 1 ที่ผมเห็น OpenBSD dc's if-then-elseสร้าง ฉันคิดว่าเราจำเป็นต้องมีdcแฟน ๆ ที่มีทั้งหมด 3 รสชาติสำหรับระบบปฏิบัติการที่สำคัญทั้งหมด ... o :-) ... และif-then-elseข้อเสนอของฉันไม่ทำงานบนต้นฉบับdcเพราะไม่มีrคำสั่ง ... :-(

1
สิ่งที่เกี่ยวกับ: [[(if)2Q]si(condition)i(else)]x- ห่อทั้งหมดไว้ในมาโครและ if-part ภายในแมโครอื่นภายในนั้นเพื่อให้คุณสามารถ2Qหลีกทางให้พ้นจากสิ่งทั้งปวงก่อนถึงส่วนอื่น ดังนั้นถ้าคุณต้องการทำถ้า1 == 1 แล้วพิมพ์ 1 อื่นพิมพ์ 2มันจะเป็น1[[1P2Q]si1=i2P]x(ยังไม่ทดลองเพราะฉันไม่สามารถเข้าถึง dc ได้ที่นี่และตอนนี้ฉันแน่ใจว่าฉันได้ทำเคล็ดลับนี้ในคำตอบที่นี่ก่อน แต่ไม่สามารถหาได้)
daniero

ใช่ฉันทำคณิตศาสตร์คำแนะนำของฉันสั้นลง ด้วยตัวอย่างเดียวกันและ "สัญกรณ์" และการลบช่องว่างมันเป็นความแตกต่าง[/*else*/]sE[[/*then*/]sE]sIlalb=IlExvs [[/*then*/2Q]sIlalb=I/*else*/]x- 6 ไบต์ ยังไม่ผ่านการ
ตรวจสอบสรรพากร

1
เยี่ยมมาก @daniero! ฉันจะอัปเดตโพสต์เมื่อฉันมีเวลาหรือคุณสามารถทำได้ถ้าคุณต้องการ
โจส

5

คุณสามารถบันทึกอินพุตด้วย d

ด้วยการใช้dซึ่งทำซ้ำ ToS (ด้านบนสุดของสแต็ค) คุณสามารถย้ายอินพุตออกไปเพื่อใช้ในภายหลังในขณะที่ยังสามารถใช้งานได้


@ ไม่มีใครอยู่นี่เจ๋งมาก !!! ขอบคุณ!
Rɪᴋᴇʀ

5

อาร์เรย์

แม้ว่าพวกเขาจะปวดหัวสำหรับผู้เริ่มต้น แต่ก็dcมีอาร์เรย์ พวกเขาทำงานเช่นนี้:

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

ตามปกติองค์ประกอบแรกมีดัชนี 0 อาร์เรย์จะมีประโยชน์เมื่อทำงานกับลำดับเช่นในลำดับ SUDSIโดยเฉพาะอย่างยิ่งเมื่อรวมกับตัวนับ อาร์เรย์สามารถลดจำนวนการสับจำนวนที่คุณต้องทำ (และจำนวนตัวนับและการเปรียบเทียบ) หากคุณต้องการเลือกองค์ประกอบเฉพาะโดยไม่ทำลายสภาพแวดล้อมของคุณ ตัวอย่างเช่นหากคุณต้องการย้ายจำนวนzสแต็คเป็นตัวเลขลงในอาร์เรย์คุณสามารถเขียนฟังก์ชันแบบเรียกซ้ำที่ใช้(ความลึกสแต็ก) หรือz 1-เป็นดัชนีเก็บองค์ประกอบและตรวจสอบว่าz == 0จะยุติตัวเองหรือไม่

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

ระวังสิ่งต่อไปนี้:

  • อาร์เรย์จะเชื่อมโยงกับอินสแตนซ์ของสแต็กที่มีชื่อ หากคุณกดค่าใหม่ในสแต็กที่มีอาร์เรย์ที่เกี่ยวข้องกับมันอาร์เรย์นั้นจะ "ผลักกลับ" และอาร์เรย์ "ใหม่" จะเข้าแทนที่ อาเรย์เก่าจะไม่สามารถใช้งานได้จนกว่าค่าที่สอดคล้องกันของสแต็กที่ตั้งชื่อจะสามารถใช้งานได้ (เช่นที่ด้านบนของสแต็ก) นี่เป็นแนวคิดที่ซับซ้อนซึ่งจะอธิบายได้ดีกว่าด้วยแอนิเมชั่นที่ดีซึ่งอยู่นอกเหนือฉัน
  • คุณสามารถจัดเก็บสิ่งต่าง ๆ ในอาร์เรย์ที่มีชื่อโดยไม่ต้องผลักดันค่าลงในการลงทะเบียนชื่อที่สอดคล้องกัน อย่างไรก็ตามหากคุณทำเช่นนี้คุณจะไม่สามารถเข้าถึงสแต็ก / ลงทะเบียนด้วยชื่อนั้นสำหรับส่วนที่เหลือของเซสชัน dcจะผิดพลาด
  • หากคุณป๊อปอัพค่าจากสแต็กที่ตั้งชื่อไว้ค่าใด ๆ ในอาร์เรย์ที่เกี่ยวข้องจะหายไป - ไม่มีคำเตือนไม่มีการป้องกันไม่มีอะไรเลย เพิ่งหายไป (ซึ่งอาจมีประโยชน์)

ทำได้ดีด้วยเคล็ดลับ DC!
Rɪᴋᴇʀ

dcอาจได้รับการอัปเดตเมื่อเร็ว ๆ นี้และพฤติกรรมอาเรย์อาจมีการเปลี่ยนแปลงเล็กน้อยเกี่ยวกับการหยุดทำงาน ไม่สามารถยืนยันได้ในตอนนี้ แต่ฉันคิดว่ามีบางอย่างที่แตกต่างไปจากครั้งล่าสุดที่ฉันใช้บน Linux
Joe

1
หากคุณพยายามอ่านดัชนีจากอาร์เรย์ที่ไม่ได้ตั้งค่าไว้คุณจะได้รับ 0 และไม่ใช่ข้อผิดพลาด ซึ่งมีประโยชน์มาก แต่ก็ควรคำนึงถึงหากคุณอาจใส่ 0s ในอาร์เรย์ ... คุณจะต้องมีวิธีอื่นในการทดสอบว่าดัชนีได้รับการสัมผัสแล้ว
brhfl

5

0 ถึงกำลังที่ n แทนที่จะเป็นเงื่อนไข / มาโคร

บางครั้งคุณอาจจำเป็นบางอย่างเช่น ternary เงื่อนไข:

A == B ? C : D;

เป็นวิธีที่ดีในการจัดการนี้ได้อธิบายไว้ใน@ คำตอบของโจ อย่างไรก็ตามเราสามารถทำได้ดีกว่า:

0AB-^E*C+

โดยที่ E คือ D - C

การทดสอบนี้เพื่อความเท่าเทียมกันโดยการเพิ่ม 0 ถึงพลังของความแตกต่างของทั้งสองค่า ผลลัพธ์นี้ใน 1 ถ้าเท่ากับและ 0 เป็นอย่างอื่น ส่วนที่เหลือเพียงแค่ปรับ 1 หรือ 0 ให้เป็นค่า C หรือ D สิ่งนี้ได้ผลเพราะdcให้ 0 0 = 1 และ 0 n = 0 สำหรับ n! = 1


4

บางครั้งมีความจำเป็นต้องทิ้งหมายเลขจากสแต็ก stวิธีหนึ่งที่จะทำเช่นนี้ก็คือการปรากฏมันกลายเป็นตัวแปรที่ไม่ได้ใช้เช่น อย่างไรก็ตามในบางสถานการณ์คุณสามารถนำไปวางไว้ที่อื่นสองสามแห่งเช่นฐานข้อมูลเมื่อคุณไม่มีอินพุตเป็นตัวเลขหรือตัวระบุความแม่นยำหากคุณไม่มีการดำเนินการใด ๆ อีกมากที่ความแม่นยำจะสร้างความแตกต่าง iในกรณีที่อดีตการใช้งาน kในกรณีหลังการใช้


หากเอาต์พุตที่เป็นตัวเลขไม่สำคัญoก็สามารถใช้งานได้เช่นกัน และหากสิ่งเหล่านี้มีความสำคัญพวกเขาสามารถใช้เป็นที่เก็บข้อมูลเช่นเดียวกับทิ้ง - I/ K/ Oจำพวกเขาตามลำดับและบันทึกไบต์มากกว่าsa/ laฯลฯ ค่าที่ถูกต้อง AFAIK: i2-16; kจำนวนเต็มใด ๆ ที่ไม่ต้องการลบ oจำนวนเต็มใด ๆ ที่มากกว่า 1
brhfl

4

ความยาวคำนวณ: Z, Xและz

Zดึง ToS และกดจำนวนหลัก (ฐานสิบ) ถ้าเป็นตัวเลขหรือจำนวนตัวอักษรถ้าเป็นสตริง สิ่งนี้มีประโยชน์สำหรับการตรวจสอบความยาวของผลลัพธ์ (สำหรับบัฟเฟอร์การส่งออก) หรือการคำนวณความยาวสตริง โปรดทราบว่าสำหรับตัวเลขให้Zเลื่อนความยาวรวมของส่วนจำนวนเต็มและส่วนเศษส่วน

Xดึง ToS และผลักดันจำนวนหลักในส่วนของตัวเลข หาก ToS เป็นสตริง0จะถูกส่ง

dZrX-เพื่อหาจำนวนของตัวเลขในส่วนจำนวนเต็มของจำนวนหนึ่งอาจจะใช้ หากคุณไม่ได้เปลี่ยนความแม่นยำจากค่าเริ่มต้นการk==0ใช้1/Zจะสั้นลง แต่สมมติว่าคุณต้องรักษาความแม่นยำที่ไม่เป็นศูนย์โดยเฉพาะหลังจากการดำเนินการ: Kr0k1/Zrkค่อนข้างจะเป็นนัยน์ตา

zเพิ่มจำนวนของไอเท็มบนสแต็ก หนึ่งในคำสั่งที่ชื่นชอบมันไม่ได้ปรากฏค่าใด ๆ ! มันสามารถใช้ในการสร้างลำดับของตัวเลขหรือเพิ่มเคาน์เตอร์ การใช้zdซ้ำ ๆ (พูดที่จุดเริ่มต้นของแมโคร) สามารถให้หนึ่งการทดสอบการคำนวณในแต่ละจำนวนธรรมชาติหรือจำนวนทั้งหมดในลำดับจากน้อยไปมาก


เคยใช้zสิ่งนี้มาก่อนแล้ว แต่ไม่เคยเกิดขึ้นกับฉันเลยที่จะใช้มันเป็นแฮ็คของตัวนับ ... ยอดเยี่ยม…
59

4

ตัวเลขAที่Fอาจใช้แทนค่าตัวเลข 10 ถึง 15 อย่างไรก็ตามจะต้องได้รับการปฏิบัติอย่างมีประสิทธิภาพเช่นเดียวกับฐาน 10 หลัก (สมมติว่าฐานอินพุตคือ 10) เมื่ออยู่ในสถานที่ต่างกัน กล่าวอีกนัยหนึ่งด้วยฐานป้อน 10 FFจะไม่แสดง 255 มันจะแทน(15 * 10) + 15หรือ 165

ในความเป็นจริงงานนี้สำหรับตัวเลขทั้งหมด0จะFอยู่ในฐานป้อนข้อมูลใด ๆที่จะ2 16ดังนั้นถ้าฐานอินพุตเท่ากับ 5 26Eจะเท่ากับ(2 * 5^2) + (6 * 5) + 14หรือ 94

หมายเหตุพฤติกรรมนี้มีผลกับแหล่ง GNU ที่ไม่ได้แก้ไข อย่างไรก็ตามในขณะที่ @SophiaLechner ชี้ให้เห็นว่า distros ที่ใช้ RedHat ดูเหมือนจะใช้bc-1.06-dc_ibase.patchซึ่งเปลี่ยนพฤติกรรมนี้เพื่อให้มีการใช้ตัวเลข> = ibase ibase - 1โดยไม่คำนึงถึงค่าจริง โปรดทราบว่า TIO นั้นdc ไม่มี bc-1.06-dc_ibase.patch (แม้ว่า Fedora จะ 28 ¯_ (ツ) _ / ¯)


สิ่งนี้ไม่ถูกต้อง - แม้ว่าตัวเลขหลักเดียวเหนือฐานอินพุตจะถูกตีความอย่างที่คุณคาดหวังหากตัวอักษรมีหลายหลักหรือแม้แต่จุดทศนิยมตัวเลขที่ไม่ถูกต้องสำหรับฐานจะถูกตีความว่าเป็น (ฐาน -1) ดังนั้นในการป้อนข้อมูลฐาน 10 FFหมายถึง99ในฐานการป้อนข้อมูล 5 26Eเป็นเช่นเดียวกับ244คือฐาน 7410
Sophia Lechner

@SophiaLechner คุณแน่ใจหรือไม่ tio.run/##S0n@/9/QIJ/L0CCTy82tgMs0k8vIzLXg/38Adcคุณกำลังใช้เวอร์ชั่น ใดอยู่ ฉันใช้ GNU dc 1.4.1 บน Ubuntu และ GNU dc 1.3 บน MacOS
Digital Trauma

น่าสนใจ ฉันใช้ 1.3.95 กับ Red Hat และนี่คือโปรแกรมตัวอย่างของคุณ: [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

อ๊ะ ... ไม่สามารถทำให้การบล็อกรหัสทำงานในความคิดเห็นได้ ประเด็นก็คือFFpผลลัพธ์99ใน 1.3.95 คุณช่วยตรวจสอบเรื่องนี้ในเวอร์ชั่น MacOS ของคุณได้ไหม?
Sophia Lechner

1
แน่นอน! ขอบคุณสำหรับการวิจัยทั้งหมด
Sophia Lechner

2

เมื่อ initialising ฟังก์ชั่นมาโคร (เราจะใช้F) ที่คุณต้องการที่จะทำงานทันทีบางสิ่งบางอย่างเช่นการใช้งานมากกว่าdsFx sFlFxการทำงานเหมือนกันสำหรับตัวแปรมากกว่าdsasala

หากคุณจำเป็นต้องทำสิ่งอื่น ๆ ระหว่างการจัดเก็บและการโหลด (เช่นsa[other stuff]la) ยังคงพิจารณาว่าข้างต้นเป็นไปได้หรือไม่: ถ้าคุณปล่อยให้ค่าบนกองซ้อนก่อนการดำเนินการอื่น ๆ มันจะกลับมาที่จุดสูงสุดในตอนท้าย ของการดำเนินงานเหล่านั้นหรือไม่


2

เพิ่งค้นพบสิ่งนี้โดยบังเอิญ อีกวิธีในการสร้างศูนย์: _.

_เป็นสัญญาณให้ dc ว่าตัวเลขต่อไปนี้เป็นจำนวนลบ ตัวอย่าง:

_3 # pushes -3

แต่ถ้าเราไม่ทำตามด้วยตัวเลขล่ะ?

_ # pushes 0...sometimes

สิ่งนี้จะทำงานได้เมื่ออักขระที่ไม่ว่างถัดไปถัดจากขีดล่างไม่ใช่ตัวเลข หากตัวเลขตามหลังแม้ว่าขึ้นบรรทัดใหม่มันจะถูกตีความว่าเป็นสัญญาณเชิงลบ

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

หากเนื้อหาของสแต็กทั้งหมดต้องการการพิมพ์ที่ส่วนท้ายของโปรแกรมสามารถใช้วนรอบวนซ้ำเพื่อทำสิ่งนี้ได้ อย่างไรก็ตามมันสั้นกว่ามากในการใช้fคำสั่ง


1

dcอ่านอินพุตทีละบรรทัด หากคุณจำเป็นต้องอ่านในหลาย ๆ รายการการทำทีละบรรทัดต้องใช้?สำหรับทุกบรรทัดเพื่ออ่านหรือวนรอบแมโครที่ยุ่งยาก หากรายการอินพุตทั้งหมดสามารถใส่ในบรรทัดที่คั่นด้วยช่องว่างหนึ่งบรรทัดแล้วรายการเดียว?จะอ่านรายการอินพุตทั้งหมดโดยผลักแต่ละรายการไปยังสแต็ก

ยกตัวอย่างเช่นในseq 10 | dc -e'?f', seqจำนวนเต็มผล 1-10 ต่อหนึ่งบรรทัด ?ก็จะอ่านเป็นครั้งแรก1ซึ่งจะถูกส่งออกเมื่อfทิ้งทั้งกอง อย่างไรก็ตามในseq 10 | tr '\n' ' ' | dc -e'?f'การtrทำให้การป้อนข้อมูลจำนวนเต็มทุกพื้นที่แยกออกจากกัน ในกรณีนี้?จะอ่านจำนวนเต็มทั้งหมดจากบรรทัดในครั้งเดียวและfจะส่งออกพวกเขาทั้งหมด


1

หากผู้ประกอบการถูก จำกัด จากแหล่งที่มาให้สร้างขึ้นใหม่ด้วย a

สิ่งที่ได้มามีประโยชน์สำหรับฉันสองสามครั้งตอนนี้คือการหลีกเลี่ยงการใช้ประกอบการที่เฉพาะเจาะจงโดยการผลักดันค่า ASCII ของผู้ประกอบการที่ใช้aเพื่อแปลงเป็นสตริงและstoring นี้ในการลงทะเบียนจะได้รับการดำเนินการเป็นแมโครในภายหลัง บน. ตัวอย่างเช่นผมต้องทำส่วน /แต่ฉันไม่ได้รับอนุญาตทั้งจากหรือพยายามที่จะหลีกเลี่ยงการใช้ตัวอักษร ฉันสามารถแทนที่จะทำเช่น47asdนั้นในอนาคตเมื่อผมจำเป็นต้องแบ่ง 16 16 4 ldx4,

  • สิ่งนี้จะใช้งานได้กับตัวดำเนินการอักขระเดี่ยว (ไม่สามารถสร้างสตริง) และจะไม่ทำงานสำหรับคำสั่งเช่นsนั้นจำเป็นต้องได้รับการแก้ไขโดยบางสิ่ง
  • นี่เป็นการเพิ่มจำนวนไบต์ที่ค่อนข้างน้อยดังนั้นจึงเหมาะสมเมื่อต้องหลีกเลี่ยงอักขระเฉพาะหรือจำเป็นต้องมีโบนัสคะแนน

1

หลีกเลี่ยงช่องว่าง

dcหลีกเลี่ยงช่องว่างขึ้นมาในความท้าทายค่อนข้างน้อยและโดยทั่วไปได้ง่ายใน 1 2 3นอกเหนือจากสายหนึ่งครั้งที่เฉพาะเจาะจงมากว่าช่องว่างกลายเป็นสิ่งจำเป็นคือเมื่อผลักดันหลายหมายเลขในแถว: หากต้องหลีกเลี่ยง:

  • 1[]x2[]x3[]xดำเนินการแมโครที่ว่างเปล่าในระหว่าง:
  • ถ้ามีวงเล็บปิดตารางเก็บ NOP ของแมโครข้างหน้าของเวลา: 35asnและรันมัน1lnx2lnx3lnxในระหว่าง:

นอกจากนี้คุณยังสามารถคั่นด้วยเครื่องหมายจุลภาคหากคุณยินดีdc: ',' (054) unimplementedรับคำเตือน
Digital Trauma

ฉันไม่ได้คิดอย่างนั้น - สันนิษฐานว่าใช้กับโทเค็นที่ให้มาซึ่งไม่สามารถแก้ไขคำสั่งได้ ... น่าสนใจ ...
brhfl
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.