The TPK (Knuth & Pardo) program was concocted by DonaldKnuth and Luis Trabb Pardo as part of their work "The early development of Programming Languages" which appeared in A History of Computing in the Twentieth Century (ISBN: 0-12-491650-3 Metropolis, N., Howlett, J., Cota, Gian-Carlo, eds., Academic Press, New York, 1980). Their idea was to introduce a trivial program which involved arrays, indexing, transcendental functions, subroutines, input, output, conditionals, and iteration, and then to demonstrate how several early (pre-1960) languages implemented such concepts. Examples of TPK are somehow much more satisfying than HelloWorlds.
- The example given, which is claimed to be the original, doesn't actually have any transcendental functions.
As originally stated in AlgolLanguage:
begin integer i; real array a[0:10];
real procedure f(t); real t; value t;
f:=sqrt(abs(t))+5*t^3;
for i:=0 step 1 until 10 do read(a[i]);
for i:=10 step -1 until 0 do
begin y:=f(a[i]);
if y > 400 then write(i, "TOO LARGE")
else write(i,y);
end
end
program useless(input,output);
var i:integer, y:real, a:array[0..10] of real;
function f(t:real):real;
begin f := sqrt(abs(t)) + 5*t*t*t end;
begin
for i:= 0 to 10 do
read(a[i]);
for i:= 10 downto 0 do
begin
y := f(a[i]);
if y > 400 then
writeln(i, "TOO LARGE")
else
writeln(i,y);
end;
end.
#include <math.h>
#include <stdio.h>
static double f(double t);
int main(void) {
int i;
double y, a[11];
for(i = 0; i <= 10; i++) scanf("%lf", &a[i]);
for(i = 10; i >= 0; i--) {
if ((y = f(a[i])) > 400.0)
printf("%d TOO LARGE\n", i);
else
printf("%d\t%lf\n", i, y);
},
return 0;
},
static double f(double t) {
return sqrt(fabs(t)) + 5 * pow(t,3);
},
Option Explicit
Sub main()
Dim a(0 To 10) As Double, i As Long, y As Double
For i = 0 To 10
a(i) = InputBox("")
Next i
For i = 10 To 0 Step -1
y = f(a(i))
If y > 400 Then
MsgBox "Too Big", vbExclamation, CStr(i)
Else
MsgBox CStr(y), , CStr(i)
End If
Next i
End Sub
Private Function f(t As Double) As Double
f = Sqr(Abs(t)) + 5 * t ^ 3
End Function
\ tpk
\ requires FLOAT word set (fdup f* fover fswap f+ f< fdrop falign floats f! f@)
\ requires FLOAT EXT word set (fabs fsqrt >float f.)
: f ( f -- |f|+5*f^3 )
fdup fdup f* fover f* 5e f* fswap fabs fsqrt f+ ;
: parse-f ( "num" -- addr len ) bl parse ;
: accept-f ( -- addr len ) pad dup 40 accept ;
: str>f ( addr len -- f ) >float 0= abort" bad number!" ;
: .max400 ( f -- )
400e fover f< if fdrop ." too large" else f. then ;
\ with array
: farray ( n -- ) falign create floats allot
does> ( i -- a[i] ) swap floats + ;
11 farray a
: tpka
11 0 do parse-f str>f i a f! loop \ or accept-f (user types one float per line)
0 10 do cr i . i a f@ f .max400 -1 +loop ;
tpka -5 -4 -3 -2 -1 0 1 2 3 4 5
\ on stack (environmental dependency: needs 13 deep, min 6 deep)
: tpks
11 0 do parse-f str>f loop
11 0 do cr 10 i - . f .max400 loop ;
tpks -5 -4 -3 -2 -1 0 1 2 3 4 5
function print(s) { document.write(s + "<br>") }, // or such
function f(x) { return Math.sqrt(Math.abs(x)) + 5*Math.pow(x,3) },
function tpk() {
var a = prompt("Enter 11 numbers:").match(/[-.\d]+/g);
while (a.length) {
var v = f(a.pop());
print(v>400 ? "TOO LARGE" : v);
},
},
tpk();
import math, re
def f(x): return math.sqrt(abs(x)) + 5 * x**3
a = re.findall(r'[-.\d]+', raw_input('Enter 11 numbers: '))
for i, num in enumerate(a):
y = f(float(num))
if y > 400: print i, 'TOO LARGE'
else: print i, y
sub f { my ($x) = @_; sqrt(abs($x)) + 5 * $x**3 },
print 'Enter 11 numbers: ';
my @a = <> =~ /[-.\d]+/g;
foreach my $i (0 .. $#a) {
my $y = f($a[$i]);
if ($y > 400) { print "$i TOO LARGE\n"; },
else { print "$i $y\n"; },
},
def f(x)
Math.sqrt(x.abs) + 5 * x**3
end
print 'Enter 11 numbers: '
a = gets.scan(/[-.\d]+/)
a.each_with_index { |num, i|
y = f(num.to_f)
if y > 400 then puts "#{i}, TOO LARGE"
else puts "#{i}, #{y},"
end
},
let f x =
sqrt (abs_float x) +. 5. *. x ** 3.
;;
let () =
let a = Array.init 11 (fun _ -> read_float ()) in
Array.iteri (fun i x ->
let y = f x in
if y > 400. then
Printf.printf "%d TOO LARGE\n" i
else
Printf.printf "%d\t%f\n" i y) a
;;
! This is Fortran 90, simply because the language did
! NOT stop developing after FORTRAN-77.
! The gfortran frontend to gcc successfully compiles this.
real(8) function f(t)
implicit none
real(8), intent(in) :: t
f = sqrt(abs(t)) + 5.0_8 * t**3
return
end function f
program tpk
implicit none
integer :: i
real(8) :: a(11), y
interface
real(8) function f(t)
real(8), intent(in) :: t
end function f
end interface
do i = 1,11
read (*,*) a(i)
end do
do i = 0,10
y = f(a(11-i))
if (y > 400.0) then
print *, 11-i, " too large"
else
print *, 11-i, "\t", y
end if
end do
stop
end program tpk
import Control.Monad
f x = sqrt (abs x) + 5 * x ** 3
main = do a <- replicateM 11 readLn
forM_ (zip [0..] a)
(\(i,x) -> if y > 400 then
putStrLn (show i ++ " TOO LARGE")
else
putStrLn (show i ++ "\t" ++ show y)
where y = f x)
fun f x =
Math.sqrt (abs x) + 5.0 * Math.pow (x, 3.0)
;
val () = let
val a = Array.tabulate (11, fn _ => valOf (Real.fromString (valOf (TextIO.inputLine TextIO.stdIn))))
in
Array.appi (fn (i, x) => let
val y = f x
in
if y > 400.0 then
print (Int.toString i ^ " TOO LARGE\n")
else
print (Int.toString i ^ "\t" ^ Real.toString y ^ "\n")
end) a
end
;
It would be interesting to see a solution in an array-oriented language like APL, J, K, L, etc.
As usual, I come up with a good idea and then find someone else has already carried it out. Check out http://cs.fit.edu/~ryan/compare/ for more of this sort of thing (note, connection is slow). -- DavidBrantley
See also:
CategoryInManyProgrammingLanguages CategoryAlgorithm