On 2 Nov 2010, at 19:53, Rich Mellor wrote:
> I was just reading that 99/100 job applicants for programming jobs apparently
> cannot write a short "fizzbuzz" program when given 10 minutes to do so in an
> interview.
>
> The rules are simple -
> write out the values 1 to 100 on screen
> If the value is divisble by 3 write 'FIZZ' after the number
> If the value is divisble by 5 write 'BUZZ' after the number
> If the value is divisble by 3 and 5 write 'FIZZBUZZ' after the number
>
> My inelegant machine code program (untested) is:
>
> Sorry - made an error when typing the 68000 assembly language in - I hit a
> key which submitted the form!
>
> start MOVEQ #-1,D1 ;Open a screen channel
> LEA screen,A0
> MOVEQ #2,D3
> MOVEQ #1,D0
> TRAP #3 ;Uses built in ROM routine to open screen
> BNE.S end
> MOVEQ #6,D1
> MOVE.L A1,$58(A6) ; make room on maths stack for 6 bytes
> MOVE.W $11A,A2
> JSR (A2)
> MOVE.L $58(A6),A1
> MOVEQ #1,D6 ;Initial Loop value
> loop MOVE.L (A6),A1
> LEA 2(A1),A0
> MOVE.W D6,0(A6.A1.L) ;store value on stack
> MOVE.W $F2,A2
> JSR (A2) ;convert number to ASCII
> MOVE.W D1,D2 ; grab length of number
> MOVEQ #7,D0
> MOVEQ #-1,D3
> TRAP #3
> MOVE.L D6,D7
> DIVU #3,D7
> SWAP D7
> CMPI.W #0,D7
> BEQ.S testbuzz
> LEA fizz,A1
> MOVE.W $D0,A2 ; print string
> JSR (A2)
> testbuzz MOVE.L D6,D7
> DIVU #5,D7
> SWAP D7
> CMPI.W #0,D7
> BEQ.S nwline
> LEA buzz,A1
> MOVE.W $D0,A2
> JSR (A2)
> nwline MOVEQ #10,D1 ;Print a new line
> BSR.S printchr
> CMPI.B #100,D6
> BEQ.S end
> ADDQ.B #1,D6
> BRA.S loop
> end MOVEQ #0,D0
> RTS
> printchr MOVEQ #-1,D3
> MOVEQ #5,D0
> TRAP #3
> MOVEQ #0,D0
> RTS
> screen DC.W 17
> DC.B 'con_448x200a32x16',0
> fizz DC.W #4
> DC.B 'FIZZ'
> buzz DC.W #4
> DC.B 'BUZZ'
>
> I am sure plenty can write this in SuperBASIC, but is there a simpler
> solution in machine code?
>
I suppose that there is always a simpler method. I would not use arithmetic to
find whether the printed number is divisible by 3 or 5. I wrote a program which
actually does, after correction of course, print what is asked for. To do this
I had to open a window first (just "con") and set paper, strip and ink. Then I
had to clear the window. What a palaver!
The actual program to do the printing was:
moveq #100,d7
moveq #12,d4 ; Lines per page - 1
moveq #2,d6 ; count of 3 (0,1,2)
moveq #4,d5 ; count of 5
bra lp1
lp2 moveq #100,d1 ; find . .
sub.w d7,d1 ; . . the number
bsr prt ; print it (UT_MINT)
dbf d6,lp3 ; divisible by 3? . .
moveq #2,d6 ; reset count of 3
bsr fizz ; print FIZZ
lp3 dbf d5,lp4 ; divisible by 5? . .
moveq #4,d5 ; reset count of 5
bsr buzz ; print BUZZ
lp4 moveq #10,d0 ; to print LF (I had forgotten NL!)
moveq #io_sbyte,d0
bsr tp3 ; I prefer to use SRs so that I can
more easily use QMON to pass Traps
dbf d4,lp1 ; count lines on page
moveq #io_fbyte,d0
bsr tp3 ; Pause (else the page contents are
not seen)
moveq #sd_clear,d0
bsr tp3 ; clear the window for the next
pageful
lp1 dbf d7,lp2
moveq #io_fbyte,d0
bsr tp3 ; a final pause
................. ; The program ends somehow
tp3 trap #3
rts
; To print the number in D1
prt movea.w ut_mint,a2
jmp (a2)
; to print FIZZ
fizz lea fz,a1 ; A1 -> FIZZ
bra bz1
; To print BUZZ
buzz:
lea bz,a1 ; A1 -> BUZZ
bz1 movea.w ut_mtext,a2
jmp (a2)
fz dc.w 4
dc.b "FIZZ"
bz dc.w 4
dc.b "BUZZ"
If I were marking attempts at programming this exercise I would give more marks
to robustly written programs which contained slips rather than a weakly written
program that worked. For example it is better to have a program which can
easily be altered to produce other divisors than 3 and 5. Anyway I must confess
that my first version had set 3 and 5 set in D6 and D5 instead of the correct
values 2 and 4. Time to program the essential bits circa 8 minutes. Time to
correct this and add bits which would be needed in an actual program 20 minutes.
I await with interest some really small pieces of assembler code doing the same
thing.
This would take, I suppose, 3 minutes in S*BASIC.
George
_______________________________________________
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm