Guess the number/With feedback (player)
You are encouraged to solve this task according to the task description, using any language you may know.
The task is to write a player for the game that follows the following rules:
- The scorer will choose a number between set limits. The computer player will print a guess of the target number. The computer asks for a score of whether its guess is higher than, lower than, or equal to the target. The computer guesses, and the scorer scores, in turn, until the computer correctly guesses the target number.
The computer should guess intelligently based on the accumulated scores given. One way is to use a Binary search based algorithm.
Cf. Guess the number/With Feedback, Bulls and cows/Player
Contents |
[edit] Ada
with Ada.Text_IO;
procedure Guess_Number_Player is
procedure Guess_Number (Lower_Limit : Integer; Upper_Limit : Integer) is
type Feedback is (Lower, Higher, Correct);
package Feedback_IO is new Ada.Text_IO.Enumeration_IO (Feedback);
My_Guess : Integer := Lower_Limit + (Upper_Limit - Lower_Limit) / 2;
Your_Feedback : Feedback;
begin
Ada.Text_IO.Put_Line ("Think of a number!");
loop
Ada.Text_IO.Put_Line ("My guess: " & Integer'Image (My_Guess));
Ada.Text_IO.Put ("Your answer (lower, higher, correct): ");
Feedback_IO.Get (Your_Feedback);
exit when Your_Feedback = Correct;
if Your_Feedback = Lower then
My_Guess := Lower_Limit + (My_Guess - Lower_Limit) / 2;
else
My_Guess := My_Guess + (Upper_Limit - My_Guess) / 2;
end if;
end loop;
Ada.Text_IO.Put_Line ("I guessed well!");
end Guess_Number;
package Int_IO is new Ada.Text_IO.Integer_IO (Integer);
Lower_Limit : Integer;
Upper_Limit : Integer;
begin
loop
Ada.Text_IO.Put ("Lower Limit: ");
Int_IO.Get (Lower_Limit);
Ada.Text_IO.Put ("Upper Limit: ");
Int_IO.Get (Upper_Limit);
exit when Lower_Limit < Upper_Limit;
Ada.Text_IO.Put_Line ("Lower limit must be lower!");
end loop;
Guess_Number (Lower_Limit, Upper_Limit);
end Guess_Number_Player;
[edit] AutoHotkey
Works with the AutoHotkey entry at: http://rosettacode.org/wiki/Guess_the_number/With_feedback
MaxGuesses = 50
GetParams(LowerBound,UpperBound)
If Not GuessNum(LowerBound,UpperBound,MaxGuesses)
MsgBox, 16, Error, Could not guess number within %MaxGuesses% guesses.
GetParams(ByRef LowerBound,ByRef UpperBound)
{
WinWait, Number Guessing ahk_class #32770
Sleep, 100
WinGet, InputID, ID
ControlGetText, Temp1, Static1, ahk_id %InputID%
Temp2 := InStr(Temp1,A_Space,False,32)
LowerBound := SubStr(Temp1,31,Temp2 - 31)
UpperBound := SubStr(Temp1,Temp2 + 5,-1)
}
GuessNum(LowerBound,UpperBound,MaxGuesses)
{
Loop, %MaxGuesses%
{
Guess := LowerBound + ((UpperBound - LowerBound) // 2)
Temp1 := SendGuess(Guess)
ToolTip % Temp1
If Temp1 = Too Low
LowerBound = %Guess%
Else If Temp1 = Too High
UpperBound = %Guess%
Else
Return, 1
}
}
SendGuess(Guess)
{
WinGet, InputID, ID, Number Guessing ahk_class #32770
ControlSetText, Edit1, %Guess%, ahk_id %InputID%
ControlSend, Button1, {Enter}, ahk_id %InputID%
Loop
{
Sleep, 50
IfWinExist, Correct ahk_class #32770
Return
Else IfWinExist, Incorrect ahk_class #32770
Break
}
ControlGetText, Temp1, Static2
WinClose
WinWaitClose
IfInString, Temp1, low
Return, "Too Low"
Else
Return, "Too High"
}
[edit] C
#include <stdio.h>
int main(){
int bounds[ 2 ] = {1, 100};
char input[ 2 ] = " ";
/* second char is for the newline from hitting [return] */
int choice = (bounds[ 0 ] + bounds[ 1 ]) / 2;
/* using a binary search */
printf( "Choose a number between %d and %d.\n", bounds[ 0 ], bounds[ 1 ] );
do{
switch( input[ 0 ] ){
case 'H':
bounds[ 1 ] = choice;
break;
case 'L':
bounds[ 0 ] = choice;
break;
case 'Y':
printf( "\nAwwwright\n" );
return 0;
}
choice = (bounds[ 0 ] + bounds[ 1 ]) / 2;
printf( "Is the number %d? (Y/H/L) ", choice );
}while( scanf( "%1s", input ) == 1 );
return 0;
}
Demonstration (number is 57):
Choose a number between 1 and 100. Is the number 50? (Y/H/L) L Is the number 75? (Y/H/L) H Is the number 62? (Y/H/L) H Is the number 56? (Y/H/L) L Is the number 59? (Y/H/L) H Is the number 57? (Y/H/L) Y Awwwright
[edit] C++
A clever solution that takes advantage of C++'s built-in binary search function lower_bound(). Instead of searching a slice of a container, we search a range of numbers by implementing a specially-designed custom iterator.
#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>
struct GuessNumberIterator : std::iterator<std::random_access_iterator_tag, int> {
int i;
GuessNumberIterator() { }
GuessNumberIterator(int _i) : i(_i) { }
GuessNumberIterator& operator++() { ++i; return *this; }
GuessNumberIterator operator++(int) {
GuessNumberIterator tmp = *this; ++(*this); return tmp; }
bool operator==(const GuessNumberIterator& y) { return i == y.i; }
bool operator!=(const GuessNumberIterator& y) { return i != y.i; }
int operator*() {
std::cout << "Is your number less than or equal to " << i << "? ";
std::string s;
std::cin >> s;
return (s != "" && (s[0] == 'y' || s[0] == 'Y')) ? 0 : -1;
}
GuessNumberIterator& operator--() { --i; return *this; }
GuessNumberIterator operator--(int) {
GuessNumberIterator tmp = *this; --(*this); return tmp; }
GuessNumberIterator& operator+=(int n) { i += n; return *this; }
GuessNumberIterator& operator-=(int n) { i -= n; return *this; }
GuessNumberIterator operator+(int n) {
GuessNumberIterator tmp = *this; return tmp += n; }
GuessNumberIterator operator-(int n) {
GuessNumberIterator tmp = *this; return tmp -= n; }
int operator-(const GuessNumberIterator &y) { return i - y.i; }
int operator[](int n) { return *(*this + n); }
bool operator<(const GuessNumberIterator &y) { return i < y.i; }
bool operator>(const GuessNumberIterator &y) { return i > y.i; }
bool operator<=(const GuessNumberIterator &y) { return i <= y.i; }
bool operator>=(const GuessNumberIterator &y) { return i >= y.i; }
};
inline GuessNumberIterator operator+(int n, GuessNumberIterator &i) { return i + n; }
const int lower = 0;
const int upper = 100;
int main() {
std::cout << "Instructions:\n"
<< "Think of integer number from " << lower << " (inclusive) to "
<< upper << " (exclusive) and\n"
<< "I will guess it. After each guess, I will ask you if it is less than\n"
<< "or equal to some number, and you will respond with \"yes\" or \"no\".\n";
int answer = std::lower_bound(GuessNumberIterator(lower), GuessNumberIterator(upper), 0).i;
std::cout << "Your number is " << answer << ".\n";
return 0;
}
[edit] C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //Remember to add this if you want the game to pause in RealisticGuess.Start()
namespace ConsoleApplication1
{
class RealisticGuess //Simulates a guessing game between two people. Guessing efficiency is not a goal.
{
private int max;
private int min;
private int guess;
public void Start()
{
Console.Clear();
string input;
try
{
Console.WriteLine("Please enter the lower boundary");
input = Console.ReadLine();
min = Convert.ToInt32(input);
Console.WriteLine("Please enter the upper boundary");
input = Console.ReadLine();
max = Convert.ToInt32(input);
}
catch (FormatException)
{
Console.WriteLine("The entry you have made is invalid. Please make sure your entry is an integer and try again.");
Console.ReadKey(true);
Start();
}
Console.WriteLine("Think of a number between {0} and {1}.", min, max);
Thread.Sleep(2500);
Console.WriteLine("Ready?");
Console.WriteLine("Press any key to begin.");
Console.ReadKey(true);
Guess(min, max);
}
public void Guess(int min, int max)
{
int counter = 1;
string userAnswer;
bool correct = false;
Random rand = new Random();
while (correct == false)
{
guess = rand.Next(min, max);
Console.Clear();
Console.WriteLine("{0}", guess);
Console.WriteLine("Is this number correct? {Y/N}");
userAnswer = Console.ReadLine();
if (userAnswer != "y" && userAnswer != "Y" && userAnswer != "n" && userAnswer != "N")
{
Console.WriteLine("Your entry is invalid. Please enter either 'Y' or 'N'");
Console.WriteLine("Is the number correct? {Y/N}");
userAnswer = Console.ReadLine();
}
if (userAnswer == "y" || userAnswer == "Y")
{
correct = true;
}
if (userAnswer == "n" || userAnswer == "N")
{
counter++;
if (max == min)
{
Console.WriteLine("Error: Range Intersect. Press enter to restart the game."); //This message should never pop up if the user enters good data.
Console.ReadKey(true); //It handles the game-breaking exception that occurs
Guess(1, 101); //when the max guess number is the same as the min number.
}
Console.WriteLine("Is the number you're thinking of lower or higher? {L/H}");
userAnswer = Console.ReadLine();
if (userAnswer != "l" && userAnswer != "L" && userAnswer != "h" && userAnswer != "H")
{
Console.WriteLine("Your entry is invalid. Please enter either 'L' or 'H'");
Console.WriteLine("Is the number you're thinking of lower or higher? {L/H}");
userAnswer = Console.ReadLine();
}
if (userAnswer == "l" || userAnswer == "L")
{
max = guess;
}
if (userAnswer == "h" || userAnswer == "H")
{
min = guess;
}
}
}
if (correct == true)
{
EndAndLoop(counter);
}
}
public void EndAndLoop(int iterations)
{
string userChoice;
bool loop = false;
Console.WriteLine("Game over. It took {0} guesses to find the number.", iterations);
while (loop == false)
{
Console.WriteLine("Would you like to play again? {Y/N}");
userChoice = Console.ReadLine();
if (userChoice != "Y" && userChoice != "y" && userChoice != "N" && userChoice != "n")
{
Console.WriteLine("Sorry, your input is invalid. Please answer 'Y' to play again, or 'N' to quit.");
}
if (userChoice == "Y" || userChoice == "y")
{
Start();
}
if (userChoice == "N" || userChoice == "n")
{
Environment.Exit(1);
}
}
}
}
class Program
{
static void Main(string[] args)
{
Console.Title = "Random Number";
RealisticGuess game = new RealisticGuess();
game.Start();
}
}
}
[edit] Clojure
(require '[clojure.string :as str])
(defn guess-game [low high]
(printf "Think of a number between %s and %s.\n (use (h)igh (l)ow (c)orrect)\n" low high)
(loop [guess (/ (inc (- high low)) 2)
[step & more] (next (iterate #(/ % 2) guess))]
(printf "I guess %s\n=> " (Math/round (float guess)))
(flush)
(case (first (str/lower-case (read)))
\h (recur (- guess step) more)
\l (recur (+ guess step) more)
\c (println "Huzzah!")
(do (println "Invalid input.")
(recur guess step)))))
Output
user=> (guess-game 1 100) Think of a number between 1 and 100. (use (h)igh (l)ow (c)orrect) I guess 50 => l I guess 63 => h I guess 56 => l I guess 59 => l I guess 61 => c Huzzah!
[edit] Euphoria
include get.e
include wildcard.e
sequence Respons
integer min, max, Guess
min = 0
max = 100
printf(1,"Think of a number between %d and %d.\n",{min,max})
puts(1,"On every guess of mine you should state whether my guess was\n")
puts(1,"too high, too low, or equal to your number by typing 'h', 'l', or '='\n")
while 1 do
if max < min then
puts(1,"I think something is strange here...\n")
exit
end if
Guess = floor((max-min)/2+min)
printf(1,"My guess is %d, is this correct? ", Guess)
Respons = upper(prompt_string(""))
if Respons[1] = 'H' then
max = Guess-1
elsif Respons[1] = 'L' then
min = Guess+1
elsif Respons[1] = '=' then
puts(1,"I did it!\n")
exit
else
puts(1,"I do not understand that...\n")
end if
end while
[edit] Fantom
class Main
{
public static Void main ()
{
Int lowerLimit := 1
Int higherLimit := 100
echo ("Think of a number between 1 and 100")
echo ("Press 'enter' when ready")
Env.cur.in.readLine
while (true)
{
if (higherLimit < lowerLimit)
{ // check that player is not cheating!
echo ("Something has gone wrong ... I give up")
break
}
myGuess := (higherLimit + lowerLimit) / 2
echo ("My guess is $myGuess")
echo ("Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal")
switch (Env.cur.in.readLine.trim.upper)
{
case "E":
echo ("I got it correct - thankyou!")
break // game over
case "H":
lowerLimit = myGuess + 1
case "L":
higherLimit = myGuess - 1
default:
echo ("Pardon? Let's try that again")
}
}
}
}
Example:
Think of a number between 1 and 100 Press 'enter' when ready My guess is 50 Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal a Pardon? Let's try that again My guess is 50 Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal l My guess is 25 Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal h My guess is 37 Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal h My guess is 43 Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal h My guess is 46 Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal h My guess is 48 Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal l My guess is 47 Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal e I got it correct - thankyou!
[edit] Fortran
program Guess_a_number_Player
implicit none
integer, parameter :: limit = 100
integer :: guess, mx = limit, mn = 1
real :: rnum
character(1) :: score
write(*, "(a, i0, a)") "Think of a number between 1 and ", limit, &
" and I will try to guess it."
write(*, "(a)") "You score my guess by entering: h if my guess is higher than that number"
write(*, "(a)") " l if my guess is lower than that number"
write(*, "(a/)") " c if my guess is the same as that number"
call random_seed
call random_number(rnum)
guess = rnum * limit + 1
do
write(*, "(a, i0, a,)", advance='no') "My quess is: ", guess, " Score(h, l or c)?: "
read*, score
select case(score)
case("l", "L")
mn = guess
guess = (mx-guess+1) / 2 + mn
case("h", "H")
mx = guess
guess = mx - (guess-mn+1) / 2
case("c", "C")
write(*, "(a)") "I solved it!"
exit
case default
write(*, "(a)") "I did not understand that"
end select
end do
end program
Output
Think of a number between 1 and 100 and I will try to guess it.
You score my guess by entering: h if my guess is higher than that number
l if my guess is lower than that number
c if my guess is the same as that number
My guess is: 58 Score(h, l or c)?: h
My guess is: 29 Score(h, l or c)?: l
My guess is: 44 Score(h, l or c)?: l
My guess is: 51 Score(h, l or c)?: l
My guess is: 55 Score(h, l or c)?: l
My guess is: 57 Score(h, l or c)?: c
I solved it!
[edit] Go
Go's binary search function (sort.Search()) is general enough to be able to do this type of task, as mentioned in the documentation for the function itself.[1]
package main
import (
"fmt"
"sort"
)
func main() {
lower, upper := 0, 100
fmt.Printf(`Instructions:
Think of integer number from %d (inclusive) to %d (exclusive) and
I will guess it. After each guess, I will ask you if it is less than
or equal to some number, and you will respond with "yes" or "no".
`, lower, upper)
answer := sort.Search(upper-lower, func (i int) bool {
fmt.Printf("Is your number less than or equal to %d? ", lower+i)
s := ""
fmt.Scanf("%s", &s)
return s != "" && s[0] == 'y'
})
fmt.Printf("Your number is %d.\n", lower+answer)
}
Manual solution:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
lower, upper := 1, 100
fmt.Printf(`Instructions:
Think of integer number from %d (inclusive) to %d (inclusive) and I will guess it.
After each guess, you respond with l,h,or c depending on
if my guess was too low, too high, or correct.
Press enter when you are thinking of a number. `, lower, upper)
in := bufio.NewReader(os.Stdin)
in.ReadString('\n')
for {
guess := (upper+lower)/2
fmt.Printf("My guess: %d (l/h/c) ", guess)
s, err := in.ReadString('\n')
if err != nil {
fmt.Println("\nSo, bye.")
return
}
switch s {
case "l\n":
lower = guess + 1
case "h\n":
upper = guess - 1
case "c\n":
fmt.Println("I did it. :)")
return
default:
fmt.Println("Please respond by pressing l, h, or c")
}
}
}
[edit] Icon and Unicon
procedure main ()
lower_limit := 1
higher_limit := 100
write ("Think of a number between 1 and 100")
write ("Press 'enter' when ready")
read ()
repeat {
if (higher_limit < lower_limit)
then { # check that player is not cheating!
write ("Something has gone wrong ... I give up")
exit ()
}
my_guess := (higher_limit + lower_limit) / 2
write ("My guess is ", my_guess)
write ("Enter 'H' if your number is higher, 'L' if lower, or 'E' if equal")
reply := map(trim(read ()))
case (reply) of {
"e" : {
write ("I got it correct - thankyou!")
exit () # game over
}
"h" : lower_limit := my_guess + 1
"l" : higher_limit := my_guess - 1
default : write ("Pardon? Let's try that again")
}
}
end
[edit] J
require 'misc'
guess=:3 :0
'lo hi'=.y
while.lo < hi do.
smoutput 'guessing a number between ',(":lo),' and ',":hi
guess=.lo+?hi-lo
select.{.deb tolower prompt 'is it ',(":guess),'? '
case.'y'do. smoutput 'Win!' return.
case.'l'do. lo=.guess+1
case.'h'do. hi=.guess-1
case.'q'do. smoutput 'giving up' return.
case. do. smouput 'options: yes, low, high, quit'
end.
end.
)
Example session:
guess 1 100
guessing a number between 1 and 100
is it 86? hi
guessing a number between 1 and 85
is it 56? hi
guessing a number between 1 and 55
is it 24? lo
guessing a number between 25 and 55
is it 29? lo
guessing a number between 30 and 55
is it 43? lo
guessing a number between 44 and 55
is it 53? hi
guessing a number between 44 and 52
is it 51? hi
guessing a number between 44 and 50
is it 48? lo
guessing a number between 49 and 50
is it 49? lo
50
This could be made more efficient by replacing guess=.lo+?hi-lo with guess=.<.-:lo+hi. (The above example would have finished on the first guess, but the range 1..100 would never take more than 6 guesses -- the remaining answers would be determined after six guesses.)
[edit] Java
A clever solution that uses the built-in binary search functions with a virtual list.
import java.util.AbstractList;
import java.util.Collections;
import java.util.Scanner;
public class GuessNumber {
public static final int LOWER = 0, UPPER = 100;
public static void main(String[] args) {
System.out.printf("Instructions:\n" +
"Think of integer number from %d (inclusive) to %d (exclusive) and\n" +
"I will guess it. After each guess, you respond with L, H, or C depending\n" +
"on if my guess was too low, too high, or correct.\n",
LOWER, UPPER);
int result = Collections.binarySearch(new AbstractList<Integer>() {
private final Scanner in = new Scanner(System.in);
public int size() { return UPPER - LOWER; }
public Integer get(int i) {
System.out.printf("My guess is: %d. Is it too high, too low, or correct? (H/L/C) ", LOWER+i);
String s = in.nextLine();
assert s.length() > 0;
switch (Character.toLowerCase(s.charAt(0))) {
case 'l':
return -1;
case 'h':
return 1;
case 'c':
return 0;
}
return -1;
}
}, 0);
if (result < 0)
System.out.println("That is impossible.");
else
System.out.printf("Your number is %d.\n", result);
}
}
[edit] Modula-2
MODULE raden;Example:
IMPORT InOut;
VAR done, ok : BOOLEAN;
guess, upp, low : CARDINAL;
res : CHAR;
BEGIN
InOut.WriteString ("Choose a number between 0 and 1000.");
InOut.WriteLn;
InOut.WriteLn;
upp := 1000;
low := 0;
REPEAT
ok := FALSE;
guess := ( ( upp - low ) DIV 2 ) + low;
InOut.WriteString ("My guess is"); InOut.WriteCard (guess, 4); InOut.Write (11C);
InOut.WriteString ("How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : ");
InOut.WriteBf;
REPEAT
InOut.Read (res);
res := CAP (res)
UNTIL (res = 'Q') OR (res = 'L') OR (res = 'H');
CASE res OF
'L' : low := guess |
'H' : upp := guess
ELSE
ok := TRUE
END;
UNTIL ok;
InOut.WriteString ("So the number is"); InOut.WriteCard (guess, 4);
InOut.WriteLn;
InOut.WriteString ("Thanks for letting me play with you.");
InOut.WriteLn
END raden.
radenChoose a number between 0 and 1000.
My guess is 500 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : l My guess is 750 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : h My guess is 625 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : h My guess is 562 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : l My guess is 593 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : l My guess is 609 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : h My guess is 601 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : h My guess is 597 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : l My guess is 599 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : l My guess is 600 How did I score? 'L' = too low, 'H' = too high, 'Q' = OK : q So the number is 600
Thanks for letting me play with you.
[edit] Objective-C
A clever solution that uses the built-in binary search functions with a virtual list.
#import <Foundation/Foundation.h>
@interface GuessNumberFakeArray : NSArray
@end
@implementation GuessNumberFakeArray
- (NSUInteger)count { return NSUIntegerMax; }
- (id)objectAtIndex:(NSUInteger)i {
printf("My guess is: %lu. Is it too high, too low, or correct? (H/L/C) ", i);
char input[2] = " ";
scanf("%1s", input);
switch (tolower(input[0])) {
case 'l':
return [NSNumber numberWithInt:-1];
case 'h':
return [NSNumber numberWithInt:1];
case 'c':
return [NSNumber numberWithInt:0];
}
return nil;
}
@end
#define LOWER 0
#define UPPER 100
int main(int argc, const char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
printf("Instructions:\n"
"Think of integer number from %d (inclusive) to %d (exclusive) and\n"
"I will guess it. After each guess, you respond with L, H, or C depending\n"
"on if my guess was too low, too high, or correct.\n",
LOWER, UPPER);
GuessNumberFakeArray *fakeArray = [GuessNumberFakeArray new];
NSUInteger result = [fakeArray indexOfObject:[NSNumber numberWithInt: 0]
inSortedRange:NSMakeRange(LOWER, UPPER)
options:0
usingComparator:^(id x, id y){ return [x compare: y]; }];
[fakeArray release];
NSLog(@"Your number is %lu.", result);
[pool release];
return 0;
}
[edit] PARI/GP
guessnumber2(b)={
my(c=0,d=b,a=0);
for(x=1,b,
for(y=1,b,
if(a<c||a==c||a==d||a>d,
a=random(b),
break()
)
);
print("I guess "a" am I h,l,or e ?");
g=input();
if(g==h,
d=a,
if(g==l,
c=a,
if(g==e,
break()
)
)
)
);
}
[edit] Pascal
Program GuessIt(input, output);
var
done, ok: boolean;
guess, upp, low: integer;
res: char;
begin
writeln ('Choose a number between 0 and 1000.');
write ('Press Enter and I will start to guess the number.');
readln;
upp := 1000;
low := 0;
repeat
ok := false;
guess := ( ( upp - low ) div 2 ) + low;
write ('My guess is: ', guess:4);
write ('. How did i score? ''l'' = too low, ''h'' = too high, ''c'' = correct : ');
repeat
readln (res);
res := lowercase(res);
until (res = 'c') or (res = 'l') or (res = 'h');
case res of
'l': low := guess;
'h': upp := guess;
else
ok := true
end;
until ok;
writeln ('So the number is: ', guess:4);
writeln ('It was nice to play with you.');
end.
Output:
:> ./GuessTheNumberPlayerFeedback Choose a number between 0 and 1000. Press Enter and I will start to guess the number. My guess is: 500. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : h My guess is: 250. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : h My guess is: 125. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : l My guess is: 187. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : h My guess is: 156. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : h My guess is: 140. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : h My guess is: 132. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : l My guess is: 136. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : l My guess is: 138. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : h My guess is: 137. How did i score? 'l' = too low, 'h' = too high, 'c' = correct : c So the number is: 137 It was nice to play with you.
[edit] Perl
#!/usr/bin/perl
my $min = 1;
my $max = 99;
print "=>> Think of a number between $min and $max and I'll guess it!\n
Press <ENTER> when are you ready... ";
<STDIN>;
my $guess = int(rand $max) + $min;
my $tries = 0;
sub question {
my $guess = shift();
print "\n=>> My guess is: $guess. Is your number higher, lower or equal? (h/l/e)\n> ";
++$tries;
}
question $guess;
while (1) {
my $score = <STDIN>;
if (lc substr($score, 0, 1) eq 'h') {
$min = $guess + 1;
}
elsif (lc substr($score, 0, 1) eq 'l') {
$max = $guess;
}
elsif (lc substr($score, 0, 1) eq 'e') {
print "\nI knew it! It took me only $tries tries.\n";
last;
}
else {
print "error: invalid score\n";
}
print "\nI gave up...\n" and last if $max <= $min;
$guess = int(($max + $min) / 2);
question $guess;
}
=>> Think of a number between 1 and 99 and I'll guess it! Press <ENTER> when are you ready... =>> My guess is: 88. Is your number higher, lower or equal? (h/l/e) > l =>> My guess is: 44. Is your number higher, lower or equal? (h/l/e) > l =>> My guess is: 22. Is your number higher, lower or equal? (h/l/e) > h =>> My guess is: 33. Is your number higher, lower or equal? (h/l/e) > l =>> My guess is: 28. Is your number higher, lower or equal? (h/l/e) > e I knew it! It took me only 5 tries.
[edit] Perl 6
multi sub MAIN() { MAIN(0, 100) }
multi sub MAIN($min is copy where ($min >= 0), $max is copy where ($max > $min)) {
say "Think of a number between $min and $max and I'll guess it!";
while $min <= $max {
my $guess = (($max + $min)/2).floor;
given lc prompt "My guess is $guess. Is your number higher, lower or equal? " {
when /^e/ { say "I knew it!"; exit }
when /^h/ { $min = $guess + 1 }
when /^l/ { $max = $guess }
default { say "WHAT!?!?!" }
}
}
say "How can your number be both higher and lower than $max?!?!?";
}
You may execute this program with 'perl6 program' or with 'perl6 program min max'. PerlĀ 6 creates a usage for us if we don't give the right parameters. It also parses the parameters for us and provides them via $min and $max. We use multi-subs to provide two MAIN subroutines so the user is able to choose between min and max parameters and no parameters at all, in which case min is set to 0 and max to 100.
[edit] PicoLisp
(de guessTheNumber (Min Max)
(prinl "Think of a number between " Min " and " Max ".")
(prinl "On every guess of mine you should state whether my guess was")
(prinl "too high, too low, or equal to your number by typing 'h', 'l', Or '='")
(use Guess
(loop
(NIL (> Max Min)
(prinl "I think somthing is strange here...") )
(prin
"My guess is "
(setq Guess (+ Min (/ (- Max Min) 2)))
",is this correct? " )
(flush)
(NIL
(case (uppc (car (line)))
("H" (setq Max Guess))
("L" (setq Min Guess))
("=" (nil (prinl "I did it!")))
(T (prinl "I do not understand that...")) ) ) ) ) )
Output:
: (guessTheNumber 1 99) Think of a number between 1 and 99. On every guess of mine you should state whether my guess was too high, too low, or equal to your number by typing 'h', 'l', Or '=' My guess is 50,is this correct? h My guess is 25,is this correct? h My guess is 13,is this correct? l My guess is 19,is this correct? l My guess is 22,is this correct? = I did it!
[edit] PureBasic
min=0
max=100
If OpenConsole()
PrintN("Think of a number between "+Str(min)+" and "+Str(max)+".")
PrintN("On every guess of mine you should state whether my guess was")
PrintN("too high, too low, or equal to your number by typing 'h', 'l', Or '='")
Repeat
If max<=min
PrintN("I think somthing is strange here...")
Break
EndIf
Guess=(max-min)/2+min
Print("My guess is "+Str(Guess)+",is this correct? "): Respons.s=UCase(Input())
If Respons="H": max=Guess-1
ElseIf Respons="L": min=Guess+1
ElseIf Respons="="
PrintN("I did it!")
Break
Else
PrintN("I do not understand that...")
EndIf
ForEver
EndIf
[edit] Python
inclusive_range = mn, mx = (1, 10)
print('''\
Think of a number between %i and %i and wait for me to guess it.
On every guess of mine you should state whether the guess was
too high, too low, or equal to your number by typing h, l, or =
''' % inclusive_range)
i = 0
while True:
i += 1
guess = (mn+mx)//2
txt = input("Guess %2i is: %2i. The score for which is (h,l,=): "
% (i, guess)).strip().lower()[0]
if txt not in 'hl=':
print(" I don't understand your input of '%s' ?" % txt)
continue
if txt == 'h':
mx = guess-1
if txt == 'l':
mn = guess+1
if txt == '=':
print(" Ye-Haw!!")
break
if (mn > mx) or (mn < inclusive_range[0]) or (mx > inclusive_range[1]):
print("Please check your scoring as I cannot find the value")
break
print("\nThanks for keeping score.")
Sample Game-play
Think of a number between 1 and 10 and wait for me to guess it. On every guess of mine you should state whether the guess was too high, too low, or equal to your number by typing h, l, or = Guess 1 is: 5. The score for which is (h,l,=): l Guess 2 is: 8. The score for which is (h,l,=): l Guess 3 is: 9. The score for which is (h,l,=): l Guess 4 is: 10. The score for which is (h,l,=): = Ye-Haw!! Thanks for keeping score.
Hacky solution using a fake list class and the bisect module from the standard library to do the binary search.
import bisect
try: input = raw_input
except: pass
class GuessNumberFakeList(object):
def __getitem__(self, i):
s = input("Is your number less than or equal to %d?" % i)
return 0 if s.lower().startswith('y') else -1
LOWER, UPPER = 0, 100
if __name__ == "__main__":
print("""Instructions:
Think of integer number from %d (inclusive) to %d (exclusive) and
I will guess it. After each guess, I will ask you if it is less than
or equal to some number, and you will respond with "yes" or "no".
""" % (LOWER, UPPER))
result = bisect.bisect_left(GuessNumberFakeList(), 0, LOWER, UPPER)
print("Your number is %d." % result)
[edit] REXX
/*REXX program to play guess-the-number (with itself!). */
parse arg low high . /*let them choose the range.*/
if low=='' then low=1
if high=='' then high=1000
?=random(low,high)
say
info="Try to guess my number (it's between" low 'and',
high" inclusive)."
do j=1
say info
say
call guesser
select
when guess>? then info=right("It's too high.",40)
when guess<? then info=right("It's too low. ",40)
otherwise leave
end
end
say
say 'Congratulations! You guessed the secret number in' j "tries."
say
exit
guesser: upper info
if \datatype(newlow ,'N') then newlow =low
if \datatype(newhigh,'N') then newhigh=high
oldGuess=guess
if pos('HIGH',info)\==0 then newhigh=guess
if pos('LOW' ,info)\==0 then newlow =guess
guess=newlow+(newhigh-newlow)%2
if guess==oldguess then guess=guess+1
say 'My guess is' guess
return
Output shown is from playing several games:
Try to guess my number (it's between 1 and 1000 inclusive).
My guess is 500
It's too low.
My guess is 750
It's too low.
My guess is 875
It's too high.
My guess is 812
It's too low.
My guess is 843
It's too high.
My guess is 827
It's too high.
My guess is 819
It's too low.
My guess is 823
It's too low.
My guess is 825
Congratulations! You guessed the secret number in 9 tries.
_________________________________________________________________
Try to guess my number (it's between 1 and 1000 inclusive).
My guess is 500
It's too high.
My guess is 250
It's too high.
My guess is 125
It's too high.
My guess is 63
It's too high.
My guess is 32
It's too low.
My guess is 47
It's too low.
My guess is 55
It's too low.
My guess is 59
It's too high.
My guess is 57
It's too low.
My guess is 58
Congratulations! You guessed the secret number in 10 tries.
_________________________________________________________________
Try to guess my number (it's between 1 and 1000 inclusive).
My guess is 500
It's too high.
My guess is 250
It's too low.
My guess is 375
It's too high.
My guess is 312
It's too low.
My guess is 343
It's too low.
My guess is 359
It's too high.
My guess is 351
Congratulations! You guessed the secret number in 7 tries.
_________________________________________________________________
Try to guess my number (it's between 1 and 1000 inclusive).
My guess is 500
It's too low.
My guess is 750
It's too high.
My guess is 625
It's too low.
My guess is 687
It's too high.
My guess is 656
Congratulations! You guessed the secret number in 5 tries.
_________________________________________________________________
Try to guess my number (it's between 1 and 1000 inclusive).
My guess is 500
It's too high.
My guess is 250
It's too high.
My guess is 125
Congratulations! You guessed the secret number in 3 tries.
[edit] Ruby
Computer plays versus itself
def play(low, high, turns = 1)
num = low + (high - low) / 2
print "guessing #{num}\t"
case is_it?(num)
when 1
puts "too high"
play(low, num, turns + 1)
when -1
puts "too low"
play(num, high, turns + 1)
else
puts "found the number in #{turns} turns."
end
end
def is_it?(num)
num <=> $number
end
low = 1
high = 100
$number = low + rand(high-low)
puts "guess a number between #{low} and #{high}"
play(low, high)
Example
guess a number between 1 and 100 guessing 50 too high guessing 25 too low guessing 37 too high guessing 31 too high guessing 28 too low guessing 29 too low guessing 30 found the number in 7 turns.
[edit] Scheme
(define minimum 1)
(define maximum 100)
(display "Enter a number from ")(display minimum)
(display " to ")(display maximum)(display ": ")
(define number (read))
(define input "")
(do ((guess (round (/ (+ maximum minimum) 2)) (round (/ (+ maximum minimum) 2))))
((string= input "="))
(display "Is it ")(display guess)(display "?\n(h/l/=) > ")
(set! input (symbol->string (read)))
(if (string= input "h") (begin (display "OK...")
(set! maximum (- guess 1))))
(if (string= input "l") (begin (display "OK...")
(set! minimum (+ guess 1)))))
(display "I was RIGHT!\n")
[edit] Tcl
set from 1
set to 10
fconfigure stdout -buffering none
while 1 {
set guess [expr {($from+$to) / 2}]
puts -nonewline "Guess: $guess\tWas it lower (<) equal (=) or higher (>)? "
switch -- [gets stdin] {
< { set from [expr {$guess + 1}] }
> { set to [expr {$guess - 1}] }
= {
puts "Found it: $guess"
break
}
default {
puts "What sort of a response was that?!"
}
}
if {$to < $from} {
puts "No answer possible?!"
break
}
}
Sample run:
Guess: 5 Was it lower (<) equal (=) or higher (>)? < Guess: 8 Was it lower (<) equal (=) or higher (>)? > Guess: 6 Was it lower (<) equal (=) or higher (>)? = Found it: 6