8088 Assembly, IBM PC DOS, 164 159 156 155 ไบต์
เลขฐานสอง:
00000000: d1ee 8a0c 03f1 53fd ac3a d075 0343 e2f7 ......S..:.u.C..
00000010: 85db 741c 5f8a d043 f6c3 0174 0a57 bd64 ..t._..C...t.W.d
00000020: 0155 83eb 0374 0957 bd5d 0155 4b4b 75f7 .U...t.W.].UKKu.
00000030: 8ad0 2c2f 7213 518a f0b0 24b1 31bf 6a01 ..,/r.Q...$.1.j.
00000040: fcf2 aefe ce75 fa59 57e2 bc5a 85d2 740c .....u.YW..Z..t.
00000050: b409 cd21 b220 b402 cd21 ebef c364 6f75 ...!. ...!...dou
00000060: 626c 6524 7472 6970 6c65 246f 6824 6f6e ble$triple$oh$on
00000070: 6524 7477 6f24 7468 7265 6524 666f 7572 e$two$three$four
00000080: 2466 6976 6524 7369 7824 7365 7665 6e24 $five$six$seven$
00000090: 6569 6768 7424 6e69 6e65 24 eight$nine$
รูปร่างและการทดสอบการปฏิบัติการใช้xxd -r
จากข้างต้นหรือดาวน์โหลดPHONE.COM
รายการที่ยังไม่ได้ประกอบ:
D1 EE SHR SI, 1 ; point SI to DOS PSP (80H) for input string
8A 0C MOV CL, BYTE PTR[SI] ; load input string length into CX
03 F1 ADD SI, CX ; move SI to end of input
53 PUSH BX ; push a 0 to signal end of output stack
CHAR_LOOP:
FD STD ; set LODS direction to reverse
AC LODSB ; load next char from [SI] into AL, advance SI
3A D0 CMP DL, AL ; is it same as previous char?
75 03 JNZ NEW_CHAR ; if not, it's a different char
43 INC BX ; otherwise it's a run, so increment run length
E2 F7 LOOP CHAR_LOOP ; move on to next char
NEW_CHAR:
85 DB TEST BX, BX ; is there a run greater than 0?
74 1C JZ GET_WORD ; if not, look up digit name
5F POP DI ; get name for the current digit
8A D0 MOV DL, AL ; save current char in DL
43 INC BX ; adjust run count (BX=1 means run of 2, etc)
F6 C3 01 TEST BL, 1 ; is odd? if so, it's a triple
74 0A JZ IS_DBL ; is even, so is a double
57 PUSH DI ; push number string ("one", etc) to stack
BD 0164 MOV BP, OFFSET T ; load "triple" string
55 PUSH BP ; push to stack
83 EB 03 SUB BX, 3 ; decrement run count by 3
74 09 JZ GET_WORD ; if end of run, move to next input char
IS_DBL:
57 PUSH DI ; push number string to stack
BD 015D MOV BP, OFFSET D ; load "double" string
55 PUSH BP ; push to stack
4B DEC BX ; decrement by 2
4B DEC BX
75 F7 JNZ IS_DBL ; if not end of run, loop double again
GET_WORD:
8A D0 MOV DL, AL ; save current char into DL
2C 2F SUB AL, '0'-1 ; convert ASCII char to 1-based index
72 13 JB NOT_FOUND ; if not a valid char, move to next
51 PUSH CX ; save outer loop counter
8A F0 MOV DH, AL ; DH is the index to find, use as scan loop counter
B0 24 MOV AL, '$' ; word string is $ delimited
B1 31 MOV CL, 031H ; search through length of word data (49 bytes)
BF 016A MOV DI, OFFSET W ; reset word data pointer to beginning
FC CLD ; set DF to scan forward for SCAS
SCAN_LOOP:
F2/ AE REPNZ SCASB ; search until delimiter '$' is found in [DI]
FE CE DEC DH ; delimiter found, decrement counter
75 FA JNZ SCAN_LOOP ; if counter reached 0, index has been found
59 POP CX ; restore outer loop position
57 PUSH DI ; push string on stack
NOT_FOUND:
E2 BC LOOP CHAR_LOOP ; move to next char in input
OUTPUT_STACK:
5A POP DX ; get string from top of stack
85 D2 TEST DX, DX ; it is the last?
74 0C JZ EXIT ; if so, exit
B4 09 MOV AH, 09H ; DOS display string function
CD 21 INT 21H ; write string to console
B2 20 MOV DL, ' ' ; load space delimiter
B4 02 MOV AH, 02H ; DOS display char function
CD 21 INT 21H ; write char to console
EB EF JMP OUTPUT_STACK ; continue looping
EXIT:
C3 RET ; return to DOS
D DB "double$"
T DB "triple"
W DB "$oh$","one$","two$","three$","four$","five$","six$","seven$","eight$","nine$"
TL; DR:
สตริงอินพุตถูกอ่านจากซ้ายไปขวาเพื่อให้ค้นหาสามได้ง่ายขึ้น เอาต์พุตจะถูกส่งไปยังสแต็ก x86เพื่อลดความซับซ้อนในการกลับลำดับการแสดงผลและยังช่วยจัดเรียงคำ "double" และ "triple" ใหม่เพื่อนำหน้าชื่อของตัวเลข
หากตัวเลขถัดไปแตกต่างจากครั้งสุดท้ายชื่อจะถูกค้นหาในรายการคำและผลักไปที่สแต็ก เนื่องจากไม่มีแนวคิดอย่างเป็นทางการของ "อาร์เรย์ที่จัดทำดัชนีของสตริงความยาวผันแปร" ในรหัสเครื่องรายการคำจะถูกสแกนi
(ดัชนีของคำ) จำนวนครั้งสำหรับตัวคั่นสตริง ( $
) เพื่อค้นหาคำที่สอดคล้องกัน มีประโยชน์ x86 มีคำแนะนำสั้น ๆ ( REPNZ SCASB
ซึ่งคล้ายกับmemchr()
ใน C) ซึ่งทำให้คำสั่งนี้ง่ายขึ้น (ขอบคุณCISC !)
หากตัวเลขนั้นเหมือนกันกับตัวก่อนหน้าตัวนับสำหรับความยาวของ "การทำงาน" จะเพิ่มขึ้นและยังคงวนซ้ำไปทางซ้ายบนอินพุต เมื่อจบการทำงานแล้วชื่อของตัวเลขจะถูกนำมาจากสแต็กเพราะจะต้องวางหลังจาก "double" หรือ "triple" สำหรับการจัดกลุ่มแต่ละครั้ง หากความยาวของการวิ่งเป็นเลขคี่ (และความยาวของการวิ่งคือ> 1
) ชื่อของหลักตามด้วยสตริง "สาม" จะถูกผลักไปที่สแต็กและความยาวของการวิ่งจะลดลง 3 เนื่องจากความยาวของการวิ่งจะเท่ากัน ซ้ำสำหรับ "double" จนกระทั่งความยาวรันเท่ากับ 0
เมื่ออินพุตสตริงถึงจุดสิ้นสุดสแต็กจะถูกดัมพ์กับแต่ละสตริงที่บันทึกไว้ที่เขียนไปยังหน้าจอตามลำดับย้อนกลับ
I / O:
PC DOS แบบสแตนด์อโลนที่ปฏิบัติการได้อินพุตจากเอาต์พุตบรรทัดคำสั่งไปยังคอนโซล
ดาวน์โหลดและการทดสอบPHONE.COM