"""
Knuth's TPK program in Cobra

From http://en.wikipedia.org/wiki/Trabb_Pardo-Knuth_algorithm

"In their 1977 work "The Early Development of Programming Languages", Trabb Pardo
 and Knuth introduced a trivial program which involved arrays, indexing,
 mathematical functions, subroutines, I/O, conditionals and iteration. They then
 wrote implementations of the algorithm in several early programming languages to
 show how such concepts were expressed."

While this is useful for demonstrating a few basic things about a language, it
does not demonstrate well the features surrounding larger issues such as
organizing large code bases, working on a team, documenting your code, etc.
Also, the standard TPK code mixes input, computations and output all together.
It also directly references stdin and hard codes constants rather than taking
parameters for those things.

But some people still like to see this code to compare it to other languages.
So here it is, including a better version that addresses some of the above issues.
"""

class TPK

	shared

		def f(x as number) as number
			return x.abs.sqrt + 5.0 * x.pow(3.0)
		
		def basicTPK1
			a = number[](11)
			
			# read in the values for the array, one per line
			for i in a.length
				a[i] = number.parse(Console.readLine)
			
			# in reverse order, apply "f" to each element of the array and
			# print the result, including index
			for i in a.length-1 : 0 : -1
				y = .f(a[i])
				print '[i] ', if(y>400, 'TOO LARGE', y)

		def basicTPK2
			# some versions in other languages print the input number
			# rather than its index
			a = number[](11)
			for i in a.length
				a[i] = number.parse(Console.readLine)
			Array.reverse(a)
			for x in a
				y = .f(x)
				print '[x] ', if(y>400, 'TOO LARGE', y)

		def betterTPK
			"""
			Invokec .betterTPK with default arguments: Console.in, 11 and 400.
			"""
			.betterTPK(Console.in to !, 11, 400)

		def betterTPK(tr as TextReader, count as int, limit as number)
			require
				count > 0
			ensure
				# Well there's not much to ensure for a method that dumps its
				# results as textual output. An even better approach is to
				# separate computation from I/O so that computations can be
				# more easily tested, contracted and reused.
				true
			test
				# Now that we're using parameters, we can make a proper test.
				sw = StringWriter()
				print to sw
					.betterTPK(StringReader('1\r\n1\r\n'), 2, 400)
				r = sw.toString.replace('\r','').replace('\n','; ')
				assert r == '1  6.0; 1  6.0; '
			body
				a = number[](count)
				for i in a.length
					a[i] = number.parse(tr.readLine)
				Array.reverse(a)
				for x in a
					y = .f(x)
					print '[x] ', if(y>limit, 'TOO LARGE', y)

		def main
			if false
				print
				print 'Basic TPK - Enter numbers:'
				.basicTPK1
			if true
				print
				print 'Better TPK - Enter numbers:'
				.betterTPK

