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.
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: