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


37

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


เดี๋ยวก่อนฉันกำลังทำอยู่ใช่ไหม? ... อย่างไรก็ตามฉันอยากรู้เกี่ยวกับอันนี้จริงๆ PHP ถูกใช้โดยคนจำนวนมากและนักกอล์ฟ แต่ฉันแทบไม่รู้เลยว่าจะต้องใช้รหัส PHP กับกอล์ฟอย่างไร
JiminP

ใช้แท็กสั้น ๆ <??> มันสามารถบันทึกไม่กี่ไบต์
ม็อบ

คำตอบ:


22

ทำความเข้าใจว่าตัวแปรและช่องว่างโต้ตอบกับภาษาของ PHP สร้างได้อย่างไร

ในการตีกอล์ฟเวลาสั้น ๆ ของฉันฉันพบว่าภาษาของ PHP สร้างขึ้น (เช่น echo, return, for, while และ etc) ทำงานในลักษณะที่ไม่ค่อยมีสัญชาตญาณเมื่อโต้ตอบกับตัวแปรและช่องว่าง

echo$v;ตัวอย่างเช่นถูกต้องสมบูรณ์ตามที่เป็นอยู่return$v;และโครงสร้างที่คล้ายกันอื่น ๆ การลดช่องว่างขนาดเล็กเหล่านี้อาจนำไปสู่การลดลงของระยะเวลาสะสมที่สำคัญ

อย่างไรก็ตามโปรดทราบว่าตัวแปรก่อนการสร้างภาษาต้องใช้ช่องว่างหลังในตัวอย่างต่อไปนี้:

foreach($a AS$b){}

เนื่องจากASเป็นการสร้างภาษาจึงไม่จำเป็นต้องใช้ช่องว่างก่อนตัวแปร$bแต่หากมีการเว้นช่องว่างไว้ก่อนหน้าจะทำให้เกิดการ$aASแยกส่วนนี้เป็นชื่อตัวแปรและนำไปสู่ข้อผิดพลาดทางไวยากรณ์


3
foreach($a[1]as$b)ไม่ต้องการพื้นที่สีขาว สิ่งนี้ไม่ได้เกี่ยวกับการสร้างภาษาและตัวแปร แต่เกี่ยวกับช่องว่างระหว่างตัวอักษรของคำที่แตกต่างกัน
ติตัส

1
อินสแตนซ์อื่นที่คุณต้องการช่องว่างอยู่ในการต่อสายอักขระ ยกตัวอย่างเช่นecho $a+5." text"จะไม่ทำงานเพราะ PHP คิดว่าเป็นจุดทศนิยมสำหรับ. 5เพื่อให้มันใช้งานได้คุณจะต้องเพิ่มพื้นที่เช่นนี้:echo $a+5 ." text"
Business Cat

@BasicSunset echo$a+5," text";ว่าคำสั่งสามารถเขียนเป็น echoสร้างช่วยให้คุณสามารถส่งผ่านพารามิเตอร์หลาย ที่หนึ่งจะต้องมีการเขียนคุณสามารถเขียนecho"result: ".($a+5)."!"; echo"result: ",$a+5,"!";ในความเป็นจริงการส่งพารามิเตอร์หลายตัวไปยังechoa เป็นการปรับให้เหมาะสมขนาดเล็กเนื่องจากโค้ดจะทำงานเร็วขึ้นเล็กน้อย (เนื่องจากคุณไม่ได้ต่อผลลัพธ์เอาไว้ แต่ส่งแยกต่างหาก) สำหรับความท้าทายเกี่ยวกับการเขียนโค้ดที่เร็วที่สุดนี่อาจช่วยนิด ๆ หน่อย ๆ
Ismael Miguel

@IsmaelMiguel จะทำงานร่วมกับechoแต่ไม่ได้มีprint(ที่คุณต้องการหากคุณใส่ไว้ในการแสดงออก: echoเป็นโครงสร้างบริสุทธิ์ที่มีค่าตอบแทนในขณะที่print สามารถทำหน้าที่เป็นฟังก์ชั่น: มันไม่จำเป็นต้องมีวงเล็บ แต่มักกลับมาเสมอint(1).
ติตัส

@Titus printผมไม่ได้พูดอะไรเกี่ยวกับ
Ismael Miguel

22

ใช้สตริงอย่างชาญฉลาด

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

@$s=string;

@เป็นสิ่งจำเป็นที่จะแทนที่คำเตือนนี้จะผลิต โดยรวมแล้วคุณจะจบลงด้วยการลดหนึ่งตัวอักษร

คือบางครั้งอาจเป็นพื้นที่ที่มีประสิทธิภาพในการตั้งค่าตัวแปรเป็นชื่อของฟังก์ชันที่ใช้บ่อย โดยปกติคุณอาจมี:

preg_match(..);preg_match(..);

แต่เมื่อเล่นกอล์ฟสิ่งนี้สามารถย่อให้ง่ายต่อการ:

@$p=preg_match;$p(..);$p(..);

ด้วย "preg_match" เพียงสองอินสแตนซ์คุณจะบันทึกอักขระได้เพียงตัวเดียว แต่ยิ่งคุณใช้ฟังก์ชั่นมากเท่าไหร่คุณก็จะประหยัดพื้นที่ได้มากขึ้นเท่านั้น


10
@ ไม่จำเป็นใน codegolf; ประกาศและคำเตือน (รวมถึงE_DEPRECATED) เป็นที่ยอมรับ
ติตัส

3
@Titus แต่ใน PHP คำเตือนจะส่งออกไปยังไฟล์มาตรฐานดังนั้นจึงจำเป็น
brianush1

1
@Titus ฉันเชื่อว่าคุณสามารถระงับพวกเขาในphp.iniไฟล์
Stan Strum

12

คุณไม่จำเป็นต้องเขียนเช็คตามเงื่อนไขทุกครั้ง ตัวอย่างเช่นเฟรมเวิร์กบางตัวใช้สิ่งนี้ที่ด้านบนของไฟล์เพื่อบล็อกการเข้าถึง:

<?php defined('BASE_PATH')||die('not allowed');

หรือในฟังก์ชั่นปกติ

$value && run_this();

แทน

if($value) { run_this(); }

สามารถใช้งานได้กับ JS
ЕвгенийНовиков

8

ใช้ไวยากรณ์อาร์เรย์แบบสั้น

ตั้งแต่ PHP 5.4 อาร์เรย์สามารถประกาศได้โดยใช้วงเล็บเหลี่ยม (เช่นเดียวกับ JavaScript) แทนที่จะใช้array()ฟังก์ชัน:

$arr=['foo','bar','baz'];
// instead of
$arr=array('foo','bar','baz');

มันจะประหยัดห้าไบต์


แต่อาจมีค่าใช้จ่ายเป็นไบต์หากคุณมี "หลุม" ในอาเรย์แบบเชื่อมโยง:

$arr=array(,1,,3,,5);
// is one byte shorter than
$arr=[1=>1,3=>3,5=>5];

ข้อเสียจะกระทบกันเล็กน้อยในภายหลังหากคุณสามารถเติมค่า "ว่าง" ในรูได้:

$arr=[0,1,0,3,0,5,0,7,0,9,10,11];
// costs two byte more than
$arr=array(,1,,3,,5,,7,,9,,11);

2
PHP 7.1 ยังแนะนำการกำหนดรายชื่อสั้น ๆ[,$a,$b,$c]=$argv;:
ติตัส

7

ใช้ $ {0}, $ {1}, $ {2}, ... แทนที่จะเป็น $ a [0], $ a [1], $ a [2], ...

ถ้าคุณกำลังดำเนินการจัดการอาร์เรย์อ้างอิงมากที่สุดที่จะเป็นดัชนีอาร์เรย์สามารถถูกแทนที่ด้วยเพียง$a[$i] $$iสิ่งนี้จะเป็นจริงถ้าดัชนีเป็นจำนวนเต็มเนื่องจากจำนวนเต็มเป็นชื่อตัวแปรที่ถูกต้องใน PHP (แม้ว่าตัวอักษรจะต้องใช้เครื่องหมายวงเล็บเช่น${0})

พิจารณาการนำไปใช้ของเดือย Rabonowitz Wagon:

3.<?for(;$g?$d=0|($a[$g]=$d*$g--/2+($a[$g]?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);

สิ่งนี้สามารถปรับปรุงได้ 6 ไบต์เพียงแค่แทนที่การอ้างอิงอาร์เรย์ทั้งสอง$a[$g]ด้วย$$g:

3.<?for(;$g?$d=0|($$g=$d*$g--/2+($$g?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);

1
ผมบันทึกไว้เพียง 3 ไบต์กับ: ตู้โชว์
ติตัส

6

เรียนรู้เป็นกลุ่มย่อยที่มีขนาดใหญ่ของการทำงานห้องสมุด

ห้องสมุดของ PHP นั้นค่อนข้างใหญ่และมีฟังก์ชั่นการใช้งานที่สะดวกมากมาย คุณสามารถค้นหาได้ทุกครั้งที่คุณพยายามทำบางสิ่ง แต่คุณจะไม่พบสิ่งที่ตรงกับการค้นหาของคุณ วิธีที่ดีที่สุดคือทำความคุ้นเคยกับไลบรารีและจดจำชื่อฟังก์ชันและสิ่งที่พวกเขาทำ


6
นั่นเป็นความทรงจำมากมายโดยเฉพาะอย่างยิ่งเมื่อมีการตั้งชื่อฟังก์ชั่นมากมาย ;-) ค่อนข้างมาก
Joey

@ ตกลงเห็นด้วย คล้ายกับการจำไลบรารี Java ยกเว้นว่าจะมีประโยชน์น้อยกว่าเนื่องจากเป็น verbose มากกว่า
Matthew อ่าน

3
ฉันพบว่าฟังก์ชั่นที่สำคัญที่สุดสำหรับความท้าทายที่ฉันได้พบที่นี่คือฟังก์ชั่นการจัดการสตริงและการจัดการอาร์เรย์ ใช้ความคิดสร้างสรรค์ของผู้ที่สามารถลดรหัส
migimaru

6

ฟังก์ชั่นที่กำลังทำงานอยู่ภายในสตริง

ลองสิ่งนี้:

$a='strlen';
echo "This text has {$a('15')} chars";

หรือลองสิ่งนี้:

//only php>=5.3
$if=function($c,$t,$f){return$c?$t:$f;};
echo <<<HEREDOCS
    Heredocs can{$if(true,' be','not be')} used too and can{$if(<<<BE
{$if(true,1,0)}
BE
,'','not')} be nested
HEREDOCS;
//Expected output: Heredocs can be used too and can be nested

ใช้งานได้กับสตริงที่ใช้""และ heredocs เท่านั้น (ไม่ต้องสับสนกับ nowdocs)

การใช้ฟังก์ชั่นที่ซ้อนกันเป็นไปได้เฉพาะภายใน heredocs ที่ซ้อนกัน (หรือคุณจะพบข้อผิดพลาดในการแยกวิเคราะห์)!


you will run into parse errorsฉันอ่านเองไม่ได้เหรอ? เครื่องยนต์ Zend ที่น่ารำคาญทำอย่างไรกัน
Stan Strum

ครั้งต่อไปที่ฉันใช้อาร์กิวเมนต์"PHP เป็นภาษาโปรแกรมที่ดี"ฉันจะใช้สิ่งนี้เป็นจุดตอบโต้ ว้าว.
primo

@primo มันไม่ดีเหรอ? : O
Ismael Miguel

5

สนุกกับ typecasts

  • !!$fooจะเปลี่ยนค่าความจริงใด ๆ เป็นtrue(หรือ1ในเอาต์พุต), ค่าเท็จ (0, สตริงว่าง, อาร์เรย์ว่าง) เป็นfalse(หรือเอาต์พุตว่าง)
    สิ่งนี้ไม่ค่อยจำเป็นสำหรับโค้ดกอล์ฟในกรณีส่วนใหญ่ที่คุณต้องการบูลีน บล็อกโดยนัย

  • (int)$fooสามารถเขียนเป็น$foo|0หรือfoo^0แต่อาจต้องการวงเล็บ
    สำหรับ booleans และสายอักขระ$foo*1หรือ+$fooสามารถใช้เพื่อส่งไปยัง int

  • แตกต่างจากภาษาอื่น ๆ ส่วนใหญ่ PHP จัดการสตริงที่มีค่าตัวเลขเป็นตัวเลข ดังนั้นหากคุณมีสตริงใด ๆ ที่มีตัวเลขที่คุณต้องคำนวณด้วยเพียงแค่คำนวณ
  • วิธีอื่น ๆ ที่ไม่ได้ทำงาน: การคูณจำนวนใด ๆ ในตัวแปรที่มี10คุณสามารถผนวกศูนย์: ->*10 .0แต่ในกรณีนี้ PHP จะใช้จุดเป็นทศนิยมและบ่น (มันแตกต่างกันแม้ว่าคุณจะมีจำนวนศูนย์เป็นจำนวนตัวแปรในสตริง)
  • หากต้องการเปิดอาร์เรย์เป็นสตริงใช้แทนjoin หากคุณไม่ต้องการตัวคั่นห้ามใช้: ทำเช่นเดียวกับimplode
    join($a)join('',$a)
  • Incrementing สตริง: คุณลักษณะที่น่าตื่นตาตื่นใจที่สุด IMO คือการที่ผลิต$s=a;$s++; $s=b;ใช้ได้กับอักขระตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก ผลในการ$s=Z;$s++; นี้ยังทำงานร่วมกับกรณีผสม: การ, การ, การและการ การลดลงใช้ไม่ได้กับสตริง (และไม่ได้เปิดอยู่) ย้อนกลับไปใน PHP 3 ผลิต ฉันเสียใจเล็กน้อยที่พวกเขานำสิ่งนั้นออก$s=AA;
    aZbAA1A2A9B0z99Zaa00A
    NULL
    $n="001";$n++;$n="002";

ไม่ว่าคุณจะเล่นกอล์ฟอะไร: มีโต๊ะที่ให้ความสำคัญกับมือเสมอ


4

ใช้แท็กทางลัด

ในรหัสปกติก็ปฏิบัติที่ดีในการใช้งานและ<?php ?>อย่างไรก็ตามนี่ไม่ใช่รหัสปกติ - คุณกำลังเขียนรหัสกอล์ฟ แทนการเขียน<?php <?แทนการเขียน<?php echo <?=อย่าพิมพ์?>ตอนท้าย - เป็นทางเลือกที่สมบูรณ์ ถ้าคุณต้องการ?>ด้วยเหตุผลบางอย่าง (ตัวอย่างเช่นในการส่งข้อความและมันสั้นลงหรืออย่างใดอย่างหนึ่งไม่ต้องใส่เครื่องหมายอัฒภาคก่อนหน้า - ไม่จำเป็นต้องใช้ตาม?>ความหมายอัฒภาค

ผิด (ยาวเกินไปแน่นอน):

<?php echo ucfirst(trim(fgets(STDIN)));?>s!

แก้ไข:

<?=ucfirst(trim(fgets(STDIN)))?>s!

ด้วยการ-rตั้งค่าสถานะ ( ซึ่งมาฟรี ) คุณไม่แม้แต่แท็กใด ๆ เลย (และคุณไม่ได้รับอนุญาตให้ใช้)
ติตัส

4

วนลูปผ่านสตริง

สามารถทำได้ด้วย 26 ไบต์หรือ 24 ลงไปที่ 18:

foreach(str_split($s)as$c)  # A) 26 - general
for($p=0;a&$c=$s[$p++];)    # B) 24 - general
for($p=0;$c=$s[$p++];)      # C) 22 - if $s has no `0` character
for(;a&$c=$s[$p++];)        # D) 20 - if $p is already NULL or 0 (does NOT work for false)
for(;$c=$s[$p++];)          # E) 18 - both C and D

for(;$o=ord($s[$p++]);)     # F) 23 - work on ASCII codes, if $s has no NULL byte and D
for(;~$c=$s[$p++];)         # G) 19 - if $s has no chr(207) and D

$a&$bไม่ได้ค่าที่เหมาะสมและใน (รหัส ASCII ของ) ตัวละครใน$aและ$b
และผลในสตริงที่มีความยาวเช่นเดียวกับที่สั้นกว่าของและ$a$b


คุณช่วยเพิ่มord($s[$p++])ทางเลือกให้for(;$s+=ord($argv[++$i])%32?:die($s==100););กับfor(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;คำถามนี้ได้ที่codegolf.stackexchange.com/questions/116933/…
JörgHülsermann

โปรดเพิ่ม~สำหรับกรณีที่คุณทำงานกับตัวเลขเท่านั้น
JörgHülsermann

โปรดทราบว่า PHP 7.2 ให้คำเตือนเกี่ยวกับ~$cวิธีการ
ติตัส

4

ใช้ผู้ประกอบการที่ประกอบไปด้วย

if(a==2){some code;}else{some other code;}

สามารถย่อไปนี้:

(a==2?some code:some other code);

สั้นลงเหรอ


“ ชวเลขที่มีเงื่อนไข”? บอกชื่อจริงได้ดีกว่าดังนั้นผู้ที่สนใจรายละเอียดเพิ่มเติมสามารถค้นหาได้ในเอกสารประกอบการ: ผู้ประกอบการที่ประกอบไปด้วยส่วนที่สาม
จัดการ

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

3
ผู้ประกอบการที่ประกอบไปด้วยมีพฤติกรรมแปลก ๆ ใน PHP ถ้าคุณทำมัน a?aa:ab?aba:abb:bประเมิน(a?aa:ab)?(aba):(abb)หรืออะไรทำนองนั้น
ติตัส

1
และเริ่มต้นด้วย PHP 5.3 คุณสามารถละเว้นผู้ประกอบการที่สองเป็นเช่นเดียวกับ$a?:$b $a?$a:$b
ติตัส

1
@Cyoce ปลดล็อก||เพื่อบูลีนใน PHP
ติตัส

3

ด้วยชื่ออื่น ... ฟังก์ชั่นสมนาม

ใช้ ...

  • join แทน implode
  • chopแทนrtrim( chopใน PERL แตกต่างกัน!)
  • die แทน exit
  • fputs แทน fwrite
  • is_intแทนis_integerหรือis_long
  • is_realแทนis_floatหรือis_double
  • key_exists แทน array_key_exists
  • mysql แทน mysql_db_query

... เพื่อตั้งชื่อนามแฝงที่สำคัญที่สุด ลองดูที่http://php.net/aliasesสำหรับข้อมูลเพิ่มเติม


โอ้ ... และคุณรู้หรือไม่ว่าการdieทำงานกับและไม่มีพารามิเตอร์? die(1)จะออกจากโปรแกรมด้วยรหัสข้อผิดพลาด1(ไม่แน่ใจในเรื่องนี้อย่างสมบูรณ์ต้องการการทดสอบ); dieจะออกด้วยรหัส0และdie("Hello")จะออกด้วยรหัสหลังจากการพิมพ์0 Hello
ติตัส

3

อาร์เรย์ที่เชื่อมโยงสามารถรวมเข้ากับตัว+ดำเนินการได้

แทน:

$merged = array_merge($a, $b);

ใช้:

$merged = $a + $b;

หมายเหตุตัว+ดำเนินการทำงานกับอาร์เรย์ที่มีการจัดทำดัชนีเช่นกัน แต่อาจไม่ทำสิ่งที่คุณต้องการ


อันที่จริงแล้วการทดแทนที่ดีมักจะไม่เหมือนกัน: pastebin.com/seYeaP38
จัดการ

อ่าใช่แล้วฉันมีชื่อเดิมว่า "อาเรย์แบบเชื่อมโยง ... " แล้วจึงลบออก ฉันจะอธิบายอย่างชัดเจนขอบคุณ
Alex Howansky

อาร์เรย์ตัวเลขสามารถผสานโดยใช้+ตราบใดที่ดัชนีนั้นแตกต่างกัน หากไม่เป็นเช่นนั้นค่าจากอาร์เรย์แรกจะถูกเขียนทับด้วยค่าจากอาร์เรย์ที่สอง (เช่นเดียวกับ array_merge) ความแตกต่าง: +ไม่เรียงลำดับดัชนีใหม่
ติตัส

3

array_flip vs array_search

ใช้

array_flip($array)[$value]

แทน

array_search($value,$array)

เพื่อบันทึก 1 ไบต์ในอาร์เรย์ที่การเกิดขึ้นของแต่ละค่าไม่ซ้ำกัน


3

ข้อเท็จจริงที่น่าสนใจบางประการเกี่ยวกับตัวแปรตัวแปร

ฉันต้องแชร์พวกเขา (ก่อนที่ฉันจะตรวจสอบว่าอย่างน้อยหนึ่งในนั้นช่วยเล่นกอล์ฟ):

  • ใช้ตัวอักษร: $x=a;$$x=1;$x++;$$x=2;echo"$a,$b";พิมพ์1,2
    แต่การดำเนินการทางคณิตศาสตร์อื่น ๆ ใช้ไม่ได้กับตัวอักษร
  • ในฐานะที่เป็นพรีโม่กล่าวก่อนหน้านี้คุณสามารถใช้หมายเลขบริสุทธิ์เป็นชื่อตัวแปร: พิมพ์
    $a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};543
  • คุณสามารถไม่เพียงใช้[0-9a-zA-Z_]สำหรับชื่อตัวแปร แต่ทุกสตริง: พิมพ์
    $x="Hello!";$$x="Goodbye.";echo${"Hello!"};Goodbye.
  • แต่: ทุกอย่างยกเว้น[a-zA-Z_][a-zA-Z_0-9]*ชื่อตัวแปรต้องใช้เครื่องหมายปีกกาสำหรับการใช้ตัวอักษร
  • กับตัวแปรไม่มีกำหนด$$x=1ชุด${NULL}ซึ่งเป็นเช่นเดียวกับและ ${false}${""}
  • $a=1;$$a=5;ไม่ได้ตั้งค่าเพียงแต่ยัง${1}${true}

  • อีกหนึ่งที่แปลกประหลาดหนึ่งฉันได้พบจนถึงขณะนี้: $a=[];$$a=3;echo${[]};ลอง ใช่มันพิมพ์3!

เหตุผลส่วนใหญ่: ชื่อตัวแปรจะถูกประเมินเป็นสตริงเสมอ
(ขอบคุณ @Christoph สำหรับการชี้ให้เห็น)
ดังนั้นอะไรก็ตามที่คุณได้รับเมื่อคุณprintหรือechoนิพจน์นั่นคือสิ่งที่คุณได้รับในชื่อตัวแปร


1
ชื่อตัวแปรถูกแปลงเป็นสตริงที่อธิบายสามจุดสุดท้ายในรายการของคุณ []แปรรูปArray: พิมพ์${[]} = 5;echo $Array; 5ฉันค่อนข้างแน่ใจว่าคุณรู้ว่า แต่ทุกคนอาจไม่เห็นชัดเจน :)
Christoph

@ เจฟฟ์ฉันคงคำผิด ขอบคุณที่สังเกต
ติตัส

2

การขึ้นบรรทัดใหม่
ถ้าเอาต์พุตต้องการการแบ่งบรรทัดใช้ตัวแบ่งบรรทัดแบบฟิสิคัล (1 ไบต์) แทน"\n"
นี่จะช่วยให้คุณได้รับประโยชน์จากการเลือกระหว่างเครื่องหมายคำพูดเดี่ยวและคู่


2

หลีกเลี่ยงคำพูดที่เป็นไปได้

PHP ใช้คำที่ไม่รู้จักในสตริงตามตัวอักษรโดยปริยาย

$foo=foo;เหมือนกับ$foo='foo';(สมมติว่าfooไม่ใช่คำสำคัญหรือค่าคงที่ที่กำหนด): $foo=echo;ใช้งานไม่ได้

แต่: $p=str_pad;ไม่; และประเมิน$p(ab,3,c)abc

การใช้ตัวอักษรสตริงโดยไม่มีเครื่องหมายอัญประกาศจะทำให้ได้รับการแจ้งเตือนสำหรับUse of undefined constant; แต่นั่นจะไม่แสดงหากคุณใช้ค่าเริ่มต้นสำหรับerror_reporting(พารามิเตอร์ CLI -n)


ผมเพิ่งสังเกตเห็น: คำตอบนี้เป็นขยายค่อนข้าง / ซ้ำปรับปรุงของcodegolf.stackexchange.com/a/2916/55735
ติตัส

หมายเหตุ: PHP ก่อนหน้า 7.2 ให้การบอกกล่าว (ซึ่งคุณสามารถ opress พร้อมกับ-nflag); 7.2 ผลผลิตคำเตือน; รุ่นที่ใหม่กว่าจะโยนข้อผิดพลาด!
ติตัส

2

ฟังก์ชั่นลูกศรใน PHP 7.4

PHP 7.4 ใช้เวอร์ชั่น RC2 แล้วและหวังว่าจะเปิดตัวในอีกประมาณ 2 เดือน รายการคุณลักษณะใหม่อยู่ที่นี่ (หน้านี้สามารถปรับปรุงได้จริงเมื่อมีการออก 7.4) ใน 7.4 ในที่สุด PHP ก็มีฟังก์ชั่นลูกศรดังนั้นไม่เพียง แต่คำตอบของฟังก์ชั่นจะสั้นลงเท่านั้น นี่คือตัวอย่างบางส่วน:

ส่งคืนอินพุต + 1:

ฟังก์ชั่นไม่ระบุชื่อ (ปิด) - 25 ไบต์ - ลองออนไลน์!

function($n){return$n+1;}

ฟังก์ชั่นลูกศร - 12 ไบต์ - ลองออนไลน์!

fn($n)=>$n+1

ทวีคูณรายการของอินพุตแรก (อาร์เรย์ของ ints) โดยอินพุตที่สอง (int):

ฟังก์ชั่นไม่ระบุชื่อ (ปิด) - 72 ไบต์ - ลองออนไลน์!

function($a,$n){return array_map(function($b)use($n){return$b*$n;},$a);}

ฟังก์ชั่นลูกศร - 38 ไบต์ - ลองออนไลน์!

fn($a,$n)=>array_map(fn($b)=>$b*$n,$a)

คุณสังเกตเห็นว่า$nสามารถเข้าถึงได้ในฟังก์ชั่นด้านในโดยไม่มีuse $nคำสั่ง? ใช่ว่าเป็นหนึ่งในคุณสมบัติฟังก์ชั่นลูกศร


เป็นหมายเหตุด้านข้างฉันไม่สามารถรับฟังก์ชั่นลูกศรซ้ำได้ (เรียกใช้ฟังก์ชันลูกศรเดียวกันภายในตัวเอง) เพราะเราไม่สามารถตั้งชื่อให้พวกเขาและเก็บไว้เป็นตัวแปรในแบบที่$fไม่$fสามารถเข้าถึงได้ด้วยตัวเอง (เศร้า ) ดังนั้นตัวอย่างนี้ใช้งานไม่ได้และใช้$fในบรรทัดแรกทำให้เกิดข้อผิดพลาดร้ายแรง:

$f=fn($n)=>$n?$f($n-1):0;
$f(5); // Causes error: "PHP Notice: Undefined variable: f" + "PHP Fatal error: Uncaught Error: Function name must be a string"

แต่การเรียกฟังก์ชั่นลูกศรพร้อมกับฟังก์ชั่นลูกศรที่แตกต่างกันทำงาน:

$f1=fn($n)=>$n+1;
$f2=fn($n)=>$f1($n-1);
$f1(2) // Returns 3
$f2(2) // Returns 2

เกิดอะไรขึ้นถ้า$f=fn($n)=>$n?$f($n-1):0;คุณทำแทน$f=$F=fn($n)=>$n?$F($n-1):0;? มันจะใช้ได้ไหม แล้วคุณก็โทร$(5)ตามปกติ
Ismael Miguel

@IsmaelMiguel ดูเหมือนว่าจะยังคงมีข้อผิดพลาดเดียวกัน คุณสามารถลองtio.run # phpด้วยตัวคุณเองได้เพราะ Dennis ได้อัพเดท PHP เป็น 7.4 RC2 สักครู่
Night2

ไม่สามารถใช้งานได้ ดูเหมือนว่าจะมีเพียงตัวแปรที่กำหนดไว้ก่อนหน้านี้เท่านั้น
Ismael Miguel


1

อาร์เรย์ที่อ้างถึงโดยตรงถูกส่งคืนจากฟังก์ชัน

เช่นแทนที่จะเป็น:

$a = foo();
echo $a[$n];

คุณทำได้:

echo foo()[$n];

วิธีนี้ใช้ได้กับ:

echo $obj->foo()[$n];

คุณยังสามารถอ่านการประกาศอาเรย์โดยตรงได้อีกด้วย:

echo [1, 2, 3, 4, 5][$n];

1

ใช้end()แทนarray_pop()

end()ฟังก์ชั่นไม่เพียง แต่ย้ายตัวชี้ภายในปลายแถวก็ยังส่งกลับค่าที่ผ่านมา หมายเหตุแน่นอนว่ามันไม่ได้ลบarray_pop()ค่าที่ดังนั้นหากคุณไม่สนใจสิ่งที่อาร์เรย์มีหลังจากนั้นคุณสามารถใช้มันแทน


1

double array_flip กับ in_array เทียบกับ array_unique

ในกรณีพิเศษนี้ array_flip สองเท่าจะบันทึก 10 ไบต์

($f=array_flip)($k=$f($c)))ลบค่าสองเท่าทั้งหมดในอาร์เรย์และฉันทำสิ่งนี้ทิ้ง$c=[],แล้ว|in_array($o,$c)แทนที่array_keys($c)ด้วย$k

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
$x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,($f=array_flip)($k=$f($c)))==$y # boolean replacement string 1 equal to string 2
    ?join($k)." ".join($c) # output for true cases
:0; #Output false cases

เวอร์ชั่นออนไลน์

ต่อต้าน

for($c=[],[,$x,$y]=$argv;a&$o=$y[$i];$i++)
  $x[$i]==$o|in_array($o,$c)?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,$c)==$y # boolean replacement string 1 equal to string 2
  ?join(array_keys($c))." ".join($c) # output for true cases
  :0; #Output false cases

เวอร์ชั่นออนไลน์

เทียบกับ array_unique จะช่วยประหยัด 2 ไบต์

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
  $x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,array_unique($c))==$y # boolean replacement string 1 equal to string 2
  ?join(array_keys($c))." ".join($c) # output for true cases
  :0; #Output false cases

