คุณมีเคล็ดลับทั่วไปอะไรสำหรับการเล่นกอล์ฟใน Perl ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ Perl (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ) กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ
คุณมีเคล็ดลับทั่วไปอะไรสำหรับการเล่นกอล์ฟใน Perl ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ Perl (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ) กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ
คำตอบ:
นั่นคือเคล็ดลับที่สำคัญที่สุดในการเล่นกอล์ฟ Perl ที่คุณต้องรู้ เมื่อใดก็ตามที่คุณดูลำดับตัวละครที่ยาวเกินไปที่คุณต้องทำเพื่อให้งานสำเร็จลุล่วงถามตัวเองว่าไม่มีวิธีอื่นที่จะได้รับผลกระทบเดียวกันโดยใช้คุณสมบัติที่แตกต่างกันหรือไม่ มักจะมี นี่เป็นเพียงไม่กี่:
~~บังคับใช้บริบทเกลาและเป็น 4 scalarตัวอักษรที่สั้นกว่า
y///cหนึ่งตัวอักษรสั้นกว่าlengthเมื่อรับความยาว$_เป็น
ต้องการวนซ้ำตัวอักษรใน$_หรือไม่ แทนที่ด้วยsplit// /./gs(หรือใช้/./gถ้าคุณยังต้องการที่จะข้ามบรรทัดใหม่.) งานนี้มีตัวแปรอื่น ๆ : เปลี่ยนด้วยsplit//,$x$x=~/./gs
Perlin ทุกตัวจะส่งคืนสิ่งที่ printส่งคืน 1 เช่นเพื่อระบุ I / O ที่สำเร็จ หากคุณต้องการเริ่มต้น$_เป็นค่าจริงเช่น$_=print$fooอนุญาตให้คุณฆ่านกสองตัวด้วยหินก้อนเดียว
เกือบทุกคำสั่งใน Perl สามารถเขียนเป็นนิพจน์ทำให้สามารถใช้ในบริบทที่หลากหลายได้กว้างขึ้น หลายคำสั่งสามารถเป็นหลายนิพจน์ที่ถูกโยงเข้าด้วยกันด้วยเครื่องหมายจุลภาค การทดสอบสามารถทำได้กับตัวดำเนินการลัดวงจร?: && ||และกับandและorซึ่งทำสิ่งเดียวกัน แต่มีความสำคัญต่ำกว่าตัวดำเนินการอื่นทั้งหมด (รวมถึงการกำหนด) ลูปสามารถทำได้ผ่านทางหรือmap grepแม้คำหลักเช่นnext, lastและreturnสามารถนำมาใช้ในบริบทการแสดงออกถึงแม้ว่าพวกเขาไม่กลับ! การคำนึงถึงการแปลงรูปแบบเหล่านี้อยู่ในใจจะช่วยให้คุณมีโอกาสแทนที่โค้ดบล็อกด้วยนิพจน์ที่สามารถยัดเข้าไปในบริบทที่หลากหลาย
$fooแล้ว มิฉะนั้น$_=1จะสั้นกว่า$_=print""และมีผลเหมือนกันมาก
$x? มิฉะนั้นคุณก็สามารถทำและ/./gs /./g
ตัวแปรพิเศษในทางที่ผิดของ Perl!
ตามที่ระบุไว้ในคำตอบก่อนหน้า$/และ$"จะเริ่มต้นโดยเริ่มต้นถึง"\n"และ" "ตามลำดับ
$,และ$\ถูกตั้งค่าเป็นทั้งค่าundefเริ่มต้นและสั้นกว่า 3 ตัวอักษร
การตั้งค่า$\เป็นค่าจะทำให้ผนวกเข้ากับทุกprintค่า ตัวอย่างเช่น: perl -ple '$\="=".hex.$/'เป็นตัวแปลงเลขฐานสิบหกถึงทศนิยมที่มีประโยชน์
หากคุณไม่ได้อ่านไฟล์จากบรรทัดคำสั่งคุณสามารถใช้-iสวิตช์บรรทัดคำสั่งเป็นช่องทางพิเศษสำหรับการป้อนสตริง $^Iค่าของมันจะถูกเก็บไว้ใน
$=บังคับให้ทุกสิ่งที่กำหนดให้มันเป็นจำนวนเต็ม ลองใช้งานperl -ple '$_=$==$_'และมอบ inupts ต่างๆ เช่นเดียวกัน$-บังคับให้ค่าเป็นจำนวนเต็มที่ไม่ใช่ลบ (เช่นเครื่องหมายขีดนำจะถือเป็นอักขระที่ไม่ใช่ตัวเลข)
คุณสามารถใช้$.เป็นแฟล็กบูลีนที่ถูกรีเซ็ตเป็นค่าจริง (ไม่ใช่ศูนย์) ในทุกการวนซ้ำของwhile(<>)ลูป
-n และวงเล็บปีกกาที่ไม่มีใครเทียบเป็นที่ทราบกันดีว่าสวิตช์บรรทัดคำสั่ง-nสามารถใช้เพื่อเรียกใช้สคริปต์หนึ่งครั้งสำหรับทุกบรรทัด
perl --help พูดว่า:
-n assume "while (<>) { ... }" loop around program
สิ่งที่ไม่ได้พูดอย่างชัดเจนก็คือ Perl ไม่เพียง แต่คิดว่าวนรอบโปรแกรม มันอย่างแท้จริงล้อมwhile (<>) { ... }รอบ
วิธีนี้คำสั่งต่อไปนี้เทียบเท่ากัน:
perl -e 'while(<>){code}morecode'
perl -ne 'code;END{morecode}'
perl -ne 'code}{morecode'
-p และวงเล็บปีกกาที่ไม่มีใครเทียบเช่นเดียวกันกับที่กล่าวมาข้างต้น-pสวิตช์ล้อมwhile (<>) { ... ; print }รอบโปรแกรม
โดยใช้วงเล็บปีกกาตรงกันperl -p 'code}{morecode'เท่านั้นจะพิมพ์ครั้งหลังจากการดำเนินการสำหรับทุกบรรทัดของการป้อนข้อมูลตามcodemorecode
เนื่องจาก$_ไม่ได้กำหนดไว้เมื่อmorecode;printมีการดำเนินการตัวแยกบันทึกการส่งออก$\สามารถใช้ในทางที่ผิดเพื่อพิมพ์เอาท์พุทที่เกิดขึ้นจริง
ตัวอย่างเช่น
perl -pe '$\+=$_}{'
อ่านหนึ่งหมายเลขต่อบรรทัดจาก STDIN และพิมพ์ผลรวมของพวกเขา
#!perl -nในบรรทัดแรกใช่มั้ย
}for(...){ระหว่างเครื่องมือจัดฟันก็มีประโยชน์เช่นกันเช่นcodegolf.stackexchange.com/a/25632
ใช้$_เพื่อกำจัดการอ้างอิงสเกลาร์ มันเป็นตัวแปรพิเศษที่ใช้เป็นค่าเริ่มต้นโดยฟังก์ชั่นส่วนใหญ่และเพียงแค่ออกจากพารามิเตอร์เป็นทางลัดในการอ้างอิงตัวแปรนี้
โดยการเปลี่ยน$nไป$_คุณสามารถเปลี่ยน$n=<>;chop$n;print$nไป$_=<>;chop;print
ที่นี่printฟังก์ชั่นพิมพ์เนื้อหาของ$_โดยค่าเริ่มต้นและchopยังใช้งาน$_ได้
$_=<>;ต้องไม่ได้<>;อ่านบรรทัดลง$_โดยอัตโนมัติ?
$_=<>;print <>;printอันแรกกลับมาหาฉันในสิ่งที่ฉันพิมพ์ในขณะที่อีกอันหนึ่งไม่กลับมา
print while(<>)โอ้ขอบคุณปรากฎว่าเกิดขึ้นเฉพาะในกรณีเช่น ถ้าไม่แน่ใจว่ามันเป็นกรณีพิเศษหรือมีบางตรรกะเชื่อมโยงกันอยู่เบื้องหลังมันไม่<>'s ส่วนร่วมในการperlopมิได้whileเป็นส่วนหนึ่งของperlsynดูเหมือนจะพูดถึงพฤติกรรมนี้
while(<>)เป็นกรณีพิเศษที่จัดทำเป็นเอกสารใน perlsyn, I / O Operators: 'ถ้าหากสัญลักษณ์อินพุตเป็นสิ่งเดียวที่อยู่ในเงื่อนไขของคำสั่ง "while" (แม้ว่าจะปลอมเป็น "for (;;)" วนรอบ) ค่าจะถูกกำหนดให้กับตัวแปรทั่วโลกโดยอัตโนมัติ $ _, ทำลายสิ่งที่เคยมีมาก่อนหน้านี้ "
ใช้ตัวแปรพิเศษของ Perl ที่คุณสามารถทำได้เช่น:
$"แทน" "$/แทน"\n"พวกเขาได้รับประโยชน์เพิ่มเติมจากการเป็นตัวระบุความยาวหนึ่งตัวที่รับประกันได้ด้วยความช่วยเหลือจาก lexer สิ่งนี้ทำให้สามารถติดกับคำหลักที่ตามมาดังเช่นในprint$.for@_
รายการตัวแปรพิเศษทั้งหมดมีอยู่ที่นี่: ตัวแปรพิเศษ
qwอย่าใช้ นี่เป็นการเสียอักขระสองตัวที่สามารถนำไปใช้ในทางที่ดีขึ้น ตัวอย่างเช่นอย่าเขียนสิ่งต่อไปนี้
@i=qw(unique value);
ใช้ barewords แทน
@i=(unique,value);
หรือถ้าคุณไม่สามารถใช้ barewords ให้ใช้globไวยากรณ์
@i=<unique value>;
glob ไวยากรณ์สามารถใช้สำหรับเอฟเฟ็กต์ที่น่าสนใจ
@i=<item{1,2,3}>;
ใช้โมเดอเรเตอร์ของคำสั่งแทนคำสั่งผสม
ข้อความสั่งแบบผสมมีแนวโน้มที่จะต้องใช้วงเล็บสำหรับอาร์กิวเมนต์และวงเล็บปีกกาสำหรับบล็อกในขณะที่ตัวดัดแปลงข้อความไม่ต้องการ
เปรียบเทียบ:
$a++,$b++while$n-- VS while($n--){$a++;$b++}chop$,if$c VS if($c){chop$,}โปรดทราบว่าตัวอย่างสุดท้ายเชื่อมโยงกับ$c&&chop$,แต่เริ่มส่องแสงจริงๆสำหรับการดำเนินการหลายคำสั่งส่วนใหญ่ &&โดยทั่วไปสิ่งที่สูญเสียความสำคัญผู้ประกอบการ
use strictอย่า (อย่าพูดถึงฉันเกี่ยวกับเรื่องนี้บริบทของ PCG.SE เป็นเรื่องสำคัญ) และที่สำคัญอย่าใช้รหัสราวกับอยู่ภายใต้ความเข้มงวด ผู้ต้องสงสัยตามปกติ:
myประกาศตัวแปรหากคุณสามารถหลีกเลี่ยงได้ ตัวแปรเดียวที่จำเป็นจริงๆmyคือตัวแปรที่คุณต้องการกำหนดขอบเขต นั่นเป็นสิ่งที่แทบจะไม่เกิดขึ้นเลยเมื่อเล่นกอล์ฟซึ่งคุณไม่ต้องการการปกป้องขอบเขตและมีแนวโน้มที่จะควบคุมการเรียกซ้ำprint helloจะไม่ทำงาน จริงๆแล้วมันหมายถึงprint hello $_(พิมพ์$_ไปยัง filehandle hello)
printและตอนนี้ฉันไม่สามารถหาตัวอย่างที่ดีและสั้นได้)
ฉันแน่ใจว่าบางส่วนของชื่อเหล่านี้มีชื่อทางการและฉันก็ไม่ทราบ
print $n++ while ($n < 10) $var = join('',<>) print ('X'*10) . "\n";นานกว่าprint ('X'*10) . $/;sayฟังก์ชั่นของ Perl นั้นสั้นกว่าprintแต่คุณจะต้องรันโค้ดด้วย-Eแทนที่จะเป็น-ea..z ถ้ามีความจำเป็นเป็นสตริงใช้aa..zzjoin$z = 'z'; print ++$z;จะแสดงaaนั่นคือทั้งหมดที่ฉันสามารถคิดได้ในขณะนี้ ฉันอาจเพิ่มอีกในภายหลัง
print ('X'*10) . $/;ควรทำ สำหรับฉันมันพิมพ์0และไม่มีการขึ้นบรรทัดใหม่ สำหรับสิ่งหนึ่งที่วงเล็บกลายเป็นข้อโต้แย้งการเรียกใช้ฟังก์ชันสไตล์ซึ่งผูกแน่นกว่าprint .และไม่ได้หมายความว่าคุณxแทน*หรืออะไร?
whileแต่join'',<>;ก็สามารถใช้งานได้หากไม่มีวงเล็บ
ใช้$%แทนการ$aช่วยให้คุณสามารถวางชื่อตัวแปรด้านขวาติดกับif, forหรือwhileสร้างเช่น:
@r=(1,2,3,4,5);$%=4;
print$_*$%for@r
หลายคนสามารถใช้งานได้ แต่ตรวจสอบเอกสารและคำตอบของ @ BreadBoxที่มีเอฟเฟกต์เวทมนตร์
หากคุณไม่สามารถใช้คำสั่ง modfiers ตามคำตอบของ @ JBแผนที่อาจบันทึกไบต์:
for(@c){} เมื่อเทียบกับ map{}@c;
และเป็นประโยชน์ถ้าคุณต้องการที่จะทำซ้ำซ้อนกันในขณะที่คุณสามารถใส่ postfix ลูปภายในformap
Perl มีตัวแปรเวทย์สำหรับ 'ข้อความก่อนการจับคู่' และ 'ข้อความหลังการจับคู่' ดังนั้นจึงเป็นไปได้ที่จะแบ่งออกเป็นกลุ่มที่มีอักขระน้อยกว่า:
($x,$y)=split/,/,$_;
($x,$y)=/(.+),(.+)/;
/,/; # $x=$`, $y=$'
# Note: you will need to save the variables if you'll be using more regex matches!
สิ่งนี้อาจทำงานได้ดีแทนsubstr:
$s=substr$_,1;
/./;# $s=$'
$s=substr$_,4;
/.{4}/;# $s=$'
หากคุณต้องการเนื้อหาของการแข่งขัน$&สามารถใช้เช่น:
# assume input like '10 PRINT "Hello, World!"'
($n,$c,$x)=split/ /,$_;
/ .+ /; # $n=$`, $c=$&, $x=$'
หากคุณโทรมาพูดprintสี่ครั้งขึ้นไปในรหัสของคุณ (สิ่งนี้จะแตกต่างกันไปตามความยาวของรูทีนที่คุณโทร) ให้แทนที่ด้วยชื่อย่อยที่สั้นกว่า:
sub p{print@_}p;p;p;p
เมื่อเทียบกับ
print;print;print;print
หากคุณมีรหัสเช่น:
$i--if$i>0
คุณสามารถใช้ได้:
$i-=$i>0
แทนที่จะบันทึกบางไบต์
หากคุณไม่ได้กำหนดให้กับตัวแปรดังนั้นจึงไม่สามารถใช้เคล็ดลับของ breadboxคุณสามารถใช้นิพจน์0|:
rand 25 # random float eg. 19.3560355885212
int rand 25 # random int
0|rand 25 # random int
rand 25|0 # random int
~~rand 25 # random int
เป็นที่น่าสังเกต แต่คุณไม่จำเป็นต้องใช้จำนวนเต็มเพื่อเข้าถึงดัชนีอาร์เรย์:
@letters = A..Z;
$letters[rand 26]; # random letter
redoเพิ่มพฤติกรรมวงบล็อกโดยไม่ต้องหรือ for เป็นวงไม่สิ้นสุดwhile{redo}
อย่าวงเล็บฟังก์ชั่นการโทร
Perl ช่วยให้คุณเรียกใช้ฟังก์ชั่นที่รู้จักกัน (หลักหรือที่ประกาศไว้ล่วงหน้า) โดยใช้NAME LISTไวยากรณ์ สิ่งนี้จะช่วยให้คุณวาง&เครื่องหมาย (ถ้าคุณยังใช้อยู่) รวมถึงวงเล็บ
ตัวอย่างเช่น: $v=join'',<>
ลองใช้ค่าของนิพจน์การกำหนดค่าเช่น:
# 14 characters
$n=pop;$o=$n&1
# 13 characters, saves 1
$o=($n=pop)&1
ใช้งานได้เพราะ$nมี 2 ตัวอักษรใน Perl คุณสามารถเปลี่ยน$nเป็น()ไม่มีค่าใช้จ่ายและบันทึก 1 อัฒภาคด้วยการย้ายการกำหนดไปไว้ในวงเล็บ
คุณสามารถรันหลาย statement ที่แตกต่างกันภายในตรรกะที่ประกอบไปด้วยตรรกะสามส่วน
สมมติว่าคุณมีขนาดใหญ่if- elsifคำสั่ง นี่อาจเป็นเหตุผลใด ๆ และจำนวนงบใด ๆ
if( $_ < 1 ) {
$a=1;
$b=2;
$c=3;
say $a.$b.$c;
} elsif($_ < 2 ) {
$a=3;
$b=2;
$c=1;
say $a.$b.$c;
} elsif( $_ < 3) {
$a=2;
$b=2;
$c=2;
say $a.$b.$c;
}
คุณสามารถใช้(cmd1, cmd2, cmd3)ภายในผู้ประกอบการที่ประกอบไปด้วยเพื่อเรียกใช้คำสั่งทั้งหมด
$_ < 1 ?
($a=1,$b=2,$c=3,say$a.$b.$c):
$_ < 2 ?
($a=3,$b=2,$c=1,say$a.$b.$c):
$_ < 3 ?
($a=2,$b=2,$c=2,say$a.$b.$c):
0; #put the else here if we have one
นี่เป็นตัวอย่างตัวอย่าง:
perl -nE'$_<1?($a=1,$b=2,$c=3,say$a.$b.$c):$_<2?($a=3,$b=2,$c=1,say$a.$b.$c):$_<3?($a=2,$b=2,$c=2,say$a.$b.$c):0;' <(echo 2)
select(undef,undef,undef,$timeout)แทนTime::HiRes(นำมาจากhttps://stackoverflow.com/a/896928/4739548 )
ความท้าทายหลายอย่างต้องการให้คุณนอนหลับด้วยความแม่นยำมากกว่าจำนวนเต็ม select()อาร์กิวเมนต์การหมดเวลาของสามารถทำสิ่งนั้นได้
select($u,$u,$u,0.1)
มีประสิทธิภาพมากกว่า:
import Time::HiRes qw(sleep);sleep(0.1)
ตัวแรกคือเพียง 20 ไบต์ในขณะที่ตัวหลังใช้เวลาถึง 39 อย่างไรก็ตามตัวเก่าต้องการให้คุณไม่ได้ใช้งาน$uและไม่เคยกำหนดไว้
หากคุณจะใช้มันเป็นจำนวนมากการนำเข้าTime::HiResจ่ายออก แต่ถ้าคุณต้องการมันเพียงครั้งเดียวการใช้select($u,$u,$u,0.1)บันทึก 19 ไบต์ซึ่งเป็นการปรับปรุงในกรณีส่วนใหญ่
ยกเว้นกรณีที่มีการระบุเป็นอย่างอื่นคุณไม่จำเป็นต้องขึ้นบรรทัดใหม่
'ความท้าทาย' ของเราพูดว่า 'เอาท์พุทตัวเลขสุ่มจาก 0 ถึง 9 ถึง STDOUT' เราสามารถใช้รหัสนี้ (28 ไบต์):
$s=int(rand(10));print"$s\n"
และย่อให้สั้นลงถึงสิ่งนี้ (25 ไบต์):
$s=int(rand(10));print $s
เพียงพิมพ์ตัวแปร อันสุดท้ายนี้ใช้กับความท้าทายนี้โดยเฉพาะ (19 ไบต์):
print int(rand(10))
แต่จะใช้ได้เฉพาะเมื่อคุณไม่ต้องทำอะไรกับตัวแปรระหว่างการกำหนดและการพิมพ์
บางครั้ง (บ่อยครั้งเมื่อต้องรับมือกับความท้าทายควินินหรือจำกัด แหล่งที่มา ) คุณได้รับประโยชน์อย่างมากจากความสามารถในการซ้อนตัวอักษรสตริง q(…)ปกติคุณต้องการทำเช่นนี้กับ อย่างไรก็ตามขึ้นอยู่กับอักขระที่คุณต้องการภายในสตริงคุณอาจบันทึกไบต์และใช้<…>ตัวดำเนินการ glob (โปรดทราบว่าสิ่งที่อยู่ในวงเล็บเหลี่ยมไม่สามารถดูเหมือนไฟล์แฮนเดิลและไม่สามารถดูเหมือนจะขยายเข้าไปในรายการชื่อไฟล์ซึ่งหมายความว่าอักขระจำนวนมากจะไม่ทำงานอย่างถูกต้อง)
ภาพประกอบที่มีคุณค่าของการทำตามนี้คือรหัสการสร้างการป้อนข้อมูลลงในคลื่นไซน์:
s/./print" "x(sin($i+=.5)*5+5).$&/eg;
อย่างที่คุณเห็นมันค่อนข้างกะทัดรัดในการวนซ้ำอักขระในอินพุตมาตรฐาน คุณสามารถใช้ regex อื่นเพื่อเปลี่ยนวิธีการจับคู่สิ่งต่าง ๆ
$_=print""$_=print$fooจะสั้นกว่า