Coding challenge: FizzBuzz

Miscellaneous Forums/General Discussion/Coding challenge: FizzBuzz

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Nasty:

Global AllFuncs:TList = New TList

Type Func
	
	Global out$	
	Field name$
	Field myargs$[]
	Field body$
	
	Method Execute$( args$[] )
		
		Assert( Len( args ) = Len( myargs ) )
		
		Local newbody$ = body
		
		For Local c = 0 Until Len( myargs )
			
			newbody = newbody.replace( myargs[ c ], eval( args[ c ] ) )
			
		Next
		
		Return Eval( newbody )
		
	End Method
	
End Type

Type DefunFunc Extends Func
	
	Method New( )
		
		name = "defun"
		
		AllFuncs.AddLast( Self )
		
	End Method
	
	Method Execute$( args$[] )
		
		Local meth$[] = pParse( args[ 0 ] )
		Local body$ = args[ 1 ]
			
		Local f:Func = New Func

		f.Name = meth[ 0 ]
		f.myargs = meth[1..]
		f.body = body
		
		AllFuncs.AddLast( f )
		
	End Method
	
End Type

Type IfFunc Extends Func
	
	Method New( )
		
		name = "if"
		
		AllFuncs.AddLast( Self )
		
	End Method
	
	Method Execute$( args$[] )
		
		If Eval( args[ 0 ] ) = "nil"
			
			Return Eval( args[ 2 ] )
			
		Else
			
			Return Eval( args[ 1 ] )
			
		EndIf
				
	End Method
	
End Type

Type EqFunc Extends Func
	
	Method New( )
		
		name = "="
		AllFuncs.Addlast( Self )
		
	End Method
	
	Method Execute$( args$[] ) 
		
		If ( Double( Eval( args[ 0 ] ) ) = Double( Eval( args[ 1 ] ) ) )
			
			Return "1"
			
		Else
		
			Return "nil"
			
		EndIf
		
	End Method
	
End Type


Type LTFunc Extends Func
	
	Method New( )
		
		name = "<"
		AllFuncs.Addlast( Self )
		
	End Method
	
	Method Execute$( args$[] ) 
		
		If ( Double( Eval( args[ 0 ] ) ) < Double( Eval( args[ 1 ] ) ) )
			
			Return "1"
			
		Else
		
			Return "nil"
			
		EndIf
		
	End Method
	
End Type

Type Pr Extends Func
	
	Method New( )
	
		name = "pr"
		AllFuncs.AddLast( Self )
	
	End Method
	
	Method Execute$( Args$[] )

		Local n[] = [ $46, $69, $7A, $42, $75 ]
		
		
		If Int( Eval( Args[ 0 ] ) ) > 100
			
			Print Func.Out
			End
		
		Else
		
			Func.Out:+[ String( Int( Eval( Args[ 0 ] ) ) ), Pr( n, [ 0, 1, 2, 2 ] ), Pr( n, [ 3, 4, 2, 2 ] ), Pr( n, [ 0, 1, 2, 2 ] ) + Pr( n, [ 3, 4, 2, 2 ] ) ][ Int( Eval( Args[ 1 ] ) ) ] + "~n"
				
		EndIf

	End Method
	
	
	Method Pr$( ca[], n[] )
		
		Local o$
		
		For Local c = EachIn n
		
			o:+Chr(ca[c])
		
		Next
		
		Return o
		
	End Method
	
	
End Type

Type SubFunc Extends Func
	
	Method New( )
		
		name = "-"
		AllFuncs.Addlast( Self )
		
	End Method
	
	Method Execute$( args$[] ) 
	
		Return Double( Eval( args[ 0 ] ) ) - Double( Eval( args[ 1 ] ) )

	End Method
	
End Type


Type PlusFunc Extends Func
	
	Method New( )
		
		name = "+"
		AllFuncs.Addlast( Self )
		
	End Method
	
	Method Execute$( args$[] ) 
	
		Return Double( Eval( args[ 0 ] ) ) + Double( Eval( args[ 1 ] ) )

	End Method
	
End Type

Type TimesFunc Extends Func
	
	Method New( )
		
		name = "*"
		AllFuncs.Addlast( Self )
		
	End Method
	
	Method Execute$( args$[] ) 
		
		Return Double( Eval( args[ 0 ] ) ) * Double( Eval( args[ 1 ] ) )

	End Method
	
End Type

Local d:DefunFunc = New DefunFunc
Local f:IfFunc = New IfFunc
Local eq:EqFunc = New EqFunc
Local sub:SubFunc = New SubFunc
Local plus:PlusFunc = New PlusFunc
Local times:TimesFunc = New TimesFunc
Local lt:LTFunc = New LTFunc
Local p:PR = New PR

For Local str$ = EachIn [ "(defun (i n p) (if (< n p) (= n 0) (i (- n p) (- p 0))))", "(defun (pp t) (if (pr t (+ (i t 3) (+ (i t 5) (i t 5) ) ) ) ) )", "(defun (it a) (if (pp a) (it (+ a 1)) (it (+ a 1)) ) )", "(it 1)" ]
	
	Eval( str )
	
Next

Function Eval$( str$ )
		
	Local funcs$[] = pParse( str )

	For Local f:Func = EachIn AllFuncs
		
		If ( f.Name = funcs[ 0 ] )
			
			Local n$ = f.Execute( funcs[1..] )
			
			Return n
			
		EndIf
	
	Next
	
	Return str
		
End Function

Function pParse$[]( str$ )
	
	Local ret$[256]
	Local level = 0
	Local slot = 0
	
	For n = 1 To Len( str )
		
		
		If level > 1 Or ( ( Level = 1 ) And ( Mid( str, n, 1 ) = "(" ) )
			
			ret[ slot ]:+Mid( str, n, 1 )
			
		EndIf
		
		
		Select Mid( str, n, 1 )
		
			Case "("
				
				level:+1
				
			Case ")"
				
				level:-1
				
			Case " "
				
				If ( level <= 1 )
				
					If ret[ slot ] <> ""
						
						slot:+1
						
					EndIf
					
				EndIf
			
			Default
				
				If level <= 1
					
					ret[ slot ]:+Mid( str, n, 1 )
					
				EndIf
				
				
		End Select
		
		
	Next
	
	Return ret[..slot+1]

End Function