Soloway's recurring rainfall: Difference between revisions

m
(Added Quackery.)
 
(10 intermediate revisions by 8 users not shown)
Line 101:
END
</syntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="arturo">i: 0
sum: 0
 
while ø [
n: input "Enter rainfall as integer (99999 to quit): "
try? -> n: to :integer n
else [
print "Input must be an integer."
continue
]
if 99999 = n -> break
'i + 1
'sum + n
print ~« The current average rainfall is |sum // i|.
]</syntaxhighlight>
 
{{out}}
 
<pre>Enter rainfall as integer (99999 to quit): 145
The current average rainfall is 145.0.
Enter rainfall as integer (99999 to quit): 43678
The current average rainfall is 21911.5.
Enter rainfall as integer (99999 to quit): 9
The current average rainfall is 14610.66666666667.
Enter rainfall as integer (99999 to quit): 155
The current average rainfall is 10996.75.
Enter rainfall as integer (99999 to quit): 99999</pre>
 
=={{header|BASIC}}==
Line 361 ⟶ 391:
}
}
</syntaxhighlight>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
Although Delphi supports console applications that use simple keyboard input and teletype output, the primary focus of the language is GUI development. Consequently, I've produced a GUI version of the problem that uses the "TMemo" component to simulate a console interface.
 
To get the TMemo to behave like a console application, I've created an object that captures keyboard into to the TMemo and can return the keystrokes a chars, integers or reals. The object, which is called "TKeyWaiter," is simply created and attached to a TMemo component. While the object is alive, it will capture key stroke and return chars, integers or reals. It can be destroyed as soon as it is no longer needed. In fact, in this code, I create and destroy it for every input. The creation overhead is so low that there is no reason to create a global copy and keep it alive while the program is operating.
 
<syntaxhighlight lang="Delphi">
 
{This code would normally be in a library somewhere, but it is included here for clarity}
 
{TKeywaiter interface}
 
type TKeyWaiter = class(TObject)
private
FControl: TWinControl;
FControlCAbort: boolean;
protected
procedure HandleKeyPress(Sender: TObject; var Key: Char);
public
KeyChar: Char;
ValidKey: boolean;
AbortWait: boolean;
constructor Create(Control: TWinControl);
function WaitForKey: char;
function WaitForInteger: integer;
function WaitForReal: double;
property ControlCAbort: boolean read FControlCAbort write FControlCAbort;
end;
 
 
{ TMemoWaiter implementation }
 
type TControlHack = class(TWinControl) end;
 
constructor TKeyWaiter.Create(Control: TWinControl);
{Save the control we want to wait on}
begin
FControl:=Control;
FControlCAbort:=False;
end;
 
procedure TKeyWaiter.HandleKeyPress(Sender: TObject; var Key: Char);
{Handle captured key press}
begin
KeyChar:=Key;
ValidKey:=True;
if ControlCAbort then AbortWait:=KeyChar = #$03;
end;
 
 
function TKeyWaiter.WaitForKey: char;
{Capture keypress event and wait for key press control}
{Spends most of its time sleep and aborts if the user}
{sets the abort flag or the program terminates}
begin
ValidKey:=False;
AbortWait:=False;
TControlHack(FControl).OnKeyPress:=HandleKeyPress;
repeat
begin
Application.ProcessMessages;
Sleep(100);
end
until ValidKey or Application.Terminated or AbortWait;
Result:=KeyChar;
end;
 
 
function TKeyWaiter.WaitForInteger: integer;
var C: char;
var S: string;
begin
Result:=0;
S:='';
{Wait for first numeric characters}
repeat
begin
C:=WaitForKey;
if AbortWait or Application.Terminated then exit;
end
until C in ['+','-','0'..'9'];
{Read characters and convert to}
{integer until non-integer arrives}
repeat
begin
S:=S+C;
C:=WaitForKey;
if AbortWait or Application.Terminated then exit;
end
until not (C in ['+','-','0'..'9']);
Result:=StrToInt(S);
end;
 
 
type TCharSet = set of char;
 
function TKeyWaiter.WaitForReal: double;
var C: char;
var S: string;
const RealSet: TCharSet = ['-','+','.','0'..'9'];
begin
Result:=0;
S:='';
{Wait for first numeric characters}
repeat
begin
C:=WaitForKey;
if AbortWait or Application.Terminated then exit;
end
until C in RealSet;
{Read characters and convert to}
{integer until non-integer arrives}
repeat
begin
S:=S+C;
C:=WaitForKey;
if AbortWait or Application.Terminated then exit;
end
until not (C in RealSet);
Result:=StrToFloat(S);
end;
 
 
 
{===========================================================}
 
 
function WaitForReal(Memo: TMemo; Prompt: string): double;
{Wait for double entered into TMemo component}
var KW: TKeyWaiter;
begin
{Use custom object to wait for and capture reals}
KW:=TKeyWaiter.Create(Memo);
try
Memo.Lines.Add(Prompt);
Memo.SelStart:=Memo.SelStart-1;
Memo.SetFocus;
Result:=KW.WaitForReal;
finally KW.Free; end;
end;
 
var Count: integer;
var Average: double;
 
procedure RecurringRainfall(Memo: TMemo);
var D: double;
begin
Count:=0;
Average:=0;
while true do
begin
D:=WaitForReal(Memo,'Enter integer rainfall (99999 to quit): ');
if Application.Terminated then exit;
if (Trunc(D)<>D) or (D<0) then
begin
Memo.Lines.Add('Must be integer >=0');
continue;
end;
if D=99999 then break;
Inc(Count);
Average := Average + (1 / Count) * D - (1 / Count)*Average;
Memo.Lines.Add('New Average: '+FloatToStrF(Average,ffFixed,18,2));
end;
end;
 
</syntaxhighlight>
{{out}}
<pre>
Enter integer rainfall (99999 to quit):
5.4
 
Must be integer >=0
Enter integer rainfall (99999 to quit):
-2
 
Must be integer >=0
Enter integer rainfall (99999 to quit):
5
 
New Average: 5.00
Enter integer rainfall (99999 to quit):
2
 
New Average: 3.50
Enter integer rainfall (99999 to quit):
10
 
New Average: 5.67
Enter integer rainfall (99999 to quit):
99999
 
 
Elapsed Time: 01:56.914 min
 
</pre>
 
=={{header|EasyLang}}==
{{trans|BASIC256}}
<syntaxhighlight>
repeat
print "Enter integral rainfall (99999 to quit): "
i = number input
until i = 99999
if error = 1 or i < 0 or i mod 1 <> 0
print "Must be an integer no less than 0, try again."
else
n += 1
sum += i
print " The current average rainfall is " & sum / n
.
.
</syntaxhighlight>
 
Line 582 ⟶ 826:
rainfall_problem()
</syntaxhighlight>
 
=={{header|Nim}}==
We catch exceptions related to wrong input, i.e. non integer values. Negative values are allowed. If an end of file is encountered, the program terminates with an error message.
<syntaxhighlight lang="Nim">import std/[strformat, strutils]
 
const EndValue = 99999
 
 
var sum, count = 0.0
 
while true:
 
var value: int
 
# Read input until a valid integer if found.
var input: string
while true:
stdout.write &"Enter an integer value, {EndValue} to terminate: "
stdout.flushFile()
try:
input = stdin.readLine()
value = input.parseInt()
break
except ValueError:
echo &"Expected an integer: got “{input}”"
except EOFError:
quit "\nEncountered end of file. Exiting.", QuitFailure
 
# Process value.
if value == EndValue:
echo "End of processing."
break
count += 1
sum += value.toFloat
echo &" Current average is {sum / count}."
</syntaxhighlight>
 
