Penney's game

From Rosetta Code
Task
Penney's game
You are encouraged to solve this task according to the task description, using any language you may know.

Penney's game is a game where two players bet on being the first to see a particular sequence of heads or tails in consecutive tosses of a fair coin.

It is common to agree on a sequence length of three then one player will openly choose a sequence, for example:

 Heads,  Tails,  Heads, or HTH for short.

The other player on seeing the first players choice will choose his sequence. The coin is tossed and the first player to see his sequence in the sequence of coin tosses wins.


Example

One player might choose the sequence HHT and the other THT.

Successive coin tosses of HTTHT gives the win to the second player as the last three coin tosses are his sequence.


Task

Create a program that tosses the coin, keeps score and plays Penney's game against a human opponent.

  • Who chooses and shows their sequence of three should be chosen randomly.
  • If going first, the computer should randomly choose its sequence of three.
  • If going second, the computer should automatically play the optimum sequence.
  • Successive coin tosses should be shown.


Show output of a game where the computer chooses first and a game where the user goes first here on this page.


See also



BASIC[edit]

Sinclair ZX81 BASIC[edit]

Works with 1k of RAM.

 10 IF RND>=.5 THEN GOTO 100
20 PRINT "YOU PICK FIRST."
30 INPUT P$
40 PRINT "YOU CHOSE ";P$
50 LET C$="H"
60 IF P$(2)="H" THEN LET C$="T"
70 LET C$=C$+P$( TO 2)
80 PRINT "I CHOOSE ";C$
90 GOTO 190
100 PRINT "I PICK FIRST."
110 LET C$=""
120 FOR I=1 TO 3
130 LET C$=C$+"H"
140 IF RND>=.5 THEN LET C$(I)="T"
150 NEXT I
160 PRINT "I CHOOSE ";C$
170 INPUT P$
180 PRINT "YOU CHOSE ";P$
190 LET G$=""
200 IF RND>=.5 THEN GOTO 230
210 LET G$=G$+"H"
220 GOTO 240
230 LET G$=G$+"T"
240 PRINT AT 5,0;G$
250 IF LEN G$<3 THEN GOTO 200
260 IF G$(LEN G$-2 TO )=P$ THEN GOTO 290
270 IF G$(LEN G$-2 TO )=C$ THEN GOTO 310
280 GOTO 200
290 PRINT "YOU WIN"
300 STOP
310 PRINT "I WIN"
Output:
YOU PICK FIRST.
YOU CHOSE HTH
I CHOOSE  HHT


HTTTHTTTTHHT
I WIN

Batch File[edit]

::
::Penney's Game Task from Rosetta Code Wiki
::Batch File Implementation
::
::Please Directly Open the Batch File to play...
::
 
@echo off
setlocal enabledelayedexpansion
title The Penney's Game Batch File
 
set cpu=0&set you=0
cls
echo.
echo Penney's Game
echo Batch File Implementation
 
:main
set you_bet=&set cpu_bet=
echo.&echo --------------------------------------------------------&echo.
echo CPU's Score: %cpu% Your Score: %you%
echo.
<nul set /p "dummy=Heads I start, Tails you start..."
set /a startrnd=%random%%%2
set firsttoss=Tails&set func=optimal
if %startrnd%==1 (set firsttoss=Heads&set func=rndbet)
ping -n 3 localhost >nul
<nul set /p "dummy=. %firsttoss%^!"
echo.&echo.
goto %func%
 
:rndbet
set /a "seq1=%random%%%2","seq2=%random%%%2","seq3=%random%%%2"
set binary=%seq1%%seq2%%seq3%
set cpu_bet=%binary:1=H%
set cpu_bet=%cpu_bet:0=T%
echo I will bet first. So, my bet sequence will be %cpu_bet%.
:again1
set /p "you_bet=What will be your bet sequence? "
call :validate again1
echo.&echo So, you're feeling lucky on %you_bet%. We'll see...
goto succesivetossing
 
:optimal
echo Ok. You will bet first.
:again2
set /p "you_bet=What will be your bet sequence? "
call :validate again2
set seq1=%you_bet:~0,1%&set seq2=%you_bet:~1,1%
set new_seq1=T
if /i %seq2%==T set new_seq1=H
set cpu_bet=%new_seq1%%seq1%%seq2%
echo.&echo Hmm... My bet will be %cpu_bet%. We'll see who's lucky...
 
:succesivetossing
set toses=&set cnt=0
echo.
<nul set /p "dummy=Tosses: "
:tossloop
call :tossgen
<nul set /p dummy=%toss%
ping -n 2 localhost >nul
set /a newline=%cnt%%%60
if %newline%==59 (
echo.
<nul set /p "dummy=. "
)
if "%toses:~-3,3%"=="%cpu_bet%" goto iwin
if "%toses:~-3,3%"=="%you_bet%" goto uwin
set /a cnt+=1&goto tossloop
 
:tossgen
set /a rand=%random%%%2
set toss=T
if %rand%==0 set toss=H
set toses=%toses%%toss%
goto :EOF
 
:iwin
set /a cpu+=1&set newgame=
echo.&echo.
echo I Win^^! Better Luck Next Time...
echo.
set /p "newgame=[Type Y if U Wanna Beat Me, or Else, Exit...] "
if /i "!newgame!"=="Y" goto :main
exit
 
:uwin
set /a you+=1&set newgame=
echo.&echo.
echo Argh, You Win^^! ...But One Time I'll Beat You.
echo.
set /p "newgame=[Type Y for Another Game, or Else, Exit...] "
if /i "!newgame!"=="Y" goto :main
exit
 
:validate
echo "!you_bet!"|findstr /r /c:"^\"[hHtT][hHtT][hHtT]\"$">nul || (
echo [Invalid Input...]&echo.&goto %1
)
if /i "!you_bet!"=="%cpu_bet%" (echo [Bet something different...]&echo.&goto %1)
for %%i in ("t=T" "h=H") do set "you_bet=!you_bet:%%~i!"
goto :EOF
Output:

Note: The outputs of tosses are 'delayed' just to make the game a little more dramatic.

Penney's Game
Batch File Implementation

--------------------------------------------------------

CPU's Score: 0 Your Score: 0

Heads I start, Tails you start....   Heads!

I will bet first. So, my bet sequence will be THH.
What will be your bet sequence? tTh

So, you're feeling lucky on TTH. We'll see...

Tosses:    HHTHTHH

I Win! Better Luck Next Time...

[Type Y if U Wanna Beat Me, or Else, Exit...] y

--------------------------------------------------------

CPU's Score: 1 Your Score: 0

Heads I start, Tails you start....   Tails!

Ok. You will bet first.
What will be your bet sequence? tHt

Hmm... My bet will be TTH. We'll see who's lucky...

Tosses:    HTTH

I Win! Better Luck Next Time...

[Type Y if U Wanna Beat Me, or Else, Exit...]

BBC BASIC[edit]

REM >penney
PRINT "*** Penney's Game ***"
REPEAT
PRINT ' "Heads you pick first, tails I pick first."
PRINT "And it is... ";
WAIT 100
ht% = RND(0 - TIME) AND 1
IF ht% THEN
PRINT "heads!"
PROC_player_chooses(player$)
computer$ = FN_optimal(player$)
PRINT "I choose "; computer$; "."
ELSE
PRINT "tails!"
computer$ = FN_random
PRINT "I choose "; computer$; "."
PROC_player_chooses(player$)
ENDIF
PRINT "Starting the game..." ' SPC 5;
sequence$ = ""
winner% = FALSE
REPEAT
WAIT 100
roll% = RND AND 1
IF roll% THEN
sequence$ += "H"
PRINT "H ";
ELSE
PRINT "T ";
sequence$ += "T"
ENDIF
IF RIGHT$(sequence$, 3) = computer$ THEN
PRINT ' "I won!"
winner% = TRUE
ELSE
IF RIGHT$(sequence$, 3) = player$ THEN
PRINT ' "Congratulations! You won."
winner% = TRUE
ENDIF
ENDIF
UNTIL winner%
REPEAT
valid% = FALSE
INPUT "Another game? (Y/N) " another$
IF INSTR("YN", another$) THEN valid% = TRUE
UNTIL valid%
UNTIL another$ = "N"
PRINT "Thank you for playing!"
END
:
DEF PROC_player_chooses(RETURN sequence$)
LOCAL choice$, valid%, i%
REPEAT
valid% = TRUE
PRINT "Enter a sequence of three choices, each of them either H or T:"
INPUT "> " sequence$
IF LEN sequence$ <> 3 THEN valid% = FALSE
IF valid% THEN
FOR i% = 1 TO 3
choice$ = MID$(sequence$, i%, 1)
IF choice$ <> "H" AND choice$ <> "T" THEN valid% = FALSE
NEXT
ENDIF
UNTIL valid%
ENDPROC
:
DEF FN_random
LOCAL sequence$, choice%, i%
sequence$ = ""
FOR i% = 1 TO 3
choice% = RND AND 1
IF choice% THEN sequence$ += "H" ELSE sequence$ += "T"
NEXT
= sequence$
:
DEF FN_optimal(sequence$)
IF MID$(sequence$, 2, 1) = "H" THEN
= "T" + LEFT$(sequence$, 2)
ELSE
= "H" + LEFT$(sequence$, 2)
ENDIF
Output:
*** Penney's Game ***