เวอร์ชั่นออนไลน์

หลังจากพบข้อผิดพลาดในโปรแกรมนี้และทดแทน$x[$i]==$o?:$c[$x[$i]]=$oการ($p=$x[$i])==$o?:$k[$c[$p]=$o]=$parray_flip คู่ก็ไม่จำเป็นอีกต่อไป


array_uniqueปลอดภัยเชื่อมโยง เย้!
ติตัส

@Titus ฉันได้เพิ่มข้อเสนอแนะของคุณ
JörgHülsermann

1

การตัดกันสตริง

คุณเคยใช้
join("DELIMITER",str_split($s))(31 ไบต์) หรือแม้กระทั่ง
preg_replace(".","DELIMITER",$s)(32 ไบต์)
?

มีตัวสำหรับ:

ลองchunk_split($s,1,"DELIMITER")(29 ไบต์)


หากคุณไม่ใช้พารามิเตอร์ที่สามchunk_splitจะใช้\r\n; ที่สามารถช่วยคุณประหยัด 7 หรือ 8 ไบต์

แต่ระวัง: chunk_splitเพิ่มตัวคั่นต่อท้ายสตริง
ดังนั้นคุณอาจไม่ได้สิ่งที่ต้องการ

(หากคุณไม่ได้ให้ความยาวก้อนมันจะใช้ 76. ค่อนข้างแปลกสำหรับรหัสกอล์ฟ แต่ใครจะรู้)


