Soloway's recurring rainfall: Difference between revisions

From Rosetta Code
Content added Content deleted
(J second draft -- display running average after each entry)
m (J third draft -- use return. instead of break.)
Line 321: Line 321:
while. do.
while. do.
y=. _.".prompt'Enter rainfall int, 99999 to quit: '
y=. _.".prompt'Enter rainfall int, 99999 to quit: '
if. 99999 e. y do. break. end.
if. 99999 e. y do. (+/%#)list return. end.
if. y-:y do. echo 'New average: ',":(+/%#)list=. list,y
if. y-:y do. echo 'New average: ',":(+/%#)list=. list,y
else. echo 'invalid input, reenter'
else. echo 'invalid input, reenter'
end.
end.
end.
end.
(+/%#)list
}}</syntaxhighlight>
}}</syntaxhighlight>



Revision as of 21:53, 10 September 2022

Task
Soloway's recurring rainfall
You are encouraged to solve this task according to the task description, using any language you may know.

Soloway's Recurring Rainfall is commonly used to asses general programming knowledge by requiring basic program structure, input/output, and program exit procedure.

The problem:

Write a program that will read in integers and output their average. Stop reading when the value 99999 is input.

References:


Ada

with Ada.Text_IO; 
with Ada.Text_IO.Unbounded_IO;
with Ada.Strings.Unbounded;
with Ada.Integer_Text_IO;
with Ada.IO_Exceptions;

procedure RecurringRainfall is
   Current_Average : Float := 0.0;
   Current_Count : Integer := 0;
   Input_Integer : Integer;
   
   -- Recursively attempt to get a new integer
   function Get_Next_Input return Integer is
      Input_Integer : Integer;
      Clear_String : Ada.Strings.Unbounded.Unbounded_String;
   begin
      Ada.Text_IO.Put("Enter rainfall int, 99999 to quit: ");
      Ada.Integer_Text_IO.Get(Input_Integer);
      return Input_Integer;
   exception
      when Ada.IO_Exceptions.Data_Error => 
         Ada.Text_IO.Put_Line("Invalid input");
         -- We need to call Get_Line to make sure we flush the kb buffer
         -- The pragma is to ignore the fact that we are not using the result
         pragma Warnings (Off, Clear_String);
         Clear_String := Ada.Text_IO.Unbounded_IO.Get_Line;
         -- Recursively call self -- it'll break when valid input is hit
         -- We disable the infinite recursion because we're intentionally
         -- doing this.  It will "break" when the user inputs valid input
         -- or kills the program
         pragma Warnings (Off, "infinite recursion");
         return Get_Next_Input;
         pragma Warnings (On, "infinite recursion");
   end Get_Next_Input;

