/* Import the Java I/O package */ import java.io.*; import AppletConsoleApp; /** * Solution to the 1999 British Informatics Olympiad exam * question 1: Digital Rivers * * This application that can be run either from the console * as a stand-alone application or from an in-applet * console created with the AppletConsole applet. * * Solution copyright (c) 1999 The British Informatics Olympiad (BIO). * * This program may be freely copied by persons or organisations * involved in the British Informatics Olympiad or the International * Olympiad in Informatics, on condition that no changes are made and * this notice is not altered. Distribution for profit is forbidden * unless permission is first obtained in writing from the BIO. * * This program is for educational purposes only and comes with no * warranty, implied or otherwise, as to its fitness for any purpose. * * Author: Antony Rix * Internet: http://www.christs.cam.ac.uk/bio/ * E-mail: a.rix@lineone.net * S-mail: The British Informatics Olympiad * Christ's College * Cambridge CB2 3BU * United Kingdom * * @author Antony Rix * @version 0.1 * @see AppletConsoleApp * @see AppletConsole */ class BIO99R1Q1App extends AppletConsoleApp { /** * Start the application from the command line. */ public static void main(String[] args) { BIO99R1Q1App thisApp = new BIO99R1Q1App(); thisApp.redirectStreams(System.in, System.out); thisApp.run(); } /** * Start value */ int n; /** * The implementation of this application. */ public void run() { out.println( "Enter a number from 1 to 16384 for\npart 1(a), or 0 to run part 1(b)." ); out.print( ">" ); try { /* Create a StreamTokenizer to allow us to read in the start numbers */ StreamTokenizer sin = new StreamTokenizer( in ); sin.nextToken(); n = (int)sin.nval; if( n > 0 ) part1a(); else part1b(); } catch (IOException e) { out.println("I/O failure"); }; out.println( "Program finished." ); } /** * Given a starting value n, calculate the next element in the river. */ public int next_river( int n ) { int s = n; while( s > 0 ) { n = n + (s % 10); s = s / 10; } return n; } /** * Solution to part 1(a). * Given a start number, find the lowest number at which this river meets * one of rivers 1, 3 or 9. We do this by following rivers 1, 3 and 9 * and river n until one of them meets. */ public void part1a() { /* river1, river3 and river9 will be used to hold the current value in river 1, river 3 and river 9 as we follow them along. */ int river1 = 1; int river3 = 3; int river9 = 9; /* If we have not found a match, move along rivers 1, 3 and 9 until we meet or pass n. If we still haven't got a meeting, move one step along river n. */ while( (n != river1) && (n != river3) && (n != river9) ) { while( river1 < n ) river1 = next_river( river1 ); while( river3 < n ) river3 = next_river( river3 ); while( river9 < n ) river9 = next_river( river9 ); if( (n != river1) && (n != river3) && (n != river9) ) n = next_river( n ); } /* Show the solution */ if( river1 == n ) out.println( "First meets river 1 at " + n ); if( river3 == n ) out.println( "First meets river 3 at " + n ); if( river9 == n ) out.println( "First meets river 9 at " + n ); } /** * Find the lowest number that is in exactly 100 rivers. We do this * by following rivers 1 to 500 and storing an array with the times * each number has been met. */ public void part1b() { int start; /* Current starting river */ int current; /* Position in river start */ int[] hits = new int[500]; /* Number of times we've met each value */ /* Initialise number of hits to zero */ for( current = 1; current < 500; current++ ) hits[current] = 0; /* Follow rivers 1 to 500 */ for( start = 1; start < 500; start++ ) { current = start; while( current < 500 ) { hits[current]++; current = next_river( current ); } } /* Find the first time we meet a number 100 times */ for( current = 1; current < 500; current++ ) if( hits[current] == 100 ) { out.println( "First number in 100 rivers is " + current ); break; } } }