Heads you pick first, tails I pick first.
And it is... heads!
Enter a sequence of three choices, each of them either H or T:
> HTT
I choose HHT.
Starting the game...
     H  H  H  H  H  T  
I won!
Another game? (Y/N) Y

Heads you pick first, tails I pick first.
And it is... tails!
I choose HTH.
Enter a sequence of three choices, each of them either H or T:
> HHT
Starting the game...
     T  T  H  H  H  H  T  
Congratulations! You won.
Another game? (Y/N) N
Thank you for playing!

C[edit]

This solution stores the sequences in bit-packed integers. With minor adjustments, this can be extended to allow larger sequence lengths beyond the required 3. However, the ai's algorithm for the perfect choice would need to be altered. More robust methods of input could be chosen, as scanf is generally fairly unsafe. A safer alternative would be to use something like fgets, and parse the input string ourselves.

 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#define SEQLEN 3
 
int getseq(char *s)
{
int r = 0;
int i = 1 << (SEQLEN - 1);
 
while (*s && i) {
switch (*s++) {
case 'H':
case 'h':
r |= i;
break;
case 'T':
case 't':
/* 0 indicates tails, this is 0, so do nothing */
break;
default:
return -1;
}
i >>= 1;
}
 
return r;
}
 
void printseq(int seq)
{
int i;
for (i = SEQLEN - 1; i >= 0; --i)
printf("%c", seq & (1 << i) ? 'h' : 't');
}
 
int getuser(void)
{
int user;
char s[SEQLEN + 1];
 
printf("Enter your sequence of %d (h/t): ", SEQLEN);
while (1) {
/* This needs to be manually changed if SEQLEN is changed */
if (scanf("%3s", s) != 1) exit(1);
if ((user = getseq(s)) != -1) return user;
printf("Please enter only h/t characters: ");
}
}
 
int getai(int user)
{
int ai;
 
printf("Computers sequence of %d is: ", SEQLEN);
/* The ai's perfect choice will only be perfect for SEQLEN == 3 */
if (user == -1)
ai = rand() & (1 << SEQLEN) - 1;
else
ai = (user >> 1) | ((~user << 1) & (1 << SEQLEN - 1));
 
printseq(ai);
printf("\n");
return ai;
}
 
int rungame(int user, int ai)
{
/* Generate first SEQLEN flips. We only need to store the last SEQLEN
* tosses at any one time. */

int last3 = rand() & (1 << SEQLEN) - 1;
 
printf("Tossed sequence: ");
printseq(last3);
while (1) {
if (user == last3) {
printf("\nUser wins!\n");
return 1;
}
 
if (ai == last3) {
printf("\nAi wins!\n");
return 0;
}
 
last3 = ((last3 << 1) & (1 << SEQLEN) - 2) | (rand() & 1);
printf("%c", last3 & 1 ? 'h' : 't');
}
}
 
int main(void)
{
srand(time(NULL));
int playerwins = 0;
int totalgames = 0;
 
/* Just use ctrl-c for exit */
while (1) {
int user = -1;
int ai = -1;
 
printf("\n");
if (rand() & 1) {
ai = getai(user);
user = getuser();
}
else {
user = getuser();
ai = getai(user);
}
 
playerwins += rungame(user, ai);
totalgames++;
 
printf("You have won %d out of %d games\n", playerwins, totalgames);
printf("=================================\n");
}
 
return 0;
}
 
Output:
Enter your sequence of 3 (h/t): tth
Computers sequence of 3 is: htt
Tossed sequence: ttth
User wins!
You have won 1 out of 1 games
=================================

Enter your sequence of 3 (h/t): tth
Computers sequence of 3 is: htt
Tossed sequence: thhhthhhthhhtt
Ai wins!
You have won 1 out of 2 games
=================================

C++[edit]

 
#include <time.h>
#include <iostream>
#include <string>
 
using namespace std;
 
class penney
{
public:
penney()
{ pW = cW = 0; }
void gameLoop()
{
string a;
while( true )
{
playerChoice = computerChoice = "";
if( rand() % 2 )
{ computer(); player(); }
else
{ player(); computer(); }
 
play();
 
cout << "[Y] to play again "; cin >> a;
if( a[0] != 'Y' && a[0] != 'y' )
{
cout << "Computer won " << cW << " times." << endl << "Player won " << pW << " times.";
break;
}
cout << endl << endl;
}
}
private:
void computer()
{
if( playerChoice.length() == 0 )
{
for( int x = 0; x < 3; x++ )
computerChoice.append( ( rand() % 2 ) ? "H" : "T", 1 );
}
else
{
computerChoice.append( playerChoice[1] == 'T' ? "H" : "T", 1 );
computerChoice += playerChoice.substr( 0, 2 );
}
cout << "Computer's sequence of three is: " << computerChoice << endl;
}
void player()
{
cout << "Enter your sequence of three (H/T) "; cin >> playerChoice;
}
void play()
{
sequence = "";
while( true )
{
sequence.append( ( rand() % 2 ) ? "H" : "T", 1 );
if( sequence.find( playerChoice ) != sequence.npos )
{
showWinner( 1 );
break;
}
else if( sequence.find( computerChoice ) != sequence.npos )
{
showWinner( 0 );
break;
}
}
}
void showWinner( int i )
{
string s;
if( i ) { s = "Player wins!"; pW++; }
else { s = "Computer wins!"; cW++; }
cout << "Tossed sequence: " << sequence << endl << s << endl << endl;
}
string playerChoice, computerChoice, sequence;
int pW, cW;
};
int main( int argc, char* argv[] )
{
srand( static_cast<unsigned>( time( NULL ) ) );
penney game; game.gameLoop();
return 0;
}
 
Output:
Computer's sequence of three is: HHH
Enter your sequence of three (H/T) THH
Tossed sequence: TTHTTTTTTTTTTTHTHTTTHTTHTTHH
Player wins!

[Y] to play again y

Enter your sequence of three (H/T) HTH
Computer's sequence of three is: HHT
Tossed sequence: THHT
Computer wins!

[Y] to play again 

Clojure[edit]

(ns penney.core
(:gen-class))
 
(def heads \H)
(def tails \T)
 
(defn flip-coin []
(let [flip (rand-int 2)]
(if (= flip 0) heads tails)))
 
(defn turn [coin]
(if (= coin heads) tails heads))
 
