เคล็ดลับการตีกอล์ฟใน Tcl


15

คุณมีเคล็ดลับอะไรบ้างสำหรับการเล่นกอล์ฟใน Tcl? ฉันกำลังมองหาแนวคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะ Tcl (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ) กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ

คำตอบ:



4

ในคำตอบของฉัน/codegolf//a/107557/29325ฉันสามารถสาธิต:

  1. มักset j 0;while \$j<$n;{...;incr j}จะสั้นกว่าที่เทียบเท่ากันfor {set j 0} {$j<$n} {incr j} {...}

  2. เมื่อตัวแปรลูปเริ่มต้นที่ 1 เราสามารถทำการเพิ่มขึ้นเป็นส่วนหนึ่งของwhileเงื่อนไขการทดสอบหลีกเลี่ยงการเขียนก่อนset i 1โดยไม่จำเป็น: while {[incr i]<=$n} {...}แทนset i 1;while \$i<=$n;{...;incr i}

ความสนใจ : หนึ่งสามารถทำได้ 2. ในกรณีของการวนรอบนอก! ฉันไม่สามารถใช้มันกับjตัวแปรของฉันเพราะมันจะต้องถูกรีเซ็ตเป็น 1 ในด้านนอกของวงในของตัวเอง! และincr jจะได้รับค่าที่ตั้งไว้ในขั้นตอนสุดท้ายของลูปด้านในแทนที่จะจับตัวแปรที่ไม่ได้กำหนดjเพื่อคาดเดา0และเพิ่มมันเป็น1!


4

บางครั้งมันก็คุ้มค่าที่จะใช้โดยtime {script} nที่nมีจำนวนการวนซ้ำมากกว่าปกติwhileหรือforวนซ้ำ แม้ว่าtimeจุดประสงค์ของมันจะไม่วนซ้ำ แต่ผลที่ได้ก็ยังเหมือนเดิม

ฉันเพิ่งเปลี่ยนแปลงคำตอบของตัวเองตามทิศทางนี้

UPDATE:ฉันได้ค้นพบเพียงแค่เรื่องง่ายที่จะตกอยู่อันตราย: คุณไม่สามารถเปลี่ยนforหรือwhileโดยtimeบล็อกถ้ามันมีหรือbreakcontinue


3

ใช้เปลือกโต้ตอบ สิ่งนี้ช่วยให้คุณสามารถย่อชื่อคำสั่งตราบเท่าที่มีเพียง 1 คำสั่งเริ่มต้นด้วยตัวอักษรที่เหลือ

ตัวอย่าง:

  • gets -> ge
  • lassign -> las
  • expr -> exp
  • puts -> pu

และโซลูชั่นแบบอินเทอร์แอคทีฟฟรี: P

พื้นหลัง :

เมื่อtclshทำงานกับขั้วเป็นอุปกรณ์ป้อนจะกำหนดตัวแปรเพื่อtcl_interactive 1สาเหตุนี้unknown(โพรซีเดอร์เริ่มต้นที่จะถูกเรียกหากไม่พบคำสั่ง) เพื่อค้นหาคำสั่งที่ขึ้นต้นด้วยชื่อนั้น

ข้อเสีย: มันจะพิมพ์ผลลัพธ์ของทุกบรรทัดใช้;แทนการขึ้นบรรทัดใหม่
โอ๋และมันอาจจะเรียกคำสั่งภายนอกเช่นซึ่งเป็นตัวย่อที่ดีของwwhile


3

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

จากนั้นคุณสามารถใช้สิ่งนี้กับความมหัศจรรย์ของnamespaceการทำสิ่งชั่วร้ายอย่างแท้จริง พิจารณาสิ่งนี้:

namespace exp *;namespace en cr -c ?

หลังจากนั้น?ตอนนี้เป็นคำสั่งที่มีมนต์ขลังที่ช่วยให้คุณย่อ Tcl คำสั่งใด ๆ ทั่วโลกและโดยไม่ต้องมีความไม่แน่นอนที่น่ารังเกียจของ messing unknownรอบด้วย


2

