Hailstone sequence: Difference between revisions

(→‎Vectorization solution: Improved syntax.)
Line 9,849:
Sequence = 27 82 41 124 ... 8 4 2 1
77031's Hailstone length = 351
</pre>
 
=={{header|Z80 Assembly}}==
This task will be split into two parts, in order to fit all the output of each on one Amstrad CPC screen.
===Show The Sequence with n=27===
Output is in hexadecimal but is otherwise correct.
<lang z80>;;;;;;;;;;;;;;;;;;; HEADER ;;;;;;;;;;;;;;;;;;;
read "\SrcCPC\winape_macros.asm"
read "\SrcCPC\MemoryMap.asm"
read "\SrcALL\winapeBuildCompat.asm"
;;;;;;;;;;;;;;;;;;; PROGRAM ;;;;;;;;;;;;;;;;;;;
 
org &8000
ld de,27
call doHailstone
;returns length of sequence, and writes each entry in the sequence
; to RAM
 
;print the sequence length (in hex)
ld a,h
call ShowHex
ld a,l
ld (memdump_smc),a
;just to prove I didn't need to know the sequence length at
; compile time, I'll store the calculated length as the operand
; of "doMemDump" which normally takes a constant embedded after
; it as the number of bytes to display.
 
; If that doesn't make sense, don't worry.
; This has nothing to do with calculating the hailstone sequence, just showing the results.
call ShowHex
 
call NewLine ;prints CRLF
call NewLine
 
call doMemDump
memdump_smc:
byte 0 ;operand of "doMemDump" (gets overwritten with the sequence length)
word HailstoneBuffer ;operand of "doMemDump"
 
 
ret
 
;;;;;;;;;;;;;;;;;;; LIBRARY ;;;;;;;;;;;;;;;;;;;
read "\SrcCPC\winape_stringop.asm"
read "\SrcCPC\winape_showhex.asm"
 
 
doHailstone:
;you need the proper input for the function "hailstone"
;returns addr. of last element in IX.
call hailstone
ld de,HailstoneBuffer
or a ;clear carry
push ix
pop hl ;returns element count in HL.
sbc hl,de ;subtract the two to get the length of the array.
 
SRL H
RR L ;divide array size by 2, since each entry is 2 bytes.
INC L
ret nz ;if no carry, don't increment H.
INC H
ret
 
 
hailstone:
;input - de = n
ld ix,HailstoneBuffer
ld a,d
or e
ret z ;zero is not allowed.
loop_hailstone:
ld (IX+0),e
ld (IX+1),d
ld a,e
cp 1
jr nz,continue_hailstone
ld a,d
or a
ret z ;if de = 1, stop.
continue_hailstone:
bit 0,e
jr z,DE_IS_EVEN
;de is odd
push de
pop hl ;ld hl,de
 
SLA E
RL D
add hl,de ;hl = de*3
 
ld de,1
add hl,de
 
push hl
pop de ;ld de,hl
 
inc ix
inc ix
jr loop_hailstone
 
DE_IS_EVEN:
SRL D ;A/2
RR E
inc ix
inc ix
jr loop_hailstone
 
 
doMemDump:
;show the hailstone sequence to the screen. This is just needed to display the data, if you don't care about that
;you can stop reading here.
pop hl ;get PC
ld b,(hl) ;get byte count
inc hl
ld e,(hl) ;get low byte of start addr.
inc hl
ld d,(hl) ;get high byte of start addr.
inc hl
push hl ;now when we return we'll skip the data block.
ex de,hl
 
 
call NewLine
 
;we'll dump 8 words per line.
 
ld c,8
loop_doMemDump:
inc hl
ld a,(hl)
call ShowHex
dec hl
ld a,(hl)
call ShowHex
ld a,' '
call PrintChar
inc hl
inc hl
dec c
ld a,c
and %00001111
jr nz,continueMemdump
ld c,8
continueMemdump:
djnz loop_doMemDump
ret
 
 
 
HailstoneBuffer:
ds 512,0</lang>
 
{{out}}
<pre>
call &8000
0070
 
001B 0052 0029 007C 003E 001F 005E 002F
008E 0047 00D6 006B 0142 00A1 01E4 00F2
0079 016C 00B6 005B 0112 0089 019C 00CE
0067 0136 009B 01D2 00E9 02BC 015E 00AF
01BD 0538 029C 014E 00A7 01F6 00FB 02F2
0179 046C 0236 011B 0352 01A9 04FC 027E
013F 03BE 01DF 059E 02CF 086E 0437 0CA6
0653 12FA 097D 1C78 0E3C 071E 038F 0AAE
0557 1006 0803 180A 0C05 2410 1208 0904
0482 0241 06C4 0362 01B1 0514 028A 0145
03D0 01E8 00F4 007A 003D 00B8 005C 002E
0017 0046 0023 006A 0035 00A0 0050 0028
0014 000A 0005 0010 0008 0004 0002 0001
</pre>
 
1,489

edits