นี่เป็นความท้าทายที่สนุกในการทำงานเปิดและปิดระหว่างการเฉลิมฉลองวันคริสต์มาส ขอบคุณสำหรับการโพสต์! การเล่นกอล์ฟนี้เป็นเรื่องที่น่าสนใจเพราะสเปคนั้นเต็มไปด้วยข้อยกเว้นและกรณีพิเศษซึ่งต้องใช้เงื่อนไขมากมาย นอกจากนี้ในขณะที่ฉันไม่จำเป็นต้องแปลงเป็นและจากทศนิยมในเวลานี้ฉันก็ต้องการฟังก์ชั่น "สูงสุด" เพื่อกำหนดจำนวนหลักที่ใหญ่ที่สุดในแต่ละหมายเลขและค่าที่มากที่สุดของตัวเลขในแต่ละสถานที่
รุ่นแรกของรุ่นนี้คือ 4844 ไบต์เพื่อให้คุณทราบว่าฉันเล่นกอล์ฟนี้มากแค่ไหน
โปรแกรมคาดว่าอินพุตเป็นรายการของจำนวนเต็มที่คั่นด้วยเครื่องหมายจุลภาค ไม่มีช่องว่างหรือบรรทัดใหม่ การใช้สิ่งเหล่านั้นจะทำให้เกิดพฤติกรรมที่ไม่ได้กำหนด
' '' '' ''' "" ' ''' "" ' ''' " ' '' ' ' '' ''"'' ''' "" ' ''' "" '"' "" ' ''' "" ' ''' "" ' ''' "" "" "" ' ''' "" ' ''' "" ' ''' "" '' " '"' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" '"" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" ' ''' "" "" "" "" "" "" "" " ' '' ' ' '''' ' ' '''' ' ' '''' '' '' ' '"'' '''" " ' '''"' "" ' ''' "" ' ''' " ' '' ' ' '' '' ' ' '' ''"'' '''' '' '' '' "' '' ''"" "" '' ' ' '' '' '''' '' '' ''" ' '' ' ' ''''"' '' '' '' "" '' '' '' '' ' '' ' ' '' '' ' ' '''' '' '' ' ' '''' ' '"'' '''' '' '' '' ''" ' '' ''' "" "" "" ' ''' " ' ''"' '' '' '' ' ' '''' ' ' '''' ' ' '''' " ''" """" "" "" "" ' '' '' ''' "" "" "" '"' "" " ' '''" "" "" "" '"' "" "" '' ' '' '' ' ' '' '' '''' ' '"'' ''' "" "" "" """ '' '' '' ' ' '''' " ''" ' '' '' ''' "" ' ''' " ' '' ' ' '' '' '' '''' '' '' ''' "" ' ''' """""" ' '' '' ''' "" "" " ' '' ' ' '' '' '' '''' '' '' ''' "" "" ''" " '' '' " ' '' ' ' '' '' '' '''' ''' "" "" "" ' '''" ' '' "' '' '' "" '' '' ''" ' '' '' '' ' ' '' ' ' '' '' "'' '''' '' '' ''"' '' '' '' "" ''"" ''"" " ' '' ''"'" "" ' ''' "" "" "" "" '' ' ' '' '''' '' '' ' ' ''''" " '' ' '' ' ' '' '' '' '''' ''' "" "" " ' '' '' '' '''" "" "" "" '' '' ''"" '' " ' '''" "" "" "" ' '' '' '' "' '' "" '' '' '' ''" ' '' '' '' '' "' ''"" "" "" '' '' ''"" '' ' ' '' ' ' '' '' '' '' ' ' '''' '' '' '''' '''' '' ' '' '' '' ''' "" " ' '' '''" "" " ' '' '' '''" " '' ' ' '''' ' ' ''''" "" ' ''' "" '"' "" "" '' ''" " '' '' '' ' ' '' '' ''''" '' ' ' ''''"" "" "" '"' "" " ' '' '''" """ " '' '' ' ' '' '' '''' ' ' '''' ' ' '''' " ' '''" " '' ' ' '' '' '''' ' ' '''' ' '"'' '' "" "" "" "" ' '' '' "' " ' '' ' ' '''' '' '' '''" ' '' "' '' "" '' ''" ' '' '' '' "' '' ''"" '"'" "" ' '' '' '' ''' "" "" "" " '"'" "" ' '' '' '' '' "' '' '' ''" "" '' '' '' ' ' '' '' '''' ' ' '''' ' ' '''' ' ' '''' ' '' "' '' '' '' '' ' '' '' '' ' ' '''' ' ' '''' ' ' '''' ' '"'' ''' "" "" "" """ " '' ''"" "" ' '' '' '' ''' "" "" "" "" '' '' ''" ' ''"' '' '' '' '' "" '' '' '' " ' '''" " '"'" "" ' '' '' ''' "" ' ''' "" '"' "" """ ' '' '' '' ''"' "" ' '' '' '' ' ' '' '' '' ' '"'' '''' '' '' '' ''' "" ' ''' "" """"" ' '' '' '' ' '"'' ''' "" "" ' '' '' ''' "" "" "" " '"'" "" " '' ''" "" "" ' '' '' '' '' ' ' '''' '' '' ''' "" "" ''"" '' '' '' '' ' ' '''' " "" "" "" "" '' '' ''" ' ''"' '' "" '' '' '' '' ' ' '''' ' ' '''' ''""" " ' '' '' '' ' '"'' '''" "" ' '' '' '' ''' "" " ' '''" "" "" """ ''" "" "" '"' "" " ' '' '' '' '''" "" "" "" "" ''" ' '' '' '' "' '' '' '' '' ' '' "' '' '' '' '' "" '' '' ''" ' '' '' '' "' '' "" '' '' '' ''" " ''' '' '' '' "' ''" " '' '' '' ' ' '''' ' ' '''' ' ' '''' ' '' ' ' ''''"' " "" "" "" ' ''' "" ' ''' "" '"' "" " ' '' '' '' ' ' '' '' '' '''' '''" "" "" "" ' ''' "" ' ''' "" '"' "" " ' '' '''" "" "" "" """ '' '' '' ''"' ''' "" "" " ' '' '' '' ' ' '' '' '''' ' '"'' '''" "" "" """ " '' '' '' " ' '''" " '' ' ' '' '' '''' '' '' ''""" '' ' ' '' '' '' '''' '' '' '' ' '' '' '' ' '"'' ''' "" "" '' '' '' ''" " '' '' '' ' ' '''' ' ' ''''" ' '''" "" "" "" ' ''' " ' ''"' '' ' ' '' '' '' '' ' ' '''' '' '' '''' " " '' ' ' '' '' '' '''' ''"" "" "" " ' '' '' '' ' '"'' '''" "" "" "" "' "" "" "" " ' '' '' '' ' '"'' '''" "" ' '' ''"' '' '' '' "" '' '' ''' ''' " ' '' ' ' '''' '' '' ''' "" '"' "" "" '' ' ' '' '''' ''"" '' '' " ' '' '' '''" "" "" "" '"' "" " ' '' '' '' '''" "" "" "" ' '' '' ''"' " " '' ' ' '' '' '''' '' '' ' ' '''' ' '' ' ' '' '' '' '''' '' '' ''"'" '"'" "" ' ''"' '' '' ' ' '' '' '' ' ' '' '' '''' ' '"'' ''''" '' " "" "" ' ''' " ' '' ' ' '' '' '''' '' '' '''" ' '' ' ' '''' '' '' ''' "" "" "" " '"'" "" ' '' '' '' '' ' ' '''' '' '' ''' "" " ' '' '' "'" """" "" " ' '' '' '' '''" "" "" "" " ' '' '' '' '''" "" "" "" ' ''' "" ''" " ''" '' "" ''" ' '' '' '' ''"' '' '' "" '' '' '' ' ' '' '' ''''" ''" ' ''' "" "" "" " '"'" """ '' '' '' ' ' '''' ' ' '''' " '' "" ''" """" "" "" "" ' '' '' '' ' ' '''' ' '"'' '''" " '' '' '' ' ' '' '' '' '''' " ' ''"' '' '' '' '' ' ' '' '' '' '''' '' '' '' ' ' '' '' '' '''' '' '' " "" '' '' ''"" '' " ' '' '' '' '' ' ' '' '' '' ' ' '''' ' '"'' '''''"" ' ''' "" ' ''' "" ' ''' "" ' ''' "" '' " ' '' ' ' '' '' '''' '' '' ''' "" " ' '' '' '' '''" "" "" " ' '''" " '"'" "" ' '' ''"' '' '' '' "" ''" "" " ' '''" " '' ' ' '' '' '' '''' '' '' ''"" " '"'" "" ' '' '' "'"" "" "" " ' '' ' ' '' '' '' '''' '' '' '''" "" "" "" ' '' "' ''"
คำอธิบาย
ฉันจะแนะนำคุณเกี่ยวกับวิธีการทำงานของโปรแกรมโดยแสดงให้คุณเห็นว่ามันประมวลผลอินพุตเฉพาะ202,100,1
อย่างไร
ในการเริ่มต้นเราสร้างค่าบางอย่างที่เราต้องการในภายหลัง - ส่วนใหญ่เป็นรหัส ASCII ของตัวละครที่เราจะส่งออก
อย่างที่คุณเห็น'8'
และ'.'
มีอยู่แล้ว '|'
อย่างไรก็ตามเป็น 124 จริงๆไม่ใช่ 14 เราใช้ a while loop เพื่อเพิ่มค่าชั่วคราวสองครั้งใน slot # 1 ลงไปเพื่อรับ 124 (ซึ่งคือ 14 + 55 × 2 เนื่องจากขณะที่ loop ทำงาน 56−1 = 55 ซ้ำ) สิ่งนี้ช่วยประหยัดบางไบต์เนื่องจากตัวอักษรจำนวนเต็มขนาดใหญ่เช่น 124 มีความยาวจริง ๆ ในแผนภาพต่อไปนี้ฉันจะแสดงตำแหน่งของตัวแปรทุกตัวที่โปรแกรมใช้
ต่อไปเราต้องการใส่อักขระทั้งหมดและเก็บไว้ในเทปเริ่มต้นที่เซลล์ # 12 ( pเป็นตัวชี้การทำงานสำหรับสิ่งนี้) ในเวลาเดียวกันเราต้องการทราบว่าจำนวนที่ยาวที่สุดคือเท่าใด เพื่อให้บรรลุนี้เราให้รวมการทำงานในเอก leftwards จะเริ่มต้นที่เซลล์ # -1 (เราใช้Qเป็นตัวชี้ทำงาน) หลังจากป้อนหมายเลขแรก ( 202
) เทปจะมีลักษณะดังนี้:
คุณจะสังเกตเห็นว่าตัวเลขนั้นถูกปิดด้วย 4 ทีนี้เมื่อเราใส่พวกมันครั้งแรกพวกเขาคือค่า ASCII ดังนั้นพวกเขาจึง“ ปิด” 48 และเครื่องหมายจุลภาคคือ 44 สำหรับตัวละครแต่ละตัวเราคัดลอก 46 จาก'.'
เป็นrแล้วลบออกด้วย a while loop (ซึ่งลบ 45) จากนั้นเราบวก 1 เราทำเช่นนั้นเครื่องหมายจุลภาค (ตัวคั่นของเรา) คือ 0 ดังนั้นเราสามารถใช้เงื่อนไขเพื่อจดจำมัน
นอกจากนี้คุณจะสังเกตเห็นว่าเราออกจากเซลล์ # 11 ที่ 0 เราจำเป็นต้องรู้ขอบเขตของหมายเลขแรก
ตัวละครต่อไปจะเป็นเครื่องหมายจุลภาคเพื่อให้เราเก็บ 0 ใน # 15 แต่แน่นอนเวลานี้เราทำไม่ได้ล่วงหน้าQ แต่เราตั้งค่าคิวกลับเป็น 0 และเริ่ม“ เขียนทับ” 1s ที่เราได้วางไว้แล้ว
หลังจากประมวลผลอักขระที่เหลือทั้งหมดแล้วเราจะได้รับสิ่งนี้:
อย่างที่คุณเห็นตอนนี้1s ที่เขียนโดยqจะแสดงความยาวของตัวเลขที่ยาวที่สุด
ขณะนี้เราใช้ในขณะที่วงจะย้ายคิวไปทางซ้ายมากแล้ววางตัวชี้มีอีกซึ่งผมจะเรียกr2 วัตถุประสงค์ของr2จะชัดเจนในภายหลัง
ณ จุดนี้ให้ฉันชี้แจงคำศัพท์ที่ฉันจะใช้ตลอดนี้
- ตามตัวเลขฉันหมายถึงหนึ่งในหมายเลขอินพุตที่คั่นด้วยเครื่องหมายจุลภาค ในตัวอย่างของเราคือ 202, 100 และ 1
- โดยหลักผมหมายถึงตัวเลขหลักเดียวในหนึ่งที่เฉพาะเจาะจงของตัวเลขที่ หมายเลขแรกมี 3 หลัก
- ตามสถานที่ฉันหมายถึงสถานที่หนึ่งที่สิบสถานที่หลายร้อย ฯลฯ ดังนั้นถ้าฉันพูดว่า "ตัวเลขในสถานที่ปัจจุบัน" และสถานที่ปัจจุบันคือสถานที่ที่หนึ่งตัวเลขเหล่านั้นเป็น 2, 0 และ 1 ในที่ ใบสั่ง.
กลับไปที่รายการปกติของเรา ส่วนที่เหลือทั้งหมดของโปรแกรมเป็นลูปขนาดใหญ่ที่เลื่อนคิวไปข้างหน้าจนกว่าจะถึงเซลล์ # 0 แต่ละเซลล์ที่อยู่ระหว่างทางแสดงถึงสถานที่โดยที่ที่อยู่ทางด้านขวาสุดและqจะเริ่มต้นที่จุดสำคัญที่สุด ในตัวอย่างของเรานั่นคือสถานที่นับร้อย
เราดำเนินการต่อโดยการเพิ่มจุดqของเซลล์ที่ (นั่นคือ* q )
ตอนนี้เราอยู่ที่“ เวที 2” สำหรับสถานที่หลายร้อยแห่ง ในขั้นตอนนี้เราจะค้นหาว่าตัวเลขที่ใหญ่ที่สุดคือตัวเลขใดในหลักร้อย เราใช้เคล็ดลับการนับ unary เดียวกันสำหรับสิ่งนี้ยกเว้นเวลานี้ตัวชี้เรียกว่าrและตัวชี้r2ทำเครื่องหมายตำแหน่งเริ่มต้นซึ่งเราจำเป็นต้องรีเซ็ตทุกครั้งที่เราไปยังหมายเลขถัดไป
เริ่มจากตัวเลขแรกกันก่อน เราเริ่มต้นด้วยการตั้งค่าpเป็น 11 (ตำแหน่งเริ่มต้นฮาร์ดโค้ดของตัวเลขทั้งหมด) จากนั้นเราใช้ a while loop เพื่อค้นหาจุดสิ้นสุดของตัวเลขและตั้งค่าp2 ที่นั่นเพื่อทำเครื่องหมายตำแหน่ง ในเวลาเดียวกันเราก็ตั้งค่าq2เป็น 0:
อย่าสับสนกับข้อเท็จจริงที่ว่าq2ชี้ไปที่ vars เราไม่มีช่องว่างภายในเซลล์ว่างเปล่าเพราะเราสามารถตรวจจับเซลล์ # 0 เพียงเพราะมันเป็นศูนย์
ต่อไปเราจะผ่านจำนวนปัจจุบันโดยการลดค่าpและq2ด้วยกันจนกระทั่ง* pเป็นศูนย์ ในแต่ละสถานที่คุณค่าของ* q2บอกเราว่าเราต้องทำอะไร 1 หมายถึง“ ไม่ทำอะไรเลย” ดังนั้นเราจะดำเนินต่อไป ในที่สุดเราก็พบกับ 2 ในเซลล์ # −3 ทุกครั้งที่* q2ไม่เท่ากับ 1, q2จะเท่ากับqเสมอ
ดังที่ฉันได้กล่าวไปแล้วขั้นตอนที่ 2 คือ“ กำหนดตัวเลขที่ใหญ่ที่สุดในสถานที่แห่งนี้” ดังนั้นเราจึงตั้งค่าrเป็นr2ใช้ while loop เพื่อลดค่า* pแล้วเลื่อนrไปทางซ้ายแล้วเติมเทปด้วย 1s จากนั้นใช้อีกอันในขณะที่ loop เพื่อเลื่อนrกลับไปทางขวาและเพิ่ม* pอีกครั้งเพื่อเรียกคืนค่า โปรดจำไว้ว่าในขณะที่ลูปทำงานด้วยการวนซ้ำน้อยกว่าค่าที่เราใช้ ด้วยเหตุนี้จำนวน 1s ที่เขียนจะเท่ากับ 3 (มากกว่า 4 มากกว่า) มากกว่าค่าตัวเลขและค่าสุดท้ายที่เก็บไว้ใน* pจะเพิ่มอีก 2 ดังนั้นสิ่งนี้จึงลดลงอย่างมีประสิทธิภาพ* p 2
หลังจากนั้นเราตั้งค่าpเป็นค่าของp2แล้วเราทำทั้งหมดอีกครั้ง เป็นครั้งที่สองตั้งค่าq2เป็น 0 ค้นหาจุดสิ้นสุดของตัวเลขโดยเลื่อนpไปทางขวาจากนั้นผ่านตัวเลขของตัวเลขนี้โดยการลดค่าpและq2ด้วยกัน อีกครั้งหนึ่งที่เราจะได้พบกับ 2 ในเซลล์ # -3 และเขียนว่า 1s หลายด้านซ้ายของR *
ในกรณีของตัวเลขที่สามเราไม่ต้องทำอะไรเพราะมันไม่มีที่นับร้อย ( q2จึงไม่ถึงq ) แต่ก็ไม่เป็นไรเพราะมันไม่มีผลต่อการคำนวณค่าตัวเลขสูงสุด
นอกจากนี้เรายังตั้งค่าเซลล์* (r - 4)ซึ่งฉันได้ทำเครื่องหมายด้วยลูกศรที่ไม่มีป้ายกำกับที่นี่เป็น 1 (แม้ว่าจะอยู่ที่ 1) ฉันจะไม่บอกคุณว่าทำไมยัง แต่คุณอาจเดาได้แล้ว?
การเพิ่ม* qครั้งต่อไปจะนำเราไปสู่สเตจ 3 ซึ่งเป็น“ ลบตัวเลขสูงสุดจากตัวเลขทั้งหมดในตำแหน่งปัจจุบัน” ก่อนหน้านี้เรารีเซ็ตpเป็น 11 และq2เป็น 0 จากนั้นทำตัวเลขทั้งหมดเหมือนที่เราทำในขั้นตอนก่อนหน้า ยกเว้นเวลานี้* q = 3 แทน 2 ทุกครั้งที่q2ตรงกับqและpอยู่ในหลายร้อยแห่งเราใช้ a while loop เพื่อลดค่า* pหลาย ๆ ครั้งเนื่องจากมี 1 วินาทีในบล็อกด้านซ้ายของ* r2 (5 ในตัวอย่างของเรา) โดยใช้rเป็นตัวชี้การทำงาน เราจะลดมันอีกครั้งเพื่อให้ตัวเลขที่ใหญ่ที่สุดสิ้นสุดที่ −2 ด้วยเหตุผลที่ชัดเจนในภายหลัง:
หลังจากที่เราประมวลผลตัวเลขทั้งหมดแล้วตอนนี้เราจะถึงจุดสิ้นสุดของขั้นตอนที่ 3 ที่นี่เราแสดงสองสิ่งที่แปลกประหลาด
- อันดับแรกเรายังลบขนาดของr -block (บวก 1) จาก* qแต่ใช้ตัวชี้r2ซึ่งปล่อยไว้ทางซ้าย * qกลายเป็นลบด้วยวิธีนี้ ในกรณีของเราr -block มีห้า 1 วินาทีดังนั้น* qกลายเป็น −3
- ประการที่สองเราตั้งค่าตัวแปรออกเป็นค่าที่ไม่ใช่ศูนย์เพื่อบ่งชี้ว่าตอนนี้เรากำลังเข้าสู่ขั้นตอนการส่งออก (โดยทางเทคนิคแล้วความจริงที่ว่า* qนั้นเป็นค่าลบแสดงถึงขั้นตอนการส่งออกแล้ว แต่นี่เป็นเรื่องยากเกินไปที่จะตรวจสอบดังนั้นจึงเป็นตัวแปรพิเศษ)
ตอนนี้คุณเข้าใจว่าเราให้ไปผ่านตัวเลขค้นหาสถานที่ปัจจุบัน (แสดงโดยค่าที่ไม่ใช่ 1 ของQ * ) ภายในแต่ละหมายเลขและทำบางสิ่งบางอย่างขึ้นอยู่กับมูลค่าของQ * เราเห็นว่า* qถูกเพิ่มครั้งแรกเป็น 2 (= คำนวณค่าตัวเลขสูงสุดสูงสุด) จากนั้น 3 (ลบค่าตัวเลขสูงสุดจากทุกตำแหน่งในตำแหน่งนี้) จากนั้นเราลบออกเพื่อให้มันเป็นค่าลบ จากนั้นจะเพิ่มขึ้นเรื่อย ๆ จนกว่าจะถึง 1 ดังนั้นจะเรียกคืนค่าที่หมายถึง "ไม่ทำอะไรเลย" ณ จุดนั้นเราย้ายไปยังสถานที่ต่อไป
ตอนนี้เมื่อ* qเป็นลบเราจะแสดงผล * qเป็นค่าที่ถูกต้องดังนั้นเราจะส่งออกจำนวนแถวของอักขระที่ถูกต้องก่อนที่จะถึง 1; ถ้าตัวเลขที่ใหญ่ที่สุดคือ 2 เราต้องเอาท์พุท 3 แถว มาดูกันว่าเกิดอะไรขึ้นกับแต่ละค่าของ* q :
- * q = −2:
- สำหรับหมายเลขแรก* pคือ −2 ซึ่งบ่งชี้ว่าเราจำเป็นต้องส่งออก a
'.'
(จุด) หรือ a ':'
(โคลอน) เราตัดสินใจที่โดยดูที่Q : ถ้ามัน -1 เราอยู่ในสถานที่ที่คนเพื่อการส่งออก':'
(ซึ่งเราจะคำนวณเป็น'8'
2) '.'
มิฉะนั้น
- สำหรับหมายเลขที่สอง* pคือ −3 อะไรก็ตามที่ไม่ใช่ −2 หมายถึงเราส่งออก
'|'
(ไปป์) แล้วเพิ่มค่า วิธีนี้จะไปถึง −2 ในตำแหน่งที่ถูกต้องจากนั้นเราจะส่งออก'.'
s / ':'
s สำหรับส่วนที่เหลือของตัวเลขนั้น
- ในแต่ละกรณีเรายังตั้งตัวแปรpdเป็น 0 ก่อนที่เราจะประมวลผลจำนวนและตั้งค่าpd (=“ พิมพ์”) เป็นค่าที่ไม่เป็นศูนย์เพื่อระบุว่าเราได้พิมพ์ตัวอักษรแล้ว
- สำหรับหมายเลขที่สามจะไม่มีการประมวลผลเกิดขึ้นเนื่องจากหมายเลขที่สามไม่มีจำนวนร้อย ในกรณีนี้pdจะยังคงเป็น 0 หลังจากประมวลผลหมายเลขซึ่งระบุว่าเรายังคงต้องส่งออก a
'|'
(แต่ถ้าออกไม่ใช่ศูนย์เพราะมิฉะนั้นเรายังอยู่ในขั้นตอนที่ 2 หรือ 3)
- หลังจากการประมวลผลตัวเลขทั้งหมดถ้าออกมาเป็นที่ไม่ใช่ศูนย์ส่งออกขึ้นบรรทัดใหม่ โปรดทราบว่าเราต้องการตัวแปรoutเพื่อที่เราจะได้ไม่ต้องขึ้นบรรทัดใหม่ในระยะที่ 2 หรือ 3
- * q = −1:เหมือนเมื่อก่อนยกเว้นว่า * pคือ −2 สำหรับทั้งสองหมายเลขแรกดังนั้นทั้งสองเอาท์พุต
'.'
(และเอาท์พุตที่สามเป็น'|'
เหมือนก่อนหน้า)
- * q = 0:เมื่อ * qเป็น 0 นี่หมายความว่า "ไม่ต้องทำอะไรถ้าเราอยู่ในที่เดียวกันมิฉะนั้นให้ส่งออกแถว
'|'
s โดยไม่คำนึงถึง * p " วิธีนี้เราจะได้ช่องว่างระหว่างตัวเลข
ทีนี้เราก็เพิ่มคิวเพื่อย้ายไปยังตำแหน่งถัดไป, หลักสิบและเพิ่ม* q ที่นั่น ที่จุดเริ่มต้นของระยะที่ 2 เทปจะมีลักษณะดังนี้:
จากนั้นเราก็ขึ้นเวที 2 เหมือนเมื่อก่อน โปรดจำไว้ว่าการลบ 2 อย่างมีประสิทธิภาพจากทุกหลักในสถานที่นี้และปล่อยให้หมายเลข unary ที่เหลือของ* r2แสดงถึงจำนวนสูงสุด เราปล่อยให้หมายเลขเอกนารีก่อนหน้าเพียงอย่างเดียวและขยายเทปไปทางซ้ายเรื่อย ๆ มันจะเสียค่าใช้จ่ายรหัสพิเศษที่ไม่จำเป็นเพื่อ "ล้าง" เมื่อเราเสร็จแล้วและเราเพิ่มขึ้น* qในตอนเริ่มต้นของเวที 3 เทปตอนนี้:
จริงๆแล้วนี่เป็นเรื่องโกหก โปรดจำไว้ว่าก่อนหน้านี้ที่ฉันบอกว่าเราตั้ง* (r - 4)เป็น 1 และฉันไม่ได้บอกคุณว่าทำไม? ตอนนี้ฉันจะบอกคุณว่าทำไม สำหรับกรณีเช่นนี้ซึ่งตัวเลขที่ใหญ่ที่สุดในความเป็นจริง 0 หมายถึงตัวเลขทั้งหมดในสถานที่นี้คือ 0 การตั้งค่า* (r - 4) ที่ระบุโดยลูกศรที่ไม่มีป้ายกำกับด้านบนถึง 1 ขยายหมายเลขเอกนัมเบอร์โดย 1 แต่เฉพาะในกรณีพิเศษนี้ ด้วยวิธีนี้เราทำท่าราวกับว่าตัวเลขที่ใหญ่ที่สุดคือ 1 ซึ่งหมายความว่าเราจะส่งออกหนึ่งแถวพิเศษ
หลังจากขั้นตอนที่ 3 (ลบตัวเลขสูงสุดจากตัวเลขทั้งหมดในตำแหน่งปัจจุบัน) รวมถึงขั้นตอนพิเศษที่ทำให้* q เป็นลบเทปจะมีลักษณะเช่นนี้ ครั้งที่แล้วตัวเลขที่ใหญ่ที่สุดถูกแสดงด้วย −2 ในบล็อก* pแต่ครั้งนี้พวกเขาทั้งหมด −3 เพราะพวกเขาทั้งหมดเป็นศูนย์จริง ๆ แต่เราแสร้งทำเป็นว่าตัวเลขสูงสุดคือ 1
ตอนนี้เรามาดูกันว่าเกิดอะไรขึ้นเมื่อ* qไปยัง 1:
- เมื่อ* q = −1 ค่า* pคือ −3 ทั้งหมดซึ่งหมายความว่าเราส่งออก
'|'
s และเพิ่มพวกเขา
- เมื่อ* Q = 0 เราส่งออก
'|'
เพราะที่สิ่งที่เรามักจะทำเมื่อQ * = 0 โดยไม่คำนึงถึง* p
ดังนั้นเราจึงได้รับท่อสองแถว
ในที่สุดเราย้าย* qไปยังสถานที่หนึ่ง อันนี้น่าสนใจเพราะเราต้องเอาท์พุท':'
s หากตัวเลขจริงคืออะไรนอกจาก 1 แต่'8'
ถ้าเป็น 1 ลองดูว่าโปรแกรมดำเนินไปอย่างไร ก่อนอื่นเราเพิ่ม* qเพื่อเริ่มขั้นตอนที่ 2:
หลังจากขั้นตอนที่ 2 (“ คำนวณค่าตัวเลขสูงสุด”) เราจะเหลือสิ่งนี้:
หลังจากขั้นตอนที่ 3 (“ ลบค่าตัวเลขสูงสุดจากตัวเลขทั้งหมดในตำแหน่งปัจจุบัน”) เทปจะมีลักษณะดังนี้:
ทีนี้ลองทำซ้ำแต่ละ* qกัน:
- * q = −2:
- หมายเลขแรก: อยู่ที่ −2 ดังนั้นให้ส่งออก a
':'
(แทนที่จะเป็น'.'
เพราะq = −1)
- หมายเลขที่สอง: ที่ −4 ดังนั้นเอาท์พุท a
'|'
และส่วนเพิ่ม
- จำนวนที่สาม: ที่ -3
'|'
เพื่อการส่งออก อย่างไรก็ตามในครั้งนี้แทนที่จะเป็นตัวพิมพ์ใหญ่จะทำให้เกิดกรณีพิเศษ เฉพาะในกรณีที่เราส่งออกสถานที่สุดท้าย ( q = −1) และเราอยู่ในแถวที่สองสุดท้ายสำหรับ ( * q = −2) และหลักคือ 1 ( * p = −3) , แล้วแทนการเพิ่มมันถึง -2 เราตั้งค่าให้ -1 ในคำอื่น ๆ ที่เราใช้ -1 เป็นค่าพิเศษที่จะแสดงให้เห็นว่าในการย้ำต่อไปเราจะต้องส่งออกแทน'8'
':'
- * q = −1:
- จำนวนแม่: แล้วที่ -2
':'
เพื่อการส่งออก
- จำนวนสอง: ที่ -3
'|'
เพื่อการส่งออก เงื่อนไขพิเศษไม่เปิดใช้งานเพราะ* qไม่มีอีกต่อไป −2 ดังนั้นการเพิ่มขึ้น
- จำนวนที่สาม: -1
'8'
เพื่อการส่งออก
- * q = 0:โดยปกติแล้วเราจะส่งออกแถว padding ของ
'|'
ที่นี่ แต่ในกรณีพิเศษที่เราอยู่ในสถานที่ที่ ( q = −1) เราข้ามมัน
หลังจากนี้qจะเพิ่มขึ้นเป็น 0 และใหญ่ขณะที่ลูปสิ้นสุด
ตอนนี้คุณรู้วิธีการป้อนข้อมูลเหมือน202,100,1
งาน อย่างไรก็ตามมีอีกหนึ่งกรณีพิเศษที่เรายังไม่ได้ครอบคลุม คุณอาจจำได้ว่าในขณะที่เรากำลังประมวลผลสถานที่สุดท้ายเมื่อ* pเป็น −3 เราตั้งค่าเป็น −1 สำหรับ1
(แทนที่จะเพิ่มขึ้นเป็น −2) เพื่อให้การทำซ้ำครั้งถัดไป'8'
แทน สิ่งนี้ใช้งานได้เพราะเรามีการทำซ้ำที่* pคือ −3 และเราทำการตัดสินใจว่าจะเพิ่มขึ้นหรือตั้งเป็น −1 เราไม่ได้เช่นการทำซ้ำถ้าทั้งหมดของตัวเลขในสถานที่ที่เป็น 0 หรือ 1 ในกรณีเช่นนี้ทั้งหมด* pค่า 1s จะเริ่มต้นที่ -2; ไม่มีโอกาสตัดสินใจที่จะตั้งเป็น −1มากกว่าที่จะเพิ่มขึ้นได้จาก -3 ด้วยเหตุนี้จึงมีเงื่อนไขพิเศษอีกอย่างหนึ่งในขั้นตอนที่ 3 (“ ลบตัวเลขสูงสุดจากทุกหลักในสถานที่ปัจจุบัน”) ฉันอ้างว่าหลังจากลบค่าตัวเลขสูงสุดจากทุกหลัก (ณ จุดที่ตัวเลขสูงสุดคือ −1) เราก็ลดมันอีกครั้ง แต่จริงๆแล้วมีเงื่อนไขว่าจะไปดังนี้:
หากตัวเลขที่เราดูมีค่าเท่ากับตัวเลขสูงสุดในสถานที่นี้ ( * p = −1) และสถานที่นี้คือตำแหน่งที่หนึ่ง ( q = −1) และตัวเลขสูงสุดคือ 1 ( * (r + 5) = 0, คือบล็อกยูนารีที่ด้านซ้ายสุดมีความยาวเพียง 5 เซลล์เท่านั้น , จากนั้นเราจะปล่อย* pที่ −1 เพื่อระบุว่าการวนซ้ำของเอาต์พุตเท่านั้นที่จะต้องส่งออก'8'
และ ในกรณีอื่น ๆ เราจะลดมันอีกครั้ง
เสร็จสิ้น สวัสดีปีใหม่!
แก้ไข 1 (3183 → 3001):มีความสุขปีใหม่กอล์ฟ! ฉันจัดการเพื่อกำจัดตัวแปรp2และr2โดยสิ้นเชิง! พีตอนนี้แข่งไปมาเพื่อให้การหาจุดเริ่มต้นและจุดสิ้นสุดของตัวเลข แต่ดูเหมือนว่าจะสั้นลงในรหัส ฉันพยายามกำจัดq2ด้วย แต่ฉันไม่สามารถทำให้รหัสสั้นลงได้
ฉันยังพบสถานที่อีกไม่กี่แห่งที่ฉันสามารถใช้เทคนิคการตีกอล์ฟทั่วไปที่อ่านไม่ได้เช่นการใช้ค่าสุดท้ายของลูปอีกครั้ง เพื่อให้คุณเป็นตัวอย่างแทน
while *(++p) { 1 } // just increment p until *p is 0; the 1 is a noop
if (pd) { x } else { y } // where pd is a variable
ฉันสามารถบันทึก'""""
(ทำครั้งแรกจากนั้นสอง) และ'"""
(คงที่ 1) โดยการเขียนในลักษณะที่เป็นเช่น
if (while *(++p) { pd }) { x } else { y }
แน่นอนมันใช้งานได้ก็ต่อเมื่อฉันรู้ว่าขณะที่ลูปจะทำงานอย่างน้อยหนึ่งรอบ แต่ถ้าเป็นเช่นนั้นค่าส่งคืนจะเป็นpdดังนั้นฉันจึงสามารถใช้มันเป็นเงื่อนไขสำหรับ if ได้