Last changed 8 Jan 2011
This is a one-time hobby of mine: to write some silly thing in as many programming languages as possible. Here we calculate averages. Not all of these are tested! and even those that are, are not guaranteed to work in any particular environment.
See also Raiding the Lost Lottery Line.
ABC was designed for the same purpose as Pascal and BASIC in their turns: to be an easy-to-learn language with which it would be very difficult to fall into bad programming habits. BASIC failed, and since there is no comment statement in ABC as far as I know, I hardly think you could call ABC victorious either. Anyway, this was the predecessor of Python.
As you can see, number 0 stands for end of input. That means 0 cannot be included in the list of values you want to get the average of; but in an interpreting environment this is the easiest way round. No serious piece of programming this one.
figure = 1
WHILE figure <> 0:
WRITE "Give a number, 0 to quit: "
READ figure EG 0
PUT sum + figure IN sum
PUT n + 1 IN n
PUT n - 1 IN n
PUT sum / n IN average
WRITE "Average =", average
Ada is a high-level procedural language much like
C
and
Pascal.
It has been developed by and for the US government, and sometimes it’s
been called the world’s first paranoid
programming language, as
it puts much emphasis on data protection.
This example is totally untested and I’m actually quite sure it’s still not 100% correct.
-- Calculating average in Ada
with Ada.Text_IO;
use Ada.Text_IO;
n : INTEGER := 0;
figure : FLOAT := 1.0;
sum : FLOAT := 0.0;
begin CalcAverage
while figure != 0.0 loop
Text_IO.Put("Give a number, or 0 to quit: ");
Text_IO.Get(figure);
n := n + 1;
sum := sum + figure;
end loop;
n := n - 1;
average := sum / n;
Text_IO.Putline("Average = ", average);
end CalcAverage;
AWK is a text-scanning, not a general-purpose programming language. Since AWK programs always have an implicit input loop, there is no need to write an input routine: we just have to make sure the data obtained is valid.
Previously, I had here a version that only expected one figure per input line—I said we shouldn’s bother about anything more refined. Well, now I’ve refined it. In effect, this script can slurp in any text file and ultimately produce an average of all the figures found inside it, negative ones included, unlike before.
# Calculating average in AWK
/-?[0-9]+.?[0-9]*/ {
for (p = 1; p <= NF; p ++)
if ($p ~ /^-?[0-9]+.?[0-9]*$/) {
sum += $p
n ++
}
}
END {
average = sum / n
printf("Average = %f\n", average)
}
Here I tried to approximate the feeling of very primitive
BASIC: no advanced loop control, just a
clause
forcing the control to move onto a given line number—the so-called
GOTOspaghetti BASIC.
Later BASICs got very close to, say,
Pascal.
There were a few commonly used abbreviations in later
BASICs, too. For instance,
was typed
PRINT
to save a couple of bytes of the precious memory
space, and ?
was redundant after
GOTO
for the same reason. THEN
clause is optional when there was no need to end the run prematurely.END
0 again stands for the end-of-input, as in the ABC code.
100 REM Calculating average in BASIC 110 REM 120 PRINT "Give a number, 0 to quit: "; 130 INPUT F 140 S=S+F 150 N=N+1 160 IF F<>0 THEN GOTO 120 170 N=N-1 180 A=S/N 190 PRINT "Average ="; A 200 END
Nothing remarkable here except the eyesore syntax, at least when compared to Pascal or Python.
I think there is no reason to prompt the user as in the ABC etc. samples, since C programs can easily read the standard input.
/* Calculating average in C */
#include <stdio.h>
void main(void)
{
double figure = 1.0, sum = 0.0, average;
int n = 0;
for (; figure; sum += figure, n ++)
scanf("%lf", &figure);
average = sum / -- n;
printf("Average = %lf\n", average);
}
This is hardly any different from C except in minor points. In a program of this size, there is no gain in utilizing the object-orientedness of the language.
C++ standards have changed lately, so I have had to modify the following a bit; nowadays it’s obligatory to specify namespaces.
// Calculating average in C++
#include <iostream>
int main(void)
{
double figure = 1.0, sum = 0.0, average;
int n;
for (n = 0; figure; n ++, sum += figure)
std::cin >> figure;
average = sum / -- n;
std::cout << "Average =" << average << std::endl;
return(0);
}
As in my samples in other languages, I tried to find
the true
COBOL here, which means going back in time a bit.
0 stands for end of input. Cf. ABC.
IDENTIFICATION DIVISION.
PROGRAM-ID. CALC-AVERAGE.
*
* Calculating average in COBOL
*
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
DATA DIVISION.
WORKING-STORAGE SECTION.
FIGURE PIC 999999.999 VALUE 0.
SUM PIC 9999999.9999 VALUE 0.
N PIC 99 VALUE 0.
AVERAGE PIC ZZZZZZ9.9ZZZ VALUE 0.
PROCEDURE DIVISION.
MAIN SECTION.
PERFORM SUM-FIGURES UNTIL FIGURE EQUALS TO 0.
DIVIDE SUM BY N GIVING AVERAGE.
DISPLAY "Average =", AVERAGE.
MAIN-EX.
EXIT.
END RUN.
SUM-FIGURES SECTION.
DISPLAY "Give a number, 0 to quit: ".
ACCEPT FIGURE.
ADD FIGURE TO SUM.
ADD 1 TO N.
SUM-FIGURES-EX.
EXIT.
As becomes the Forth ideology, this is a one-liner.
Adherents in other languages may want to use indentations and such to
point out the structure. The input-output ideology tries to be as much
Forthish,
as possible: there is neither input nor output here.
The word
created in the sample expects to find its input in the
stack when it is called, and the answer is left in the stack when done.
What happens? First we get the
of the stack, i.e., the number of items in it. The value goes to the top
of the stack, where we depthduplicate it, since we’ll be
needing it twice. One of these values is put the return stack
with
where it will be safe for a while. Now we go to a
loop from 1 to >r
(remember, we still have it on the
stack!). The body of the loop is between the depth
and
do
: so, we sum all the values we find in the stack
(the loop
value was already eaten up by
depth
). Finally, we get the saved value from the return
stack with do
. Now there are only two values left in
the stack: the sum and the r>
, so we divide the
former with the latter, leaving the result on the stack.depth
(Wow, it takes much longer in English!)
\ Calculating average in Forth ( n1 n2 ... -- n ) : avg depth dup >r 1 do + loop r> / ;
Old-fashioned Fortran, here, but not so old-fashioned that
we should use the predefined variable names (i etc. for
integers, f etc. for floats and so on).
0 stands for end of input. Cf. ABC.
c Calculating average in Fortran
program average
real f, s, a
integer n
s=0
n=0
10 write (*,*) 'Give a number, 0 to quit:'
read (*,*) f
s=s+f
n=n+1
if (f.eq.0) goto 10
n=n-1
a=s/n
write (*,*) 'Average =', a
stop
end
Haskell is a purely-functional programming language.
The example given doesn’t have any I/O: it only specifies the function to be called when calculating the average of a list of floats.
avg :: [Float] -> Float avg xs = sum xs / (fromIntegral (length xs))
Icon can be notoriously cryptic when used by real gurus. It has ingenious control structures that do not return a value but signal failure or success, which makes it very easy to hide value-checking inside ordinary statements.
In my sample here, there is no need to write an explicit
end-of-loop test in the
clause, since
while
fails when no more input is available,
and that makes read()
fail (and end) too.while
# Calculating average in Icon
procedure main()
sum := n := 0
while sum +:= read() do n +:= 1
write("Average = ", average := sum / n)
end
This one expects to be called from somewhere, as befits JavaScript’s Web-based ideology.
// Calculating average in JavaScript
function calcAverage(l)
{
for (i = 0; i < calcAverage.arguments.length;
i ++, sum += calcAverage.arguments[i]) ;
average = sum / calcAverage.arguments.length;
document.write('Average =', average);
}
One silly language this one, just a little better than the
hideous MS-DOS batch language (or rather, language
).
; Calculating average in KiXtart
$figure = 1
$sum = 0
$n = 0
WHILE "$figure"
"Give a number, 0 to quit:"
GET $figure
$sum = $sum + $figure
$n = $n + 1
LOOP
$n = $n - 1
$average = $sum / $n
"Average =" $average
Lots of Idiotic Silly Parentheses,
eh? Well, the
syntax is a bit rough for us humans, but still, the ideology in
Lisp is quite sound.
I had here previously a version that used
(eval), but Teemu Likonen proposed me the following,
more “Lisp-like” version that uses (apply).
; Calculating average in Lisp (defun average (numbers) (/ (apply #'+ numbers) (length numbers)))
The syntax of Pascal is as lucid as you could hope for. For short tasks as in here, the lucidity tends to give an additional length to the code, but Pascal-adherents worship readability above all. (The same is true of Python.)
{ Calculating average in Pascal }
program CalcAverage(input, output);
var figure, sum, average : double;
n : integer;
begin
figure := 1.0;
sum := 0.0;
n := 0;
while figure <> 0 do begin
write ('Give a number, 0 to quit: ');
read (figure);
sum := sum + figure;
n := n + 1
end;
average := sum / n;
writeln ('Average =', average)
end.
Perl is one of the languages with which you can write absolutely unreadable code if so you wish (cf. AWK, Icon). The sample here is an eyesore for all Pascal-lovers, but still pretty easy to figure out.
# Calculating average in Perl
for (; <>; $sum += $_, $n ++) {}
$average = $sum / $n;
print "Average = $average\n";
This example is totally untested, since I don’t currently have an interpreter for Pilot, though I once even ported one to OS/2. Silly language. I wonder whoever thought that language of this kind would be suitable for the educational environment?!
The syntax is extremely crude and simplistic. It can be
directly read once you grasp that the one-letter commands are just
abbreviations of common English verbs: A
for accept,
C
for compute, J
for jump, and T
for
type.
R:Calculating average in Pilot *INPUT T:Give a number, or 0 to quit: A:#F C:#S=#S+#F C:#N=#N+1 J(#F<>0):*INPUT C:#N=#N-1 C:#A=#S/#N T:Average = #A
This one is a real milestone on the bumpy road of programming language history. PL/I paved the road for languages like Pascal and C with its neat procedural syntax.
/* Calculating average in PL/I */
KESKIARV: PROCEDURE OPTIONS (MAIN);
DECLARE (LUKU, SUMMA, KESKIARVO) FIXED BIN(15);
DECLARE (LKM) FIXED BIN(7);
LUKU = 1;
SUMMA = 0;
LKM = 0;
DO WHILE (LUKU <> 0);
PUT SKIP DATA "Give a number, 0 to quit: ";
GET LUKU;
SUMMA = SUMMA + LUKU;
LKM = LKM + 1;
END DO;
PUT SKIP DATA "Keskiarvo =", keskiarvo
END KESKIARV;
Python may be the easiest language for humans to read.
The following example uses standard input, which necessitates
the from ... import line. The code requires Python 2 or newer,
since the contracted assignment operators (e.g.,
)
were borrowed from the C tradition at that time. I think the decision to do
that was good: there’s a (+=deep
) semantic difference
between modifying an existing value in a variable and assigning it a
totally new value. In my mind,
is quite different from n = n + 1
even though the
result is the same.n += 1
# Calculating average in Python
from sys import stdin
sum = 0.0
n = 0
for line in stdin:
sum += float(line)
n += 1
average = sum / n
print('Average = {0}'.format(average))
The next example uses list comprehension to process the data from the standard input – nice. It requires enough memory to hold the whole file and more, but that will be a problem only with very large files.
First, sys.stdin.readlines() reads the standard I/O until
EOF and returns everything in a list of strings. Next, list
comprehension is used to create a copy of the (temporary) input buffer
where each element is cast into floats. This list is assigned
the name nums; and the rest is easy.
# Calculating average in Python
import sys
nums = [float(num) for num in sys.stdin.readlines()]
average = sum(nums) / len(nums)
print('Average = %f\n' % average)
REXX is a nice well-behaved little language. I used it a lot back in my OS/2 days. The sample should be self-explanatory for all with any familiarity with procedural languages.
/* Calculating average in REXX */
sum = 0.0
n = 0
do loop until figure = 0
pull figure
sum = sum + figure
n = n + 1
end do
n = n - 1
average = sum / n
say "Average =" average
Ruby is still a newcomer in the field. Being an interpreted
language suitable for scripting, it competes primarily with
Perl
and
Python,
but unlike them, it’s fully object-oriented. Thus it’s also something like
Smalltalk to the masses
.
Syntactically Ruby is closer to Perl than Python, but it does not inherit the uglyness: variable names do not need to be preceded by silly characters (those which in Perl tell the type of the variable), statements do not need the trailing semicolons, and so on.
Some people see Ruby as the successor
to
Perl—that still remains to be seen, I guess.
# Calculating average in Ruby
sum = 0.0
n = 0
ARGF.each do |line|
summa += line.to_f
n += 1
end
average = sum / n
print "Keskiarvo = #{average}"
Scheme is very much like (some dialects of)
Lisp.
Not being accustomed to it, I find it’s idea very much harder to
grasp to Lisp’s, but I guess every detail is nicely reasoned even
when bewildering for a newbie. See the tidier-looking Lisp example to see
what I mean by bewildering
!
Anyway, this example does not work for
the idiotic reason that the-environmentmay only be
evaluated in a top-level environment,
as it spells out in the
manual. Nowhere is it said what would be a possible environment for
lower-level evals.
; Calculating the average in Scheme
(define average
(lambda (#!rest l)
(/ (eval (append '(+) l) (the-environment)) (length l)))
Speaking of silly languages Still, Tcl is pretty straigtforward once you get accustomed to the cumbersome notation used when, for example, setting values to variables.
Tcl is often (solely?) used because of its quite usable Tk
GUI toolkit, so often in fact that you see the name Tcl/Tk
mentioned
much more often than plain Tcl
.
(For years and years, the following code used to be syntactically incorrect. I knew of that but couldn’t run it anywhere to get it right. Now it seems to work at least on my Linux box.)
# Calculating the average in Tcl
set fig 1
set sum 0
set n 0
while { $luku != 0 } {
puts "Give a number or 0 to quit:"
gets stdin fig
set sum [ expr $sum + $fig ]
incr n
}
set n [ expr $n - 1 ]
set average [ expr $sum / $n ]
puts stdout "Average = $average"
Perhaps not a fully-fledged programming language, this
one
JP Software’s
4DOS was (and is, now as freeware) an alternative to the extremely cude
MS-DOS command interpreter, command.com
. It has reincarnated as 4OS2
for OS/2, 4NT for Windows NT, and Take Command for various Windows GUIs, all
of which inherit the same syntax.
@echo off
rem Calculating average in 4DOS batch language
setlocal
set sum=0
set n=0
do while %figure ne 0
echo Give a number, or 0 to quit:
input %%figure
set sum=%@eval[%sum + %figure]
set n=%@eval[%n + 1]
enddo
set n=%@eval[%n - 1]
set average=%@eval[%sum / %n]
echo Average = %average
endlocal