บางทีคุณควรเพิ่มตัวอย่างร่วมกับstrtrฉันชอบความคิดนี้
JörgHülsermann

1

unset () และ INF

ในกรณีที่ค้นหาขั้นต่ำในอาร์เรย์คุณสามารถใช้แทน

unset($var[$k]);

$var[$k]=INF;

เพื่อบันทึก 3 ไบต์


1

str_repeat

ในบางกรณีคุณมีอินพุตของตัวละครและคุณควรเอาท์พุทพวกเขาซ้ำแล้วซ้ำอีกด้วยการป้อนข้อมูลที่เป็นศูนย์สำหรับแต่ละตัว

for(;--$z?:($c=$argn[$i++]).$z=$argn[$i++];)echo$c;

(52 ไบต์) สั้นกว่า

for(;~$c=$argn[$i++];)echo str_repeat($c,$argn[$i++]);

หรือ

for(;~$c=$argn[$i++];)echo str_pad($c,$argn[$i++],$c);

(54 ไบต์ต่อคน)

มันทำงานอย่างไรสำหรับอินพุทตัวอย่าง a1b2c1

$zไม่ได้ตั้งค่า (โดยนัยNULL) --$zไม่ทำอะไรเลยและเป็นเท็จ

$c="a", $z="1"และ$i=2-> $c.$z="a1"เป็น truthy -> เอาท์พุท"a"