begin
   loop
      Input_Integer := Get_Next_Input;
      exit when Input_Integer = 99999;
      
	  Current_Count := Current_Count + 1;
      Current_Average := Current_Average + (Float(1) / Float(Current_Count))*Float(Input_Integer) - (Float(1) / Float(Current_Count))*Current_Average;
      
      Ada.Text_IO.Put("New Average: ");
      Ada.Text_IO.Put_Line(Float'image(Current_Average));
      
   end loop;
end RecurringRainfall;

ALGOL 68

BEGIN # read a sequence of integers, terminated by 99999 and outpout their average #
    INT end value = 99999;
    INT sum      := 0;
    INT count    := 0;
    WHILE
        INT n := 0;
        WHILE
            STRING s;
            print( ( "Enter rainfall (integer) or ", whole( end value, 0 ), " to quit: " ) );
            read( ( s, newline ) );
            BOOL valid := UPB s >= LWB s; # invalid if the string is empty #
            FOR s pos FROM LWB s TO UPB s WHILE valid DO
                IF valid := s[ s pos ] >= "0" AND s[ s pos ] <= "9"
                THEN
                    n *:= 10 +:= ( ABS s[ s pos ] - ABS "0" )
                FI
            OD;
            NOT valid
        DO
            print( ( "Invalid input, please enter an integer", newline ) )
        OD;
        n /= end value
    DO
        sum   +:= n;
        count +:= 1;
        print( ( "New average: ", fixed( sum / count, -12, 4 ), newline ) )
    OD
END

C

#include <stdio.h>

int main(int argc, char **argv)
{
	// Unused variables
	(void)argc;
	(void)argv;
	
	float currentAverage = 0;
	unsigned int currentEntryNumber = 0;
	
	for (;;)
	{
		int ret, entry;
		
		printf("Enter rainfall int, 99999 to quit: ");
		ret = scanf("%d", &entry);
		
		if (ret)
		{
			if (entry == 99999)
			{
				printf("User requested quit.\n");
				break;
			}
			else
			{
				currentEntryNumber++;
				currentAverage = currentAverage + (1.0f/currentEntryNumber)*entry - (1.0f/currentEntryNumber)*currentAverage;
				
				printf("New Average: %f\n", currentAverage);
			}
		}
		else
		{
			printf("Invalid input\n");
			while (getchar() != '\n');	// Clear input buffer before asking again
		}
	}
	
	return 0;
}

C++

#include <iostream>
#include <limits>

int main()
{
	float currentAverage = 0;
	unsigned int currentEntryNumber = 0;
	
	for (;;)
	{
		int entry;
		
		std::cout << "Enter rainfall int, 99999 to quit: ";
		std::cin >> entry;
		
		if (!std::cin.fail())
		{
			if (entry == 99999)
			{
				std::cout << "User requested quit." << std::endl;
				break;
			}
			else
			{
				currentEntryNumber++;
				currentAverage = currentAverage + (1.0f/currentEntryNumber)*entry - (1.0f/currentEntryNumber)*currentAverage;
				
				std::cout << "New Average: " << currentAverage << std::endl;
			}
		}
		else
		{
			std::cout << "Invalid input" << std::endl;
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		}
	}
	
	return 0;
}

C#

namespace RosettaCode
{
	class CSharpRecurringRainfall
    {		
		static int ReadNextInput()
		{
			System.Console.Write("Enter rainfall int, 99999 to quit: ");
			string input = System.Console.ReadLine();
			
			if (System.Int32.TryParse(input, out int num))
			{
				return num;
			}
			else
			{
				System.Console.WriteLine("Invalid input");
				return ReadNextInput();
			}
		}
		
        static void Main()
        {
			double currentAverage = 0;
			int currentEntryNumber = 0;
			
            for (int lastInput = ReadNextInput(); lastInput != 99999; lastInput = ReadNextInput())
            {
				currentEntryNumber++;
				currentAverage = currentAverage + (1.0/(float)currentEntryNumber)*lastInput - (1.0/(float)currentEntryNumber)*currentAverage;
				System.Console.WriteLine("New Average: " + currentAverage);
			}
        }
    }
}

D

import std.stdio;

void main()
{
	float currentAverage = 0;
	uint currentEntryNumber = 0;
	
	for (;;)
	{
		int entry;
				
		write("Enter rainfall int, 99999 to quit: ");
		
		try {
			readf("%d", entry);
			readln();
		}
		catch (Exception e) {
			writeln("Invalid input");
			readln();
			continue;
		}
		
		if (entry == 99999) {
			writeln("User requested quit.");
			break;
		} else {
			currentEntryNumber++;
			currentAverage = currentAverage + (1.0/currentEntryNumber)*entry - (1.0/currentEntryNumber)*currentAverage;
			
			writeln("New Average: ", currentAverage);
		}
	}
}

Fortran

Fortran 90

function getNextInput() result(Input)
    implicit none
    integer :: Input
    integer :: Reason
    Reason = 1
    
    do while (Reason > 0)
        print *, "Enter rainfall int, 99999 to quit: "
        read (*,*,IOSTAT=Reason) Input
        
        if (Reason > 0) then
            print *, "Invalid input"
        end if
    enddo
    
end function getNextInput

program recurringrainfall
    implicit none
    real        :: currentAverage
    integer     :: currentCount
    integer     :: lastInput
    integer     :: getNextInput
    
    currentAverage = 0
    currentCount = 0

    do
        lastInput = getNextInput()
        
        if (lastInput == 99999) exit
        
        currentCount = currentCount + 1
        currentAverage = currentAverage + (1/real(currentCount))*lastInput - (1/real(currentCount))*currentAverage
        
        print *, 'New Average: ', currentAverage
    enddo 

    
end program recurringrainfall

J

The specification for this task seems inadequate. So, we'll copy some features from other implementations of this task.

Specifically, we'll issue a prompt for every number requested, and reject lines which contain something that is not a number.

However, since we're supposedly collecting information about rainfall, and rainfall is not necessarily an integer, we'll allow arbitrary numbers here and trust the judgement of the person entering the numbers.

Implementation:

require'general/misc/prompt'

task=: {{
  list=. ''
  while. do.
    y=. _.".prompt'Enter rainfall int, 99999 to quit: '
    if. 99999 e. y do. (+/%#)list return. end.
    if. y-:y do. echo 'New average: ',":(+/%#)list=. list,y
    else. echo 'invalid input, reenter'
    end.
  end.
}}

Example use:

   task''
Enter rainfall int, 99999 to quit: 2
New average: 2
Enter rainfall int, 99999 to quit: 3
New average: 2.5
Enter rainfall int, 99999 to quit: 5
New average: 3.33333
Enter rainfall int, 99999 to quit: 7
New average: 4.25
Enter rainfall int, 99999 to quit: 11
New average: 5.6
Enter rainfall int, 99999 to quit: 99999
5.6

Java

class recurringrainfall
{ 
	private static int GetNextInt()
	{
		while (true)
		{
			System.out.print("Enter rainfall int, 99999 to quit: ");
			String input = System.console().readLine();
        
			try
			{
				int n = Integer.parseInt(input);
				return n;
			}
			catch (Exception e)
			{
				System.out.println("Invalid input");
			}
		}
	}
	
    private static void recurringRainfall() {
		float currentAverage = 0;
		int currentEntryNumber = 0;
		
		while (true) {
			int entry = GetNextInt();
			
			if (entry == 99999)
				return;
			
			currentEntryNumber++;
			currentAverage = currentAverage + ((float)1/currentEntryNumber)*entry - ((float)1/currentEntryNumber)*currentAverage;
			
			System.out.println("New Average: " + currentAverage);
		}
    }
    
    public static void main(String args[]) { 
        recurringRainfall();
    } 
}

Python

import sys

def get_next_input():
    try:
        num = int(input("Enter rainfall int, 99999 to quit: "))
    except:
        print("Invalid input")
        return get_next_input()
    return num

current_average = 0.0
current_count = 0

while True:
    next = get_next_input()

    if next == 99999:
        sys.exit()
    else:
        current_count += 1
        current_average = current_average + (1.0/current_count)*next - (1.0/current_count)*current_average
        
        print("New average: ", current_average)

Rust

fn main() {
	
	let mut current_average:f32 = 0.0;
	let mut current_entry_number:u32 = 0;
	
	loop
	{
		let current_entry;

		println!("Enter rainfall int, 99999 to quit: "); 
		let mut input_text = String::new();
		std::io::stdin().read_line(&mut input_text).expect("Failed to read from stdin");
		let trimmed = input_text.trim();
		match trimmed.parse::<u32>() {
			Ok(new_entry) => current_entry = new_entry,
			Err(..) => { println!("Invalid input"); continue; }
		};

		if current_entry == 99999
		{
			println!("User requested quit.");
			break;
		}
		else
		{
			current_entry_number = current_entry_number + 1;
			current_average = current_average + (1.0 / current_entry_number as f32)*(current_entry as f32) - (1.0 / current_entry_number as f32)*current_average;

			println!("New Average: {}", current_average);
		}
	}
}

Wren

Library: Wren-ioutil
import "./ioutil" for Input

var n = 0
var sum = 0
while (true) {
    var i = Input.integer("Enter integral rainfall (99999 to quit): ", 0)
    if (i == 99999) break
    n = n + 1
    sum = sum + i
    System.print("  The current average rainfall is %(sum/n)")
}
Output:

Sample session:

Enter integral rainfall (99999 to quit): 5.4
Must be an integer no less than 0, try again.
Enter integral rainfall (99999 to quit): -2 
Must be an integer no less than 0, try again.
Enter integral rainfall (99999 to quit): 5
  The current average rainfall is 5
Enter integral rainfall (99999 to quit): 2
  The current average rainfall is 3.5
Enter integral rainfall (99999 to quit): 10
  The current average rainfall is 5.6666666666667
Enter integral rainfall (99999 to quit): 99999