ฉันใช้ Tcl 8.0.5 แต่ฉันเชื่อว่าสิ่งต่อไปนี้สามารถใช้กับเวอร์ชันล่าสุดทั้งหมด

  1. ใช้renameเพื่อเปลี่ยนชื่อrename:

    rename rename &
    

    &สามารถระบุใด ๆ &แค่ทำให้ฉันนึกถึง "การอ้างอิง" ในภาษาซี

  2. ใช้การเปลี่ยนชื่อrenameเพื่อเปลี่ยนชื่อset:

    & set =
    

    อีกครั้ง=สามารถเป็นตัวระบุใด ๆ ; =เป็นเรื่องง่ายสำหรับฉัน

  3. ตอนนี้เปลี่ยนชื่อคำสั่งอื่น ๆ ที่มีมูลค่าการเปลี่ยนชื่อเช่น

    & regsub R
    & string S
    & while W
    

    คำสั่งที่มีมูลค่าการเปลี่ยนชื่อถ้าได้รับความยาวnและเกิดขึ้นk , k (n-1) - (n + 4)> 0 แก้สำหรับkk > (n+4)/(n-1)สูตรจะกลายเป็น นี่คือตารางอ้างอิงที่ทำให้ง่าย:

    length of       minimum         example(s)
    command         occurrences
    ------------------------------------------------
    2               6               if (consider renaming to "?")
    3               4               for, set (consider renaming to "=")
    4               3               eval, expr, incr (consider renaming to "+"), info, join, proc, puts, scan
    5               3               break, catch, lsort, split, subst, trace, unset, while
    6               3               format, lindex, lrange, regexp, regsub, rename, return, string, switch
    7               2               foreach, lappend, linsert, llength, lsearch, unknown
    .               2               lreplace
    .               2               continue
    .               2               
    
  4. ถัดไปคอมแพคย่อยที่ใช้บ่อยเช่น

    = I index
    = L length
    

    เพื่อให้คุณสามารถทำสิ่งต่าง ๆ เช่น

    S $I $x 7
    S $L $x
    
  5. บางเรื่องที่เห็นได้ชัด:

    1. lappend สามารถกำหนดองค์ประกอบแรกของรายการหากยังไม่มี (ไม่จำเป็นต้องเริ่มต้น)
    2. คุณสามารถตั้งค่าอาร์เรย์โดยไม่ต้องใช้array, เช่น set doesNotExist(7) 43
    3. คุณสามารถใช้สตริง ( "a b c") [list a b c]แทน
    4. foo${a}barคุณสามารถสอดแทรกในสตริงชอบโดย:
    5. คุณสามารถใช้มากกว่าtwo\ words "two words"(จำไว้โดยทั่วไปว่าสำหรับสตริงที่ต่อเนื่องกันโดยไม่มีช่องว่างสามารถใส่เครื่องหมายคำพูดคู่ได้!)
    6. คุณสามารถเขียนfors เป็นwhiles เพื่อบันทึกอักขระหนึ่งหรือสองตัวได้ตลอดเวลาเนื่องจาก a whileสามารถตรวจสอบและเพิ่มได้พร้อมกันในขณะที่forใช้บล็อกแยกต่างหาก
  6. สำหรับโปรแกรมขนาดใหญ่ต่อไปนี้เป็นเคล็ดลับที่ฉันคิด แต่ยังไม่ได้ใช้:

    proc unknown {c args} {eval [info commands $c*] $args}
    

    สิ่งนี้เลียนแบบคำสั่งแบบโต้ตอบ! มีค่าใช้จ่าย 54 ตัวอักษร แต่ตอนนี้คุณสามารถใช้jสำหรับjoin, spสำหรับsplit, stสำหรับstring, wสำหรับwhile, และอื่น ๆ


1
หากคุณต้องการเลียนแบบตัวย่อแบบโต้ตอบให้ใช้info script {};set tcl_interactive 1
Johannes Kuhn

เจ๋งขอบคุณ! ผมเคยให้เครดิตคุณที่นี่ มีบางประเด็นที่มีเทคนิคที่มี แต่ที่ผมไม่ได้พบกับunknownเส้นทาง: ดูที่นี่และที่นี่
Andrew Cheong