(defn first-index [combo coll]
(some #(if (= (second %) combo) (first %)) coll))
 
(defn find-winner [h c]
(if (< h c)
(do (println "YOU WIN!\n") :human)
(do (println "COMPUTER WINS!\n") :computer)))
 
(defn flip-off [human comp]
(let [flips (repeatedly flip-coin)
idx-flips (map-indexed vector (partition 3 1 flips))
h (first-index (seq human) idx-flips)
c (first-index (seq comp) idx-flips)]
(println (format "Tosses: %s" (apply str (take (+ 3 (min h c)) flips))))
(find-winner h c)))
 
(defn valid? [combo]
(if (empty? combo) true (and (= 3 (count combo)) (every? #(or (= heads %) (= tails %)) combo))))
 
(defn ask-move []
(println "What sequence of 3 Heads/Tails do you choose?")
(let [input (clojure.string/upper-case (read-line))]
(if-not (valid? input) (recur) input)))
 
(defn optimize-against [combo]
(let [mid (nth combo 1)
comp (str (turn mid) (first combo) mid)]
(println (format "Computer chooses %s: " comp)) comp))
 
(defn initial-move [game]
(let [combo (apply str (repeatedly 3 flip-coin))]
(println "--------------")
(println (format "Current score | CPU: %s, You: %s" (:computer game) (:human game)))
(if (= (:first-player game) tails)
(do
(println "Computer goes first and chooses: " combo)
combo)
(println "YOU get to go first."))))
 
(defn play-game [game]
(let [c-move (initial-move game)
h-move (ask-move)]
(if-not (empty? h-move)
(let [winner (flip-off h-move (if (nil? c-move) (optimize-against h-move) c-move))]
(recur (assoc game winner (inc (winner game)) :first-player (flip-coin))))
(println "Thanks for playing!"))))
 
(defn -main [& args]
(println "Penney's Game.")
(play-game {:first-player (flip-coin)
 :human 0, :computer 0}))
Output:
Penney's Game.
--------------
Current score | CPU: 0, You: 0
Computer goes first and chooses:  THT
What sequence of 3 Heads/Tails do you choose?
tth
Tosses: TTH
YOU WIN!

--------------
Current score | CPU: 0, You: 1
YOU get to go first.
What sequence of 3 Heads/Tails do you choose?
tht
Computer chooses TTH: 
Tosses: HHHTTH
COMPUTER WINS!

--------------
Current score | CPU: 1, You: 1
YOU get to go first.
What sequence of 3 Heads/Tails do you choose?

Thanks for playing!

D[edit]

Translation of: Python
void main() {
import std.stdio, std.random, std.algorithm, std.string,
std.conv, std.range, core.thread;
 
immutable first = uniform(0, 2) == 0;
 
string you, me;
if (first) {
me = 3.iota.map!(_ => "HT"[uniform(0, $)]).text;
writefln("I choose first and will win on first seeing %s in the list of tosses", me);
while (you.length != 3 || you.any!(c => !c.among('H', 'T')) || you == me) {
"What sequence of three Heads/Tails will you win with: ".write;
you = readln.strip;
}
} else {
while (you.length != 3 || you.any!(c => !c.among('H', 'T'))) {
"After you: What sequence of three Heads/Tails will you win with: ".write;
you = readln.strip;
}
me = (you[1] == 'T' ? 'H' : 'T') ~ you[0 .. 2];
writefln("I win on first seeing %s in the list of tosses", me);
}
 
"Rolling:\n ".write;
string rolled;
while (true) {
rolled ~= "HT"[uniform(0, $)];
rolled.back.write;
if (rolled.endsWith(you))
return "\n You win!".writeln;
if (rolled.endsWith(me))
return "\n I win!".writeln;
Thread.sleep(1.seconds);
}
}

The output is the same as the Python entry.

Elixir[edit]

Translation of: Ruby
defmodule Penney do
@toss [:Heads, :Tails]
 
def game(score \\ {0,0})
def game({iwin, ywin}=score) do
IO.puts "Penney game score I : #{iwin}, You : #{ywin}"
[i, you] = @toss
coin = Enum.random(@toss)
IO.puts "#{i} I start, #{you} you start ..... #{coin}"
{myC, yC} = setup(coin)
seq = for _ <- 1..3, do: Enum.random(@toss)
IO.write Enum.join(seq, " ")
{winner, score} = loop(seq, myC, yC, score)
IO.puts "\n #{winner} win!\n"
game(score)
end
 
defp setup(:Heads) do
myC = Enum.shuffle(@toss) ++ [Enum.random(@toss)]
joined = Enum.join(myC, " ")
IO.puts "I chose  : #{joined}"
{myC, yourChoice}
end
defp setup(:Tails) do
yC = yourChoice
myC = (@toss -- [Enum.at(yC,1)]) ++ Enum.take(yC,2)
joined = Enum.join(myC, " ")
IO.puts "I chose  : #{joined}"
{myC, yC}
end
 
defp yourChoice do
IO.write "Enter your choice (H/T) "
choice = read([])
IO.puts "You chose: #{Enum.join(choice, " ")}"
choice
end
 
defp read([_,_,_]=choice), do: choice
defp read(choice) do
case IO.getn("") |> String.upcase do
"H" -> read(choice ++ [:Heads])
"T" -> read(choice ++ [:Tails])
_ -> read(choice)
end
end
 
defp loop(myC, myC, _, {iwin, ywin}), do: {"I", {iwin+1, ywin}}
defp loop(yC, _, yC, {iwin, ywin}), do: {"You", {iwin, ywin+1}}
defp loop(seq, myC, yC, score) do
append = Enum.random(@toss)
IO.write " #{append}"
loop(tl(seq)++[append], myC, yC, score)
end
end
 
Penney.game
Output:
Penney game score  I : 0, You : 0
Heads I start, Tails you start ..... Heads
I chose  : Tails Heads Heads
Enter your choice (H/T) TTH
You chose: Tails Tails Heads
Heads Heads Tails Tails Tails Tails Heads
 You win!

Penney game score  I : 0, You : 1
Heads I start, Tails you start ..... Tails
Enter your choice (H/T) THT
You chose: Tails Heads Tails
I chose  : Tails Tails Heads
Tails Heads Heads Heads Tails Tails Heads
 I win!

Penney game score  I : 1, You : 1
Heads I start, Tails you start ..... Tails
Enter your choice (H/T)

Go[edit]

 
package main
import "fmt"
import "math/rand"
func main(){
var a1,a2,a3,y,match,j,k int
var inp string
y=1
for y==1{
fmt.Println("Enter your sequence:")
fmt.Scanln(&inp)
var Ai [3] int
var user [3] int
for j=0;j<3;j++{
if(inp[j]==104){
user[j]=1
}else{
user[j]=0
}
}
for k=0;k<3;k++{
Ai[k]=rand.Intn(2)
}
for user[0]==Ai[0]&&user[1]==Ai[1]&&user[2]==Ai[2]{
for k=0;k<3;k++{
Ai[k]=rand.Intn(2)
}
}
fmt.Println("You gave the sequence:")
printht(user)
fmt.Println()
fmt.Println("The computer generated sequence is:")
printht(Ai)
fmt.Println()
a1=rand.Intn(2)
a2=rand.Intn(2)
a3=rand.Intn(2)
fmt.Print("The generated sequence is:")
printh(a1)
printh(a2)
printh(a3)
match=0
for match==0{
if(matches(user,a1,a2,a3)==1){
fmt.Println()
fmt.Println("You have won!!!")
match=1
}else if(matches(Ai,a1,a2,a3)==1){
fmt.Println()
fmt.Println("You lost!! Computer wins")
match=1
}else{
a1=a2
a2=a3
a3=rand.Intn(2)
printh(a3)
}
}
fmt.Println("Do you want to continue(0/1):")
fmt.Scanln(&y)
}
}
func printht(a [3] int) int{
var i int
for i=0;i<3;i++{
if(a[i]==1){
fmt.Print("h")
}else{
fmt.Print("t")
}
}
return 1
}
func printh(a int) int{
if(a==1){
fmt.Print("h")
}else{
fmt.Print("t")
}
return 1
}
func matches(a [3] int,p int,q int,r int) int{
if(a[0]==p&&a[1]==q&&a[2]==r){
return 1
}else{
return 0
}
}
 

Output:

Enter your sequence:
tht
You gave the sequence:
tht
The computer generated sequence is:
hhh
The generated sequence is:hhtht
You have won!!!
Do you want to continue(0/1):

Haskell[edit]

import qualified Data.List as L
import System.IO
import System.Random
 
data CoinToss = H | T deriving (Read, Show, Eq)
 
parseToss :: String -> [CoinToss]
parseToss [] = []
parseToss (s:sx)
| s == 'h' || s == 'H' = H : parseToss sx
| s == 't' || s == 'T' = T : parseToss sx
| otherwise = parseToss sx
 
notToss :: CoinToss -> CoinToss
notToss H = T
notToss T = H
 
instance Random CoinToss where
random g = let (b, gb) = random g in (if b then H else T, gb)
randomR = undefined
 
prompt :: (Read a) => String -> String -> (String -> Maybe a) -> IO a
prompt msg err parse = do
putStrLn msg
line <- getLine
let ans = parse line
case ans of
Nothing -> do
putStrLn err
prompt msg err parse
Just ansB -> return ansB
 
showCat :: (Show a) => [a] -> String
showCat = concatMap show
 
data Winner = Player | CPU
 
-- This may never terminate.
runToss :: (RandomGen g) => [CoinToss] -> [CoinToss] -> g -> ([CoinToss], Winner)
runToss player cpu gen =
let stream = randoms gen
run ss@(s:sx)
| L.isPrefixOf player ss = player
| L.isPrefixOf cpu ss = cpu
| otherwise = s : run sx
winner = run stream
in if L.isSuffixOf player winner
then (winner, Player)
else (winner, CPU)
 
game :: (RandomGen g, Num a, Show a) => Bool -> a -> a -> g -> IO ()
game cpuTurn playerScore cpuScore gen = do
putStrLn $ "\nThe current score is CPU: " ++ show cpuScore
++ ", You: " ++ show playerScore
 
let (genA, genB) = split gen
promptPlayer check =
prompt "Pick 3 coin sides: " "Invalid input." $ \s ->
let tosses = parseToss s in
if check tosses then Just tosses else Nothing
promptCpu x = putStrLn $ "I have chosen: " ++ showCat x
 
(tosses, winner) <-
if cpuTurn
then do
let cpuChoice = take 3 $ randoms gen
promptCpu cpuChoice
playerChoice <- promptPlayer $ \n -> n /= cpuChoice && 3 == length n
return $ runToss playerChoice cpuChoice genA
else do
playerChoice <- promptPlayer $ \n -> 3 == length n
let cpuChoice = case playerChoice of [a,b,_] -> [notToss b, a, b]
promptCpu cpuChoice
return $ runToss playerChoice cpuChoice genA
 
putStrLn $ "The sequence tossed was: " ++ showCat tosses
 
case winner of
Player -> do
putStrLn "You win!"
game (not cpuTurn) (playerScore + 1) cpuScore genB
CPU -> do
putStrLn "I win!"
game (not cpuTurn) playerScore (cpuScore + 1) genB
 
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
stdgen <- getStdGen
let (cpuFirst, genA) = random stdgen
game cpuFirst 0 0 genA
Output:
The current score is CPU: 0, You: 0
Pick 3 coin sides:
HTH
I have chosen: HHT
The sequence tossed was: TTTTTTHHT
I win!

The current score is CPU: 1, You: 0
I have chosen: TTT
Pick 3 coin sides:
HTT
The sequence tossed was: HTT
You win!

The current score is CPU: 1, You: 1
Pick 3 coin sides:

J[edit]

Solution:

require 'format/printf numeric'
 
randomize '' NB. randomize seed for new session
 
Vals=: 'HT' NB. valid values
input=: 1!:1@<&1: NB. get input from user
prompt=: [email protected] NB. prompt user for input
checkInput=: 'Choose 3 H/Ts' assert (Vals e.~ ]) , 3 = #
getUserSeq=: (] [ checkInput)@[email protected]
choose1st=: Vals {~ 3 [email protected]$ 2: NB. computer chooses 1st
choose2nd=: (0 1 1=1 0 1{])&.(Vals&i.) NB. computer chooses 2nd
 
playPenney=: verb define
if. ?2 do. NB. randomize first chooser
Comp=. choose1st ''
'Computer chose %s' printf <Comp
You=. getUserSeq 'Choose a sequence of three coin tosses (H/T):'
'Choose a different sequence to computer' assert You [email protected]: Comp
else.
You=. getUserSeq 'Choose a sequence of three coin tosses (H/T):'
Comp=. choose2nd You
'Computer chose %s ' printf <Comp
end.
Tosses=. Vals {~ 100 [email protected]$ 2
Result=. (Comp,:You) {[email protected]@E."1 Tosses
'Toss sequence is %s' printf < (3 + <./ Result) {. Tosses
echo ('No result';'You win!';'Computer won!') {::~ *-/ Result
)

Usage:

   playPenney''
Computer chose TTT
Choose a sequence of three coin tosses (H/T):
HTT
Toss sequence is TTHHTT
You win!
playPenney''
Choose a sequence of three coin tosses (H/T):
HTT
Computer chose HHT
Toss sequence is HTHTT
You win!

Java[edit]

import java.util.*;
 
public class PenneysGame {
 
public static void main(String[] args) {
Random rand = new Random();
 
String compChoice = "", playerChoice;
if (rand.nextBoolean()) {
 
for (int i = 0; i < 3; i++)
compChoice += "HT".charAt(rand.nextInt(2));
System.out.printf("Computer chooses %s%n", compChoice);
 
playerChoice = prompt(compChoice);
 
} else {
 
playerChoice = prompt(compChoice);
 
compChoice = "T";
if (playerChoice.charAt(1) == 'T')
compChoice = "H";
compChoice += playerChoice.substring(0, 2);
System.out.printf("Computer chooses %s%n", compChoice);
}
 
String tossed = "";
while (true) {
tossed += "HT".charAt(rand.nextInt(2));
System.out.printf("Tossed %s%n" , tossed);
if (tossed.endsWith(playerChoice)) {
System.out.println("You win!");
break;
}
if (tossed.endsWith(compChoice)) {
System.out.println("Computer wins!");
break;
}
}
}
 
private static String prompt(String otherChoice) {
Scanner sc = new Scanner(System.in);
String s;
do {
System.out.print("Choose a sequence: ");
s = sc.nextLine().trim().toUpperCase();
} while (!s.matches("[HT]{3}") || s.equals(otherChoice));
return s;
}
}
Computer chooses HTH
Choose a sequence: hhh
Tossed H
Tossed HH
Tossed HHH
You win!

Choose a sequence: tth
Computer chooses HTT
Tossed H
Tossed HT
Tossed HTH
Tossed HTHH
Tossed HTHHT
Tossed HTHHTT
Computer wins!

Julia[edit]

Functions

 
const SLEN = 3
 
autobet() = randbool(SLEN)
function autobet(ob::BitArray{1})
rlen = length(ob)
2 < rlen || return ~ob
3 < rlen || return [~ob[2], ob[1:2]]
opt = falses(rlen)
opt[1] = true
opt[end-1:end] = true
ob != opt || return ~opt
return opt
end
autobet(ob::Array{Bool,1}) = autobet(convert(BitArray{1}, ob))
 
function pgencode{T<:String}(a::T)
b = uppercase(a)
0 < length(b) || return trues(0)
 !ismatch(r"[^HT]+", b) || error(@sprintf "%s is not a HT sequence" a)
b = split(b, "")
b .== "H"
end
pgdecode(a::BitArray{1}) = join([i ? "H" : "T" for i in a], "")
 
function humanbet()
b = ""
while length(b) != SLEN || ismatch(r"[^HT]+", b)
print("Your bet? ")
b = uppercase(chomp(readline()))
end
return b
end
 

Game Setup

 
println("Playing Penney's Game Against the computer.")
 
if randbool()
mach = autobet()
println(@sprintf "The computer bet first, chosing %s." pgdecode(mach))
println("Now you can bet.")
human = pgencode(humanbet())
else
println("You bet first.")
human = pgencode(humanbet())
mach = autobet(human)
end
print(@sprintf "You bet %s " pgdecode(human))
println(@sprintf "and the computer bet %s." pgdecode(mach))
 

Game Play

 
pg = randbool(SLEN)
pgtail = copy(pg)
while pgtail != mach && pgtail != human
push!(pg, randbool())
pgtail = [pgtail[2:end], pg[end]]
end
 
println(@sprintf("This game lasted %d turns yielding\n  %s",
length(pg), pgdecode(pg)))
 
if human == mach
println("so you and the computer tied.")
elseif pgtail == mach
println("so the computer won.")
else
println("so you won.")
end
 
Output:
$ julia penneys_game.jl
Playing Penney's Game Against the computer.
You bet first.
Your bet? tht
You bet THT and the computer bet TTH.
This game lasted 10 turns yielding
    HHTTTTTTTH
so the computer won.

$ julia penneys_game.jl
Playing Penney's Game Against the computer.
You bet first.
Your bet? hhh
You bet HHH and the computer bet THH.
This game lasted 8 turns yielding
    TTHTHTHH
so the computer won.

$ julia penneys_game.jl
Playing Penney's Game Against the computer.
The computer bet first, chosing HTT.
Now you can bet.
Your bet? hht
You bet HHT and the computer bet HTT.
This game lasted 6 turns yielding
    TTHHHT
so you won.

$ julia penneys_game.jl
Playing Penney's Game Against the computer.
The computer bet first, chosing HTT.
Now you can bet.
Your bet? hht
You bet HHT and the computer bet HTT.
This game lasted 6 turns yielding
    THTHHT
so you won.

$ julia penneys_game.jl
Playing Penney's Game Against the computer.
You bet first.
Your bet? htt
You bet HTT and the computer bet HHT.
This game lasted 10 turns yielding
    TTTTHHHHHT
so the computer won.

Lua[edit]

 
function penny_game()
local player, computer = "", ""
function player_choose()
io.write( "Enter your sequence of three H and/or T: " )
local t = io.read():upper()
if #t > 3 then t = t:sub( 1, 3 )
elseif #t < 3 then return ""
end
 
for i = 1, 3 do
c = t:sub( i, i )
if c ~= "T" and c ~= "H" then
print( "Just H's and T's!" )
return ""
end
end
return t
end
function computer_choose()
local t = ""
if #player > 0 then
if player:sub( 2, 2 ) == "T" then
t = "H"
else
t = "T";
end
t = t .. player:sub( 1, 2 )
else
for i = 1, 3 do
if math.random( 2 ) == 1 then
t = t .. "H"
else
t = t .. "T"
end
end
end
return t
end
if math.random( 2 ) == 1 then
computer = computer_choose()
io.write( "My sequence is: " .. computer .. "\n" )
while( true ) do
player = player_choose()
if player:len() == 3 then break end
end
else
while( true ) do
player = player_choose()
if player:len() == 3 then break end
end
computer = computer_choose()
io.write( "My sequence is: " .. computer .. "\n" )
end
local coin, i = "", 1
while( true ) do
if math.random( 2 ) == 1 then
coin = coin .. "T"
io.write( "T" )
else
coin = coin .. "H"
io.write( "H" )
end
if #coin > 2 then
local seq = coin:sub( i, i + 2 )
i = i + 1
if seq == player then
print( "\nPlayer WINS!!!" )
return 1
elseif seq == computer then
print( "\nComputer WINS!!!" )
return -1
end
end
end
end
math.randomseed( os.time() )
local cpu, user = 0, 0
repeat
r = penny_game()
if r > 0 then
user = user + 1
else
cpu = cpu + 1
end
print( "Player: " .. user .. " CPU: " .. cpu )
io.write( "Play again (Y/N)? " )
r = io.read()
until( r == "N" or r == "n" )
 
Output:
>lua -e "io.stdout:setvbuf 'no'" "penny.lua" 
My sequence is: TTH
Enter your sequence of three H and/or T: HHT
TTTTH
Computer WINS!!!
Player: 0 CPU: 1
Play again (Y/N)? y
Enter your sequence of three H and/or T: HTH
My sequence is: HHT
THTTHTH
Player WINS!!!
Player: 1 CPU: 1
Play again (Y/N)? y
My sequence is: HHH
Enter your sequence of three H and/or T: TTH
HTTHHTH
Player WINS!!!
Player: 2 CPU: 1
Play again (Y/N)? n
>Exit code: 0

Perl[edit]

 
#!usr/bin/perl
use 5.020;
use strict;
use warnings;
 
#Choose who goes first
binaryRand() == 0 ? flipCoin(userFirst()) : flipCoin(compFirst());
 
#Return a randomly generated 1 or 0
sub binaryRand
{
return int(rand(2));
}
#Converts 1's and 0's to H's and T's, respectively.
sub convert
{
my $randNum = binaryRand();
if($randNum == 0)
{
return "T"
}
else
{
return "H";
}
}
 
#Prompts for and returns a user's sequence of 3
sub uSeq
{
print("Please enter a sequence of 3 of \"H\" and \"T\". EG: HHT\n>");
my $uString = <STDIN>;
 
while(1)
{
#Make it uppercase and validate input
chomp($uString);
$uString = uc $uString;
#Check length and content (H's and T's only!)
if(length $uString == 3 && (substr($uString, 0, 1) =~ /[HT]/ &&
substr($uString, 1, 1) =~ /[HT]/ &&
substr($uString, 2, 1) =~ /[HT]/))
{
last;
}
else
{
print("Error, try again. \n");
print("Please enter a sequence of 3 of \"H\" and \"T\". EG: HHT\n");
$uString = <STDIN>;
}
}
return $uString;
}
 
#Returns an array with two elements: [0] user's seq, [1] random computer seq.
sub compFirst
{
my $cSeq;
#Randomly draw a sequence of 3
for(my $i = 0; $i < 3; $i++)
{
$cSeq = $cSeq . convert();
}
 
print("The computer guesses first:\ncomp- $cSeq\n");
my $uSeq = uSeq();
print("user- $uSeq\n");
my @seqArr = ($uSeq, $cSeq);
return @seqArr;
}
 
#Returns an array with two elements: [0] user's seq, [1] optimal computer seq.
sub userFirst
{
print("The user quesses first:\n");
my $uSeq = uSeq();
my $cSeq;
#Generate the optimal sequence based on $uSeq
my $middle = substr($uSeq, 1, 1);
$middle eq "H" ? $cSeq = "T" : $cSeq = "H";
$cSeq = $cSeq . substr($uSeq, 0, 2);
 
print("user- $uSeq\ncomp- $cSeq\n");
my @seqArr = ($uSeq, $cSeq);
return @seqArr;
}
 
#Flips a coin, checking both sequences against the contents of the given array
sub flipCoin
{
my ($uSeq, $cSeq) = @_;
my $coin;
while(1)
{
$coin = $coin . convert();
if($coin =~ m/$uSeq/)
{
print("The sequence of tosses was: $coin\n");
say("The player wins! ");
last;
}
elsif($coin =~ m/$cSeq/)
{
print("The sequence of tosses was: $coin\n");
say("The computer wins! ");
last;
}
}
}
 
Output:
The computer guesses first:
comp- HHH
Please enter a sequence of 3 of "H" and "T". EG: HHT
>thh
user- THH
The sequence of tosses was: HTTHTTHTHTHTTTHTTTHH
The player wins! 
================================================
The user quesses first:
Please enter a sequence of 3 of "H" and "T". EG: HHT
>hht
user- HHT
comp- HHH
The sequence of tosses was: THHH
The computer wins! 

Perl 6[edit]

enum Coin <Heads Tails>;
enum Yay <Yay Good Super Hah Ooh Yipee Sweet Cool Yes Haha>;
enum Boo <Drat Darn Crumb Oops Rats Bah Criminy Argh Shards>;
enum Bozo «'Dude' 'Cha' 'Bzzt' 'Hey' 'Silly dilly' 'Say what!?' 'You numbskull'»;
 
sub flipping {
for 1..4 {
print "-\b"; sleep .1;
print "\\\b"; sleep .1;
print "|\b"; sleep .1;
print "/\b"; sleep .1;
}
}
 
sub your-choice($p is copy) {
loop (my @seq; @seq != 3; $p = "{Bozo.pick}! Please pick exactly 3: ") {
@seq = prompt($p).uc.comb(/ H | T /).map: {
when 'H' { Heads }
when 'T' { Tails }
}
}
@seq;
}
 
repeat until prompt("Wanna play again? ").lc ~~ /^n/ {
my $mefirst = Coin.roll;
print tc "$mefirst I start, {Coin(+!$mefirst).lc} you start, flipping...\n\t";
flipping;
say my $flip = Coin.roll;
 
my @yours;
my @mine;
 
if $flip == $mefirst {
print "{Yay.pick}! I get to choose first, and I choose: "; sleep 2; say @mine = Coin.roll(3);
@yours = your-choice("Now you gotta choose: ");
while @yours eqv @mine {
say "{Bozo.pick}! We'd both win at the same time if you pick that!";
@yours = your-choice("Pick something different from me: ");
}
say "So, you'll win if we see: ", @yours;
}
else {
@yours = your-choice("{Boo.pick}! First you choose: ");
say "OK, you'll win if we see: ", @yours;
print "In that case, I'll just randomly choose: "; sleep 2; say @mine = Coin(+!@yours[1]), @yours[0,1];
}
 
sub check($a,$b,$c) {
given [$a,$b,$c] {
when @mine { say "\n{Yay.pick}, I win, and you lose!"; Nil }
when @yours { say "\n{Boo.pick}, you win, but I'll beat you next time!"; Nil }
default { Coin.roll }
}
}
 
sleep 1;
say < OK! Ready? Right... So... Yo!>.pick;
sleep .5;
say ("Pay attention now!",
"Watch closely!",
"Let's do it...",
"You feeling lucky?",
"No way you gonna win this...",
"Can I borrow that coin again?").pick;
sleep 1;
print "Here we go!\n\t";
for Coin.roll(3), &check ...^ :!defined {
flipping;
print "$_ ";
}
}
Output:

Note: the actual run displays a little coin-flipping animation, but that won't show up here:

Heads I start, tails you start, flipping...
	Heads
Yipee! I get to choose first, and I choose: Heads Heads Tails
Now you gotta choose: tth
So, you'll win if we see: Tails Tails Heads
Yo!
Can I borrow that coin again?
Here we go!
	Tails Tails Tails Tails Tails Heads 
Argh, you win, but I'll beat you next time!
Wanna play again? y
Tails I start, heads you start, flipping...
	Tails
Yes! I get to choose first, and I choose: Heads Tails Tails
Now you gotta choose: H T T
Dude! We'd both win at the same time if you pick that!
Pick something different from me: heads tails tails
Silly dilly! We'd both win at the same time if you pick that!
Pick something different from me: h,h,h
So, you'll win if we see: Heads Heads Heads
OK!
You feeling lucky?
Here we go!
	Tails Tails Tails Heads Heads Heads 
Drat, you win, but I'll beat you next time!
Wanna play again? y
Heads I start, tails you start, flipping...
	Tails
Shards! First you choose: tht
OK, you'll win if we see: Tails Heads Tails
In that case, I'll just randomly choose: Tails Tails Heads
Right...
Pay attention now!
Here we go!
	Heads Tails Tails Heads 
Hah, I win, and you lose!
Wanna play again? n

Python[edit]

from __future__ import print_function
import random
from time import sleep
 
first = random.choice([True, False])
 
you = ''
if first:
me = ''.join(random.sample('HT'*3, 3))
print('I choose first and will win on first seeing {} in the list of tosses'.format(me))
while len(you) != 3 or any(ch not in 'HT' for ch in you) or you == me:
you = input('What sequence of three Heads/Tails will you win with: ')
else:
while len(you) != 3 or any(ch not in 'HT' for ch in you):
you = input('After you: What sequence of three Heads/Tails will you win with: ')
me = ('H' if you[1] == 'T' else 'T') + you[:2]
print('I win on first seeing {} in the list of tosses'.format(me))
 
print('Rolling:\n ', end='')
rolled = ''
while True:
rolled += random.choice('HT')
print(rolled[-1], end='')
if rolled.endswith(you):
print('\n You win!')
break
if rolled.endswith(me):
print('\n I win!')
break
sleep(1) # For dramatic effect
Output:
>>> 
After you: What sequence of three Heads/Tails will you win with: TTH
I win on first seeing HTT in the list of tosses
Rolling:
  THHTHHTT
  I win!
>>> ================================ RESTART ================================
>>> 
I choose first and will win on first seeing HHT in the list of tosses
What sequence of three Heads/Tails will you win with: THH
Rolling:
  HTHTHTTTHTTTTTTHH
  You win!
>>> 

R[edit]

#===============================================================
# Penney's Game Task from Rosetta Code Wiki
# R implementation
#===============================================================
 
penneysgame <- function() {
 
#---------------------------------------------------------------
# Who goes first?
#---------------------------------------------------------------
 
first <- sample(c("PC", "Human"), 1)
 
#---------------------------------------------------------------
# Determine the sequences
#---------------------------------------------------------------
 
if (first == "PC") { # PC goes first
 
pc.seq <- sample(c("H", "T"), 3, replace = TRUE)
cat(paste("\nI choose first and will win on first seeing", paste(pc.seq, collapse = ""), "in the list of tosses.\n\n"))
human.seq <- readline("What sequence of three Heads/Tails will you win with: ")
human.seq <- unlist(strsplit(human.seq, ""))
 
} else if (first == "Human") { # Player goest first
 
cat(paste("\nYou can choose your winning sequence first.\n\n"))
human.seq <- readline("What sequence of three Heads/Tails will you win with: ")
human.seq <- unlist(strsplit(human.seq, "")) # Split the string into characters
pc.seq <- c(human.seq[2], human.seq[1:2]) # Append second element at the start
pc.seq[1] <- ifelse(pc.seq[1] == "H", "T", "H") # Switch first element to get the optimal guess
cat(paste("\nI win on first seeing", paste(pc.seq, collapse = ""), "in the list of tosses.\n"))
 
}
 
#---------------------------------------------------------------
# Start throwing the coin
#---------------------------------------------------------------
 
cat("\nThrowing:\n")
 
ran.seq <- NULL
 
while(TRUE) {
 
ran.seq <- c(ran.seq, sample(c("H", "T"), 1)) # Add a new coin throw to the vector of throws
 
cat("\n", paste(ran.seq, sep = "", collapse = "")) # Print the sequence thrown so far
 
if (length(ran.seq) >= 3 && all(tail(ran.seq, 3) == pc.seq)) {
cat("\n\nI win!\n")
break
}
 
if (length(ran.seq) >= 3 && all(tail(ran.seq, 3) == human.seq)) {
cat("\n\nYou win!\n")
break
}
 
Sys.sleep(0.5) # Pause for 0.5 seconds
 
}
}
 
Output:

Human first.

You can choose your winning sequence first.

What sequence of three Heads/Tails will you win with: THH

I win on first seeing TTH in the list of tosses.

Throwing:

 T
 TT
 TTT
 TTTH

I win!

PC first

I choose first and will win on first seeing THH in the list of tosses.

What sequence of three Heads/Tails will you win with: TTH

Throwing:

 T
 TH
 THT
 THTT
 THTTH

You win!

Racket[edit]

This does what's required of it from the task... just don't input anything outside the alphabet "htHT" for the human move.

#lang racket
;; Penney's Game. Tim Brown 2014-10-15
(define (flip . _) (match (random 2) (0 "H") (1 "T")))
 
(define (get-human-sequence) ; no sanity checking here!
(display "choose your winning sequence of 3 H or T > ")
(drop-right (drop (string-split (string-upcase (read-line)) "") 1) 1))
 
(define flips->string (curryr string-join "."))
 
(define (game-on p1 p2)
(printf "~a chooses: ~a. ~a chooses: ~a~%"
(car p1) (flips->string (cdr p1)) (car p2) (flips->string (cdr p2)))
(match-define (list (list name.1 p1.1 p1.2 p1.3) (list name.2 p2.1 p2.2 p2.3)) (list p1 p2))
(let turn ((seq null))
(match seq
[(list-rest (== p1.3) (== p1.2) (== p1.1) _) name.1]
[(list-rest (== p2.3) (== p2.2) (== p2.1) _) name.2]
[else
(let* ((flp (flip)) (seq+ (cons flp else)))
(printf "new-flip: ~a -> ~a~%" flp (flips->string (reverse seq+))) (turn seq+))])))
 
(define (play-game)
(define-values
(player-1 player-2)
(match (flip)
["H" (printf "Human chooses first: ")
(define p1 (cons 'Hom-Sap (get-human-sequence)))
(values p1 (cons 'Computer
(match p1
[(list _ f1 (and f2 (app (match-lambda ("H" "T") ("T" "H")) ¬f2)) _)
(list ¬f2 f1 f2)])))]
["T" (printf "Computer chooses first. ")
(define p1 (cons 'Computer (build-list 3 flip)))
(printf "~a chooses: ~a~%" (car p1) (flips->string (cdr p1)))
(values p1 (cons 'Hom-Sap (get-human-sequence)))]))
(printf "~a wins!~%" (game-on player-1 player-2)))
Output:

Homo Sapiens Plays First (and wins!)[edit]

> (play-game)
Human chooses first: choose your winning sequence of 3 H or T > hth
Hom-Sap chooses: H.T.H. Computer chooses: H.H.T
new-flip: H -> H
new-flip: T -> H.T
new-flip: H -> H.T.H
Hom-Sap wins!

The Computer Plays First (and loses!)[edit]

> (play-game)
Computer chooses first. Computer chooses: T.T.T
choose your winning sequence of 3 H or T > htt
Computer chooses: T.T.T. Hom-Sap chooses: H.T.T
new-flip: H -> H
new-flip: H -> H.H
new-flip: H -> H.H.H
new-flip: T -> H.H.H.T
new-flip: H -> H.H.H.T.H
new-flip: T -> H.H.H.T.H.T
new-flip: H -> H.H.H.T.H.T.H
new-flip: T -> H.H.H.T.H.T.H.T
new-flip: H -> H.H.H.T.H.T.H.T.H
new-flip: T -> H.H.H.T.H.T.H.T.H.T
new-flip: T -> H.H.H.T.H.T.H.T.H.T.T
Hom-Sap wins!

(Nail-biting stuff!)

REXX[edit]

The REXX program keeps a running score   (number of wins out of so many games played)   as well as
allowing the human to pick the number (length) of the coin toss sequence.

A fair amount of code was added to ensure a valid response from the human player as well as give an informative error message.

The human player is allowed to spell out the   H   or   T   (as heads or tails).

A feature also added was to allow a seed for the   random   BIF to allow repeatability for a game.

/*REXX program plays/simulates  Penney's Game,  a  two-player  coin toss sequence game. */
__=copies('─',9) /*literal for eyecatching fence. */
signal on halt /*a clean way out if CLBF quits. */
parse arg # seed . /*obtain optional arguments from the CL*/
if #=='' | #=="," then #=3 /*Not specified? Then use the default.*/
if datatype(seed,'W') then call random ,,seed /*use seed for RANDOM #s repeatability.*/
wins=0; do games=1 /*simulate a number of Penney's games. */
call game /*simulate a single inning of a game. */
end /*games*/ /*keep at it until QUIT or halt. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
halt: say; say __ "Penney's Game was halted."; say; exit 13
r: arg ,$; do arg(1); $=$ || random(0,1); end; return $
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1) /*pluralizer.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
game: @.=; [email protected]. /*the coin toss sequence so far. */
toss1=r(1) /*result: 0=computer, 1=CBLF.*/
if \toss1 then call randComp /*maybe let the computer go first*/
if toss1 then say __ "You win the first toss, so you pick your sequence first."
else say __ "The computer won first toss, the pick was: " @.comp
call prompter /*get the human's guess from C.L.*/
call randComp /*get computer's guess if needed.*/
/*CBLF: carbon-based life form. */
say __ " your pick:" @.CBLF /*echo human's pick to terminal. */
say __ "computer's pick:" @.comp /* " comp.'s " " " */
say /* [↓] flip the coin 'til a win.*/
do flips=1 until pos(@.CBLF,tosses)\==0 | pos(@.comp,tosses)\==0
tosses=tosses || translate(r(1),'HT',10)
end /*flips*/ /* [↑] this is a flipping coin,*/
/* [↓] series of tosses*/
say __ "The tossed coin series was: " tosses
say
@@@="won this toss with " flips ' coin tosses.'
if pos(@.CBLF,tosses)\==0 then do; say __ "You" @@@; wins=wins+1; end
else say __ "The computer" @@@
_=wins; if _==0 then _='no'
say __ "You've won" _ "game"s(wins) 'out of ' games"."
say; say copies('╩╦',79%2)'╩'; say
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
prompter: oops=__ 'Oops! '; a= /*define some handy REXX literals*/
@a_z='ABCDEFG-IJKLMNOPQRS+UVWXYZ' /*the extraneous alphabetic chars*/
p=__ 'Pick a sequence of' # "coin tosses of H or T (Heads or Tails) or Quit:"
do until ok; say; say p; pull a /*uppercase the answer. */
if abbrev('QUIT',a,1) then exit 1 /*the human wants to quit. */
a=space(translate(a,,@a_z',./\;:_'),0) /*elide extraneous characters. */
b=translate(a,10,'HT'); L=length(a) /*translate ───► bin; get length.*/
ok=0 /*the response is OK (so far). */
select /*verify the user response. */
when \datatype(b,'B') then say oops "Illegal response."
when \datatype(a,'M') then say oops "Illegal characters in response."
when L==0 then say oops "No choice was given."
when L<# then say oops "Not enough coin choices."
when L># then say oops "Too many coin choices."
when [email protected].comp then say oops "You can't choose the computer's choice: " @.comp
otherwise ok=1
end /*select*/
end /*until ok*/
@.CBLF=a; @.CBLF!=b /*we have the human's guess now. */
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
randComp: if @.comp\=='' then return /*the computer already has a pick*/
[email protected].CBLF! /* [↓] use best-choice algorithm.*/
if _\=='' then g=left((\substr(_, min(2, #), 1))left(_, 1)substr(_, 3), #)
do until g\[email protected].CBLF!; g=r(#); end /*otherwise, generate a choice. */
@.comp=translate(g, 'HT', 10)
return

output   of a six-game session   (ended by user entering a quit):

───────── The computer won first toss, the pick was:  HHH

───────── Pick a sequence of 3 coin tosses of  H or T (Heads or Tails) or Quit:
tail tail tails          ◄■■■■■■■■■■■ human's input

─────────       your pick: TTT
───────── computer's pick: HHH

───────── The computer won this toss with  12  coin tosses.

───────── The tossed coin series was:  HHTTHHTHTHHH

───────── You've won no games out of  1.

╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩

───────── You win the first toss, so you pick your sequence first.

───────── Pick a sequence of 3 coin tosses of  H or T (Heads or Tails) or Quit:
h, h, t                  ◄■■■■■■■■■■■ human's input

─────────       your pick: HHT
───────── computer's pick: THT

───────── The computer won this toss with  5  coin tosses.

───────── The tossed coin series was:  TTTHT

───────── You've won no games out of  2.

╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩

───────── The computer won first toss, the pick was:  HHT

───────── Pick a sequence of 3 coin tosses of  H or T (Heads or Tails) or Quit:
heads heads heads        ◄■■■■■■■■■■■ human's input

─────────       your pick: HHH
───────── computer's pick: HHT

───────── The computer won this toss with  3  coin tosses.

───────── The tossed coin series was:  HHT

───────── You've won no games out of  3.

╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩

───────── The computer won first toss, the pick was:  HTH

───────── Pick a sequence of 3 coin tosses of  H or T (Heads or Tails) or Quit:
t t h                    ◄■■■■■■■■■■■ human's input 

─────────       your pick: TTH
───────── computer's pick: HTH

───────── You won this toss with  3  coin tosses.

───────── The tossed coin series was:  TTH

───────── You've won 1 game out of  4.

╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩

───────── You win the first toss, so you pick your sequence first.

───────── Pick a sequence of 3 coin tosses of  H or T (Heads or Tails) or Quit:
t,h,h                    ◄■■■■■■■■■■■ human's input

─────────       your pick: THH
───────── computer's pick: HTH

───────── You won this toss with  4  coin tosses.

───────── The tossed coin series was:  TTHH

───────── You've won 2 games out of  5.

╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩

───────── The computer won first toss, the pick was:  TTH

───────── Pick a sequence of 3 coin tosses of  H or T (Heads or Tails) or Quit:
tth                      ◄■■■■■■■■■■■ human's input
───────── Oops!   You can't choose the computer's choice:  TTH

───────── Pick a sequence of 3 coin tosses of  H or T (Heads or Tails) or Quit:
tht                      ◄■■■■■■■■■■■ human's input

─────────       your pick: THT
───────── computer's pick: TTH

───────── The computer won this toss with  3  coin tosses.

───────── The tossed coin series was:  TTH

───────── You've won 2 games out of  6.

╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩╦╩

───────── You win the first toss, so you pick your sequence first.

───────── Pick a sequence of 3 coin tosses of  H or T (Heads or Tails) or Quit:
quit                     ◄■■■■■■■■■■■ human's input

Ruby[edit]

Toss = [:Heads, :Tails]
 
def yourChoice
puts "Enter your choice (H/T)"
choice = []
3.times do
until (c = $stdin.getc.upcase) == "H" or c == "T"
end
choice << (c=="H" ? Toss[0] : Toss[1])
end
puts "You chose #{choice.join(' ')}"
choice
end
 
loop do
puts "\n%s I start, %s you start ..... %s" % [*Toss, coin = Toss.sample]
if coin == Toss[0]
myC = Toss.shuffle << Toss.sample
puts "I chose #{myC.join(' ')}"
yC = yourChoice
else
yC = yourChoice
myC = Toss - [yC[1]] + yC.first(2)
puts "I chose #{myC.join(' ')}"
end
 
seq = Array.new(3){Toss.sample}
print seq.join(' ')
loop do
puts "\n I win!" or break if seq == myC
puts "\n You win!" or break if seq == yC
seq.push(Toss.sample).shift
print " #{seq[-1]}"
end
end
Output:
Heads I start, Tails you start ..... Tails
Enter your choice (H/T)
THT
You chose Tails Heads Tails
I chose Tails Tails Heads
Heads Tails Heads Heads Tails Tails Tails Heads
 I win!

Heads I start, Tails you start ..... Heads
I chose Heads Heads Heads
Enter your choice (H/T)
THH
You chose Tails Heads Heads
Heads Heads Tails Heads Tails Heads Tails Tails Tails Tails Tails Tails Tails Heads Heads
 You win!

Tcl[edit]

Works with: Tcl version 8.6
package require Tcl 8.6
 
oo::class create Player {
variable who seq seen idx
 
constructor {name sequence} {
set who $name
set seq $sequence
set seen {}
set idx end-[expr {[string length $seq] - 1}]
}
 
method pick {} {
return $seq
}
 
method name {} {
return $who
}
 
method match {digit} {
append seen $digit
return [expr {[string range $seen $idx end] eq $seq}]
}
}
 
oo::class create HumanPlayer {
superclass Player
constructor {length {otherPlayersSelection ""}} {
fconfigure stdout -buffering none
while true {
puts -nonewline "What do you pick? (length $length): "
if {[gets stdin pick] < 0} exit
set pick [regsub -all {[^HT]} [string map {0 H 1 T h H t T} $pick] ""]
if {[string length $pick] eq $length} break
puts "That's not a legal pick!"
}
set name "Human"
if {[incr ::humans] > 1} {append name " #$::humans"}
next $name $pick
}
}
 
oo::class create RobotPlayer {
superclass Player
constructor {length {otherPlayersSelection ""}} {
if {$otherPlayersSelection eq ""} {
set pick ""
for {set i 0} {$i < $length} {incr i} {
append pick [lindex {H T} [expr {int(rand()*2)}]]
}
} else {
if {$length != 3} {
error "lengths other than 3 not implemented"
}
lassign [split $otherPlayersSelection ""] a b c
set pick [string cat [string map {H T T H} $b] $a $b]
}
set name "Robot"
if {[incr ::robots] > 1} {append name " #$::robots"}
puts "$name picks $pick"
next $name $pick
}
}
 
proc game {length args} {
puts "Let's play Penney's Game!"
 
# instantiate the players
set picks {}
set players {}
while {[llength $args]} {
set idx [expr {int(rand()*[llength $args])}]
set p [[lindex $args $idx] new $length {*}$picks]
set args [lreplace $args $idx $idx]
lappend players $p
lappend picks [$p pick]
}
 
# sanity check
if {[llength $picks] != [llength [lsort -unique $picks]]} {
puts "Two players picked the same thing; that's illegal"
}
 
# do the game loop
while 1 {
set coin [lindex {H T} [expr {int(rand()*2)}]]
puts "Coin flip [incr counter] is $coin"
foreach p $players {
if {[$p match $coin]} {
puts "[$p name] has won!"
return
}
}
}
}
 
game 3 HumanPlayer RobotPlayer
Sample Game:
Let's play Penney's Game!
What do you pick? (length 3): HTH
Robot picks HHT
Coin flip 1 is T
Coin flip 2 is H
Coin flip 3 is T
Coin flip 4 is T
Coin flip 5 is T
Coin flip 6 is H
Coin flip 7 is T
Coin flip 8 is T
Coin flip 9 is H
Coin flip 10 is T
Coin flip 11 is T
Coin flip 12 is T
Coin flip 13 is H
Coin flip 14 is T
Coin flip 15 is T
Coin flip 16 is H
Coin flip 17 is T
Coin flip 18 is T
Coin flip 19 is H
Coin flip 20 is T
Coin flip 21 is H
Human has won!

UNIX Shell[edit]

Works with: Bash
#!/bin/bash
main() {
echo "Penney's Game"
echo -n "Flipping to see who goes first ... "
 
if [[ $(flip) == H ]]; then
echo "I do."
p2=$(choose_sequence)
echo "I choose: $p2"
else
echo "You do."
fi
 
while true; do
echo "Enter your three-flip sequence:"
read p1
case "$p1" in
"$p2") echo "Sequence must be different from mine";;
[hHTt][hHtT][hHtT]) break;;
*) echo "Sequence must be three H's or T's";;
esac
done
p1=$(tr a-z A-Z <<<"$p1")
 
if [ -z "$p2" ]; then
p2=$(choose_sequence "$p1")
echo "I choose: $p2"
fi
 
echo
echo "Here we go. $p1, you win; $p2, I win."
flips=
 
while true; do
flip=$(flip)
echo -n $flip
flips+=$flip
while (( ${#flips} > 3 )); do
flips="${flips#?}"
done
case "$flips" in
*$p1) echo $'\nYou win!'; exit 0;;
*$p2) echo $'\nI win!'; exit 1;;
esac
done
}
 
choose_sequence() {
local result
if (( $# )); then
case "$1" in
 ?Hh?) result=T;;
*) result=H;;
esac
result+="${1%?}"
else
result=$(flip)$(flip)$(flip)
fi
echo "$result"
}
 
flip() {
if (( RANDOM % 2 )); then
echo H
else
echo T
fi
}
 
main "[email protected]"
Output:

PC first:

Penney's Game
Flipping to see who goes first ... I do.
I choose: HHT
Enter your three-flip sequence:
THH

Here we go.  THH, you win; HHT, I win.
THH
You win!

Human first:

penney
Penney's Game
Flipping to see who goes first ... You do.
Enter your three-flip sequence:
HTH
I choose: HHT

Here we go.  HTH, you win; HHT, I win.
HHHT
I win!

zkl[edit]

fcn coinToss{ (0).random(2) and "H" or "T" } // (0).random(2) --> 0<=r<2
reg myBet, yourBet;
if(coinToss()=="H"){ // The toss says I go first
myBet=(3).pump(String,coinToss);
println("I bet ",myBet);
yourBet=ask("Your bet of three (H/T): ")[0,3].toUpper();
}else{
yourBet=ask("Your bet of three (H/T): ")[0,3].toUpper();
myBet=((yourBet[1]=="H") and "T" or "H") + yourBet[0,2];
println("I bet ",myBet);
}
print("Flipping: "); coins:="";
while(1){
print(toss:=coinToss()); coins=coins + toss;
if(Void!=coins.find(yourBet)){ println(" You win!"); break; }
if(Void!=coins.find(myBet)) { println(" I win!"); break; }
// ignore we both won
}
Output:
$ zkl bbb
Your bet of three (H/T): tth
I bet HTT
Flipping: HHHHHHTHHTHHHTHTHHHTHTHTT I win!

$ zkl bbb
I bet THT
Your bet of three (H/T): hhh
Flipping: THHH You win!