--$z=0; ดังนั้นเราจึงตั้ง$c="b", $z="2"(และ$i=4) -> $c.$z="b2"เป็น truthy -> เอาท์พุท"ab"

--$z=1 -> เอาท์พุท "abb"

--$z=0; ดังนั้นเราจึงตั้งค่า$c="c"และ$z=1 $c.$z="c1"เป็นผลลัพธ์ที่แท้จริง"abbc"

--$z=0ดังนั้น$c=""และ$z=""-> $c.$z=""เป็น falsy -> แบ่งห่วง


1

การรวมforลูป

สมมติว่าคุณมีรหัสของแบบฟอร์มต่อไปนี้:

for($pre1; $cond1; $post1) for($pre2; $cond2; $post2) $code;

โดยทั่วไปสามารถรีดซ้ำได้ในแบบฟอร์มต่อไปนี้:

for($pre1; $cond2  $post2 || $cond1  $pre2  $post1; ) $code;

โดยที่หมายถึงโอเปอเรเตอร์การรวมทั่วไป ซึ่งมักส่งผลให้การนับไบต์ลดลง แต่มีแนวโน้มว่าจะต้องใช้ความคิดสร้างสรรค์ $cond2จะต้องมีการเขียนเพื่อที่จะล้มเหลวในครั้งแรกที่ผ่าน $post1ควรล้มเหลวในการดำเนินการในครั้งแรกแม้ว่ามันอาจจะง่ายกว่าในการปรับโครงสร้างใหม่ล่วงหน้าเพื่อ$post1ไม่ให้มีอยู่