{{out}}
Sample session.
<pre>Enter an integer value, 99999 to terminate: 10
Current average is 10.0.
Enter an integer value, 99999 to terminate: -20
Current average is -5.0.
Enter an integer value, 99999 to terminate: 50
Current average is 13.33333333333333.
Enter an integer value, 99999 to terminate: 3.5
Expected an integer: got “3.5”
Enter an integer value, 99999 to terminate: aaa
Expected an integer: got “aaa”
Enter an integer value, 99999 to terminate: 10
Current average is 12.5.
Enter an integer value, 99999 to terminate: 99999
End of processing.
</pre>
 
=={{header|Perl}}==
Line 830 ⟶ 1,128:
Integer units of rainfall in this time period? (999999 to finalize and exit)>: 999999
Average rainfall 0.00 units over 0 time periods.</pre>
 
=={{header|RPL}}==
{{works with|HP|28}}
{| class="wikitable" ≪
! RPL code
! Comment
|-
|
≪ "Enter rainfall, then ENTER" 1 DISP
"" "0123456789"
'''DO DO UNTIL''' KEY '''END'''
'''IF''' DUP2 POS '''THEN'''
ROT OVER + DUP 2 DISP ROT ROT
'''END'''
'''UNTIL''' "ENTER" == '''END'''
DROP STR→
≫ '<span style="color:blue">READB</span>' STO
≪ "Enter 9999 to end" 4 DISP
(0,0) 1 CF CLLCD
DO READB
'''IF''' DUP 9999 == '''THEN''' 1 SF
'''ELSE'''
1 R→C +
"Average = " OVER RE LAST IM / →STR +
3 DISP
'''END'''
'''UNTIL''' 1 FS? '''END'''
SWAP DROP CLMF
'''IFERR''' RE LAST IM / '''THEN''' DROP2 '''END'''
≫ '<span style="color:blue">RFALL</span>' STO
|
<span style="color:blue">READB</span> ''( → n )''
Initialize variables
Loop
if keystroke is an accepted char
add char to output and display it
until ENTER is pressed
clean stack and convert to integer
<span style="color:blue">RFALL</span> ''( → ) ''
initialize counters and flag, clear screen
loop
get rainfall
if break value then set flag
otherwise
accumulate rainfall and increment count
display average rainfall
until flag set
clean stack, unfreeze display
put average rainfall in stack if count ≠ 0
|}
 
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">QUIT = 99999
num = nil
count = 0
avg = 0.0
 
loop do
begin
print "Enter rainfall int, #{QUIT} to quit: "
input = gets
num = Integer(input)
rescue ArgumentError
puts "Invalid input #{input}"
redo
end
break if num == QUIT
count += 1
inv_count = 1.0/count
avg = avg + inv_count*num - inv_count*avg
end
 
puts "#{count} numbers entered, averaging #{average}"
</syntaxhighlight>
 
=={{header|Rust}}==
Line 864 ⟶ 1,243:
}
}
}
</syntaxhighlight>
=={{header|Swift}}==
<syntaxhighlight lang="swift">
import Foundation
 
var mean: Double = 0
var count: Int = 0
var prompt = "Enter integer rainfall or 99999 to exit:"
var term = " "
print(prompt, terminator: term)
while let input = readLine() {
defer {
print("count: \(count), mean: \(mean.formatted())\n\(prompt)", terminator: term)
}
guard let val = Int(input) else {
print("Integer values only")
continue
}
if val == 99999 {
(prompt, term) = ("Done","\n")
break
}
count += 1
mean += Double(val)/Double(count) - mean/Double(count)
}
</syntaxhighlight>
Line 869 ⟶ 1,273:
=={{header|Wren}}==
{{libheader|Wren-ioutil}}
<syntaxhighlight lang="ecmascriptwren">import "./ioutil" for Input
 
var n = 0
1,983

edits