คำถามถามถึงเคล็ดลับที่ค่อนข้างเฉพาะเจาะจงกับ Tcl ผู้ประกอบการ ternary จะรวมอยู่ในเคล็ดลับสำหรับทุกภาษา
Peter Taylor

@PeterTaylor - ขอบคุณฉันได้ลบเคล็ดลับนั้นแล้ว
Andrew Cheong

2

อื่นเป็นตัวเลือก

ในฐานะที่ได้มีการกล่าวบนถ้าหน้าคู่มือ , elseเป็นนัยเกี่ยวกับการifสร้างบล็อก ดังนั้นคืออะไร

if ... {} else {}

สามารถกลายเป็น

if ... {} {}

อย่างที่คุณเห็นในคำตอบของฉัน


1

อาจจะควรรวมอยู่ในคำตอบอื่น แต่ที่นี่มันไป:

เมื่อ a procมีเพียงหนึ่งพารามิเตอร์มันสามารถเขียนเป็น

proc p a {DO THINGS}

แทน

proc p {a} {DO THINGS}

เช่นเดียวกับพารามิเตอร์สองตัวที่procใช้แบ็กสแลช มันสามารถเขียนเป็น

proc p a\ b {DO THINGS}

แทน

proc p {a b} {DO THINGS}

สำหรับพารามิเตอร์จำนวนที่สูง{}กว่าการเรนเดอร์โค้ดที่สั้นกว่า


1

บางครั้งมันก็คุ้มค่าที่จะแทนที่ทั้งสองsetประโยคเพื่อเชื่อมโยงสตริงด้วยlappendคำสั่งเดียวเท่านั้น ในการก่อสร้างเช่นเดียวสามารถทดแทน

set s ""

loop {
    # ...
    set s $s\X
}

โดย

loop {
    # ...
    append s X
}

appendคำสั่งมีincrพฤติกรรมชอบซึ่งเริ่มต้นตัวแปรยังไม่ได้กำหนดไว้

ดูแลเพื่อไม่ให้ผิดพลาดappendโดยlappend


1

หากคุณกำลังจัดการรายการที่มีการดำเนินการที่ syntactically interleaving ระหว่างแต่ละองค์ประกอบบางครั้งคุณสามารถjoinองค์ประกอบที่จะทำการดำเนินการเฉพาะแทนการข้ามมัน

ใน/codegolf//a/127042/29325มีตัวอย่าง:

puts \n[expr [join [split [read stdin]] +]]

มันread stdinจะช่วยให้แยกแล้วจะให้รายการ23 214 52 หลังจากนั้นจะกลับสตริง ในที่สุดก็ทำงานของข้อสรุป{23 214 52}[join {23 214 52} +]23+214+52expr 23+214+52


splitในกรณีนี้คุณสามารถละเว้น
Johannes Kuhn

@JohannesKuhn: ขอบคุณ เสร็จสิ้น
sergiol

1

หากคุณมีรหัสที่มีขนาดใหญ่ก็เป็นไปได้ที่จะหลีกเลี่ยงการใช้งานหลายexprใช้namespace pat tcl::mathopที่จุดเริ่มต้น มันมีการดำเนินการคำนำหน้าไวยากรณ์เป็น Tcl fonction ปกติ ตัวอย่างเช่น:

namespace pat tcl::mathop
set sum [+ 1 2 3]
set prod [* {*}{1 2 3 4}]
puts $sum\ $prod

ดูหน้า doc doc แบบทางการ


0

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

ตัวอย่างหนึ่งคือคำตอบของฉันเอง/codegolf//a/105789/29325

ในการตัดสินใจเพียงแค่ต้องการน้ำหนักจำนวนตัวแปร (สมมติว่ามีตัวแปรตัวอักษร 1 ตัวตามที่คาดไว้เมื่อเล่นกอล์ฟ):

  • <5 setคือนักกอล์ฟ

  • = 5 setและlassignสร้างจำนวนไบต์เดียวกัน

  • > 5 lassignคือนักกอล์ฟ

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