หากคุณกำลังทำงานกับลูปซ้อนกันสามวงขึ้นไปคุณสามารถรวมสองวงแรกแล้วรวมเข้าด้วยกันเป็นวงอื่น ๆ ฉันพบว่ามันง่ายกว่าที่จะรวมจากภายในสู่ภายนอก


เป็นตัวอย่างให้พิจารณาวิธีแก้ปัญหาต่อไปนี้กับเศษส่วน H-carpet ( 97 ไบต์ ):

for(;$i<$n=3**$argn;$i+=print"$s\n")for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

สิ่งนี้สามารถปรับรูปแบบได้ด้วยวิธีต่อไปนี้:

for(;($i+=$e&&print"$s\n")<$n=3**$argn;)for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

$e&&printป้องกันทวนแรกและยังไม่ได้เพิ่มขึ้นprint$i

และในที่สุด ( 93 ไบต์ ):

for(;$H>$e*=3or$e=($i+=$e&&print"$s\n")<${$s=H}=3**$argn;)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

$H>$e*=3 จะล้มเหลวในครั้งแรกเนื่องจากตัวแปรทั้งสองไม่ได้กำหนดไว้


1

การลบอักขระในสตริง

join(explode(" ",$string));

บันทึก 1 อักขระเปรียบเทียบกับ

str_replace(" ","",$string);

โปรดทราบว่าวิธีนี้ใช้ได้กับสตริงทั้งหมด (ไม่ใช่ข้อยกเว้น) ไม่ใช่เฉพาะอักขระ
CalculatorFeline

@CalculatorFeline เหตุใดจึงไม่ควรใช้กับสตริงว่าง มันไม่สมเหตุสมผลหรือในกรณีนี้
JörgHülsermann

เวอร์ชันแรกไม่สามารถใช้งานได้""และมันก็ไม่มีประโยชน์อะไรเลย
CalculatorFeline

1
@CalculatorFeline และสำหรับกรณีนี้การแก้ปัญหาศูนย์ไบต์จะดีกว่ามาก มันไม่มีเหตุผลที่จะทำอย่างนี้
JörgHülsermann

3
)ตัวอย่างเช่นการเข้าร่วมของคุณจะหายไป และstrtr($string,[" "=>""])ยิ่งสั้น
ติตัส


1

ใช้โอเปอเรเตอร์บูลีนแทนstrtoupper()และstrtolower()

หากคุณทำงานเฉพาะกับสตริงที่ประกอบด้วยอักขระตัวอักษรคุณสามารถใช้ตัวดำเนินการบูลีนเพื่อเปลี่ยนเป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็กโดยมีการกดแป้นน้อยกว่าฟังก์ชันในตัวของ PHP

ตัวอย่าง:

// Convert lowercase to uppercase
$s = "g";
echo strtoupper($s);  // Outputs 'G', uses 20 characters
echo~" "&$s;          // Outputs 'G', uses 12 characters

// Convert uppercase to lowercase
$s = "G";
echo strtolower($s);  // Outputs 'g', uses 20 characters
echo$s^" ";           // Outputs 'g', uses 11 characters

// Switch case of each character
$s = "Gg";
echo$s^"  ";          // Outputs 'gG', uses 12 characters

สิ่งต่าง ๆ มีความซับซ้อนน้อยกว่าสำหรับสายอักขระที่มีความยาวตามอำเภอใจ แต่ตัวดำเนินการ&และ^จะตัดทอนผลลัพธ์เป็นความยาวของสตริงอินพุตที่สั้นกว่า ตัวอย่างเช่นถ้า$Wเป็นสตริงของช่องว่างอย่างน้อยตราบใดที่อินพุตใด ๆ$sก็~$W&$sจะเท่ากับstrtoupper($s)และ$s|$W^$sเท่ากับstrtolower($s)( $s|$Wโดยตัวมันเองจะสร้างสตริงที่มีช่องว่างเพิ่มเติมเว้นแต่$sและ$Wมีความยาวเท่ากัน)


0

ใช้ฟังก์ชั่เลิก
หากคุณสามารถใช้ POSIX แทน PERL regex โดยไม่ต้องเสียมากกว่า 5 ไบต์ในการแสดงออกการใช้งานeregหรือeregiแทนpreg_match, splitหรือsplitiแทน preg_split
splitนอกจากนี้ยังสามารถใช้เป็นคำเหมือนสำหรับexplodeตัวคั่นส่วนใหญ่

ฟังก์ชั่นเหล่านี้ถูกทำเครื่องหมายว่าเลิกใช้แล้วและจะทำการE_DEPRECATEDแจ้งเตือน แต่ (ไม่สามารถหาแหล่งที่มาได้ในขณะนี้) ฉันคิดว่าฉันได้อ่านแล้วว่าคำเตือนและการแจ้งเตือนนั้นใช้ได้


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