Bagels
Description of the page content
Conversion of Bagels to several programming languages.
This program has been converted to 20 programming languages.
Original
Origin of bagels.bas:
By D. Resek, P. Rowe, 1978.
Creative Computing's BASIC Games.
- http://vintage-basic.net/games.html
- http://vintage-basic.net/bcg/bagels.bas
- http://www.atariarchives.org/basicgames/showpage.php?page=9
5 PRINT TAB(33);"BAGELS"
10 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY":PRINT:PRINT
15 REM *** BAGLES NUMBER GUESSING GAME
20 REM *** ORIGINAL SOURCE UNKNOWN BUT SUSPECTED TO BE
25 REM *** LAWRENCE HALL OF SCIENCE, U.C. BERKELY
30 DIM A1(6),A(3),B(3)
40 Y=0:T=255
50 PRINT:PRINT:PRINT
70 INPUT "WOULD YOU LIKE THE RULES (YES OR NO)";A$
90 IF LEFT$(A$,1)="N" THEN 150
100 PRINT:PRINT "I AM THINKING OF A THREE-DIGIT NUMBER. TRY TO GUESS"
110 PRINT "MY NUMBER AND I WILL GIVE YOU CLUES AS FOLLOWS:"
120 PRINT " PICO - ONE DIGIT CORRECT BUT IN THE WRONG POSITION"
130 PRINT " FERMI - ONE DIGIT CORRECT AND IN THE RIGHT POSITION"
140 PRINT " BAGELS - NO DIGITS CORRECT"
150 FOR I=1 TO 3
160 A(I)=INT(10*RND(1))
165 IF I-1=0 THEN 200
170 FOR J=1 TO I-1
180 IF A(I)=A(J) THEN 160
190 NEXT J
200 NEXT I
210 PRINT:PRINT "O.K. I HAVE A NUMBER IN MIND."
220 FOR I=1 TO 20
230 PRINT "GUESS #";I,
240 INPUT A$
245 IF LEN(A$)<>3 THEN 630
250 FOR Z=1 TO 3:A1(Z)=ASC(MID$(A$,Z,1)):NEXT Z
260 FOR J=1 TO 3
270 IF A1(J)<48 THEN 300
280 IF A1(J)>57 THEN 300
285 B(J)=A1(J)-48
290 NEXT J
295 GOTO 320
300 PRINT "WHAT?"
310 GOTO 230
320 IF B(1)=B(2) THEN 650
330 IF B(2)=B(3) THEN 650
340 IF B(3)=B(1) THEN 650
350 C=0:D=0
360 FOR J=1 TO 2
370 IF A(J)<>B(J+1) THEN 390
380 C=C+1
390 IF A(J+1)<>B(J) THEN 410
400 C=C+1
410 NEXT J
420 IF A(1)<>B(3) THEN 440
430 C=C+1
440 IF A(3)<>B(1) THEN 460
450 C=C+1
460 FOR J=1 TO 3
470 IF A(J)<>B(J) THEN 490
480 D=D+1
490 NEXT J
500 IF D=3 THEN 680
505 IF C=0 THEN 545
520 FOR J=1 TO C
530 PRINT "PICO ";
540 NEXT J
545 IF D=0 THEN 580
550 FOR J=1 TO D
560 PRINT "FERMI ";
570 NEXT J
580 IF C+D<>0 THEN 600
590 PRINT "BAGELS";
600 PRINT
605 NEXT I
610 PRINT "OH WELL."
615 PRINT "THAT'S TWNETY GUESSES. MY NUMBER WAS";100*A(1)+10*A(2)+A(3)
620 GOTO 700
630 PRINT "TRY GUESSING A THREE-DIGIT NUMBER.":GOTO 230
650 PRINT "OH, I FORGOT TO TELL YOU THAT THE NUMBER I HAVE IN MIND"
660 PRINT "HAS NO TWO DIGITS THE SAME.":GOTO 230
680 PRINT "YOU GOT IT!!!":PRINT
690 Y=Y+1
700 INPUT "PLAY AGAIN (YES OR NO)";A$
720 IF LEFT$(A$,1)="YES" THEN 150
730 IF Y=0 THEN 750
740 PRINT:PRINT "A";Y;"POINT BAGELS BUFF!!"
750 PRINT "HOPE YOU HAD FUN. BYE."
999 END
In Arturo
; Bagels
; Original version in BASIC:
; D. Resek, P. Rowe, 1978.
; Creative Computing's BASIC Games.
; - http://vintage-basic.net/games.html
; - http://vintage-basic.net/bcg/bagels.bas
; - http://www.atariarchives.org/basicgames/showpage.php?page=9
; This version in Arturo:
; Copyright (c) 2023, Marcos Cruz (programandala.net)
; SPDX-License-Identifier: Fair
;
; Written on 2023-10-19.
;
; Last modified: 20251205T0044+0100.
; Clear the screen, print the credits and wait for a keypress.
printCredits: function [] [
clear
print "Bagels"
print "Number guessing game\n"
print "Original source unknown but suspected to be:"
print " Lawrence Hall of Science, U.C. Berkely.\n"
print "Original version in BASIC:"
print " D. Resek, P. Rowe, 1978."
print " Creative computing (Morristown, New Jersey, USA), 1978.\n"
print "This version in Arturo:"
print " Copyright (c) 2023, Marcos Cruz (programandala.net)"
print " SPDX-License-Identifier: Fair\n"
input "Press Enter to read the instructions. "
]
; Clear the screen, print the instructions and wait for a keypress.
printInstructions: function [] [
clear
print "Bagels"
print "Number guessing game\n"
print "I am thinking of a three-digit number that has no two digits the same."
print "Try to guess it and I will give you clues as follows:\n"
print " PICO - one digit correct but in the wrong position"
print " FERMI - one digit correct and in the right position"
print " BAGELS - no digits correct\n"
input "Press Enter to start. "
]
DIGITS: 3
randomDigit: array [0 0 0]
; Return an integer array with random digits.
randomNumber: function [] [
number: array []
while [ less? size number DIGITS ] [
digit: random 0 9
if not? contains? number digit [
append 'number digit
]
]
number
]
; Print the given prompt and get a three-digit number from the user.
userInput: function [prompt] [
userDigit: array []
while [ less? size userDigit DIGITS ] [
inputString: input prompt
if? less? size inputString DIGITS [
print ~"Remember it's a |DIGITS|-digit number."
] else [
empty 'userDigit
loop inputString 'char [
if? contains? "0123456789" char [
digit: to :integer to :string char
if? contains? userDigit digit [
print "Remember my number has no two digits the same."
break
] else [
append 'userDigit digit
]
] else [
print "What?"
break
]
]
]
]
userDigit
]
; Return `true` if the given string is "yes" or a synonym.
isYes: function [answer] [
contains? ["ok", "yeah", "yes", "y"] answer
]
; Return `true` if the given string is "no" or a synonym.
isNo: function [answer] [
contains? ["no", "nope", "n"] answer
]
; Print the given prompt, wait until the user enters a valid yes/no
; string, and return `true` for "yes" or `false` for "no".
yes: function [prompt] [
answer: ""
while [ not? or? isYes answer isNo answer ] [ answer: input prompt ]
isYes answer
]
; Init and run the game loop.
play: function [] [
maxTries: 20
score: 0
while [ true ] [
clear
computerNumber: randomNumber
print "O.K. I have a number in mind."
loop range 1 maxTries [ 'guess ] [
userNumber: userInput(~"Guess #|pad .with:`0` to :string guess 2 |: ")
fermi: 0
pico: 0
loop range 0 sub DIGITS 1 [ 'i ] [
loop range 0 sub DIGITS 1 [ 'j ] [
if equal? userNumber\[i] computerNumber\[j] [
if? equal? i j [ add 'fermi 1 ]
else [ add 'pico 1 ]
]
]
]
prints repeat "PICO " pico
prints repeat "FERMI " fermi
if equal? add pico fermi 0 [ prints "BAGELS" ]
print ""
if equal? fermi DIGITS [ break ]
]
if? equal? fermi DIGITS [
print "You got it!!!"
inc score
] else [
print "Oh well."
prints ~"That's |maxTries| guesses. My number was "
loop range 0 sub DIGITS 1 [ 'i ] [ prints computerNumber\[i] ]
print "."
]
if not? yes("Play again? ") [ break ]
]
if notEqual? score 0 [
print ~"A |score|-point bagels, buff!!"
]
print "Hope you had fun. Bye."
]
printCredits
printInstructions
play
In C#
// Bagels
// Original version in BASIC:
// By D. Resek, P. Rowe, 1978.
// Creative Computing's BASIC Games.
// - http://vintage-basic.net/games.html
// - http://vintage-basic.net/bcg/bagels.bas
// - http://www.atariarchives.org/basicgames/showpage.php?page=9
// This version in C#:
// Copyright (c) 2024, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2024-12-25.
//
// Last modified: 20251205T1530+0100.
using System;
using System.Linq;
class bagels
{
// Clear the screen, display the credits and wait for a keypress.
//
static void PrintCredits()
{
Console.Clear();
Console.WriteLine("Bagels");
Console.WriteLine("Number guessing game\n");
Console.WriteLine("Original source unknown but suspected to be:");
Console.WriteLine(" Lawrence Hall of Science, U.C. Berkely.\n");
Console.WriteLine("Original version in BASIC:");
Console.WriteLine(" D. Resek, P. Rowe, 1978.");
Console.WriteLine(" Creative computing (Morristown, New Jersey, USA), 1978.\n");
Console.WriteLine("This version in C#:");
Console.WriteLine(" Copyright (c) 2024, Marcos Cruz (programandala.net)");
Console.WriteLine(" SPDX-License-Identifier: Fair\n");
Console.Write("Press Enter to read the instructions. ");
Console.ReadKey();
}
// Clear the screen, print the instructions and wait for a keypress.
//
static void PrintInstructions()
{
Console.Clear();
Console.WriteLine("Bagels");
Console.WriteLine("Number guessing game\n");
Console.WriteLine("I am thinking of a three-digit number that has no two digits the same.");
Console.WriteLine("Try to guess it and I will give you clues as follows:\n");
Console.WriteLine(" PICO - one digit correct but in the wrong position");
Console.WriteLine(" FERMI - one digit correct and in the right position");
Console.WriteLine(" BAGELS - no digits correct");
Console.Write("\nPress Enter to start. ");
Console.ReadKey();
}
const int DIGITS = 3;
static int[] randomDigit = new int[DIGITS];
// Return three random digits.
//
static int[] RandomDigits()
{
Random rand = new Random();
for (int i = 0; i < DIGITS; i++)
{
while (true)
{
digitLoop:
randomDigit[i] = rand.Next(10);
for (int j = 0; j < i; j++)
{
if (i != j && randomDigit[i] == randomDigit[j])
{
goto digitLoop;
}
}
break;
}
}
return randomDigit;
}
// Return `true` if any of the elements of the given array, which contains
// only numbers in inclusive range 0..9, is repeated; otherwise return
// `false`.
//
static bool IsAnyRepeated(int[] num)
{
bool[] present = new bool[10];
foreach (int n in num)
{
if (present[n])
return true;
else
present[n] = true;
}
return false;
}
// Print the given prompt and update the array whose address is given with a
// three-digit number from the user.
//
static void GetInput(string prompt, ref int[] userDigit)
{
// XXX TODO Create a local array, appending every digit after checking
// the contents, making `IsAnyRepeated` unnecessary.
while (true)
{
getLoop:
Console.Write(prompt);
string input = Console.ReadLine();
if (input.Length != DIGITS)
{
Console.WriteLine($"Remember it's a {DIGITS}-digit number.");
continue;
}
char digit;
for (int i = 0; i < input.Length; i++)
{
digit = input[i];
if (Char.IsDigit(digit))
{
userDigit[i] = ((int) digit) - ((int) '0');
}
else
{
Console.WriteLine("What?");
goto getLoop;
}
}
if (IsAnyRepeated(userDigit))
{
Console.WriteLine("Remember my number has no two digits the same.");
continue;
}
break;
}
}
// Return `true` if the given string is "yes" or a synonym.
//
static bool IsYes(string s)
{
string[] validOptions = {"ok", "y", "yeah", "yes"};
return validOptions.Contains(s.ToLower());
}
// Return `true` if the given string is "no" or a synonym.
//
static bool IsNo(string s)
{
string[] validOptions = {"n", "no", "nope"};
return validOptions.Contains(s.ToLower());
}
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
//
static bool Yes(string prompt)
{
while (true)
{
Console.Write(prompt);
string answer = Console.ReadLine();
if (IsYes(answer))
{
return true;
}
if (IsNo(answer))
{
return false;
}
}
}
static void Play()
{
const int TRIES = 20;
int score = 0;
int fermi = 0; // counter
int pico = 0; // counter
int[] userNumber = new int[DIGITS];
while (true)
{
Console.Clear();
int[] computerNumber = RandomDigits();
Console.WriteLine("O.K. I have a number in mind.");
for (int guess = 1; guess <= TRIES; guess++)
{
GetInput($"Guess #{guess}: ", ref userNumber);
fermi = 0;
pico = 0;
for (int i = 0; i < DIGITS; i++)
{
for (int j = 0; j < DIGITS; j++)
{
if (userNumber[i] == computerNumber[j])
{
if (i == j)
{
fermi += 1;
}
else
{
pico += 1;
}
}
}
}
for (int i = 0; i < pico; i++)
Console.Write("PICO ");
for (int i = 0; i < fermi; i++)
Console.Write("FERMI ");
if (pico + fermi == 0)
Console.Write("BAGELS");
Console.WriteLine();
if (fermi == DIGITS)
{
break;
}
}
if (fermi == DIGITS)
{
Console.WriteLine("You got it!!!");
score += 1;
}
else
{
Console.WriteLine("Oh well.");
Console.Write($"That's {TRIES} guesses. My number was ");
for (int i = 0; i < DIGITS; i++)
{
Console.Write(computerNumber[i]);
}
Console.WriteLine(".");
}
if (!Yes("Play again? "))
{
break;
}
}
if (score != 0)
{
Console.WriteLine($"A {score}-point bagels, buff!!");
}
Console.WriteLine("Hope you had fun. Bye.");
}
static void Main()
{
PrintCredits();
PrintInstructions();
Play();
}
}
In Chapel
// Bagels
// Original version in BASIC:
// D. Resek, P. Rowe, 1978.
// Creative Computing (Morristown, New Jersey, USA), 1978.
// This version in Chapel:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2025-04-06.
//
// Last modified: 20250406T1921+0200.
// Modules {{{1
// =============================================================================
import IO;
import Random;
// Terminal {{{1
// =============================================================================
const NORMAL_STYLE = 0;
proc moveCursorHome() {
write("\x1B[H");
}
proc setStyle(style: int) {
writef("\x1B[%im", style);
}
proc resetAttributes() {
setStyle(NORMAL_STYLE);
}
proc eraseScreen() {
write("\x1B[2J");
}
proc clearScreen() {
eraseScreen();
resetAttributes();
moveCursorHome();
}
// User input {{{1
// =============================================================================
proc acceptString(prompt: string): string {
write(prompt);
IO.stdout.flush();
return IO.readLine().strip();
}
// Return `true` if the given string is "yes" or a synonym.
//
proc isYes(s: string): bool {
select s.toLower() {
when "ok", "y", "yeah", "yes" do return true;
otherwise do return false;
}
}
// Return `true` if the given string is "no" or a synonym.
//
proc isNo(s: string): bool {
select s.toLower() {
when "n", "no", "nope" do return true;
otherwise do return false;
}
}
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
//
proc yes(prompt: string): bool {
var result: bool;
while true {
var answer: string = acceptString(prompt);
if isYes(answer) {
result = true;
break;
} else if isNo(answer) {
result = false;
break;
}
}
return result;
}
// Credits and instructions {{{1
// =============================================================================
// Clear the screen, display the credits and wait for a keypress.
//
proc printCredits() {
clearScreen();
writeln("Bagels");
writeln("Number guessing game\n");
writeln("Original source unknown but suspected to be:");
writeln(" Lawrence Hall of Science, U.C. Berkely.\n");
writeln("Original version in BASIC:");
writeln(" D. Resek, P. Rowe, 1978.");
writeln(" Creative computing (Morristown, New Jersey, USA), 1978.\n");
writeln("This version in Chapel:");
writeln(" Copyright (c) 2025, Marcos Cruz (programandala.net)");
writeln(" SPDX-License-Identifier: Fair\n");
acceptString("Press Enter to read the instructions. ");
}
// Clear the screen, print the instructions and wait for a keypress.
//
proc printInstructions() {
clearScreen();
writeln("Bagels");
writeln("Number guessing game\n");
writeln("I am thinking of a three-digit number that has no two digits the same.");
writeln("Try to guess it and I will give you clues as follows:\n");
writeln(" PICO - one digit correct but in the wrong position");
writeln(" FERMI - one digit correct and in the right position");
writeln(" BAGELS - no digits correct\n");
acceptString("Press Enter to start. ");
}
// Main {{{1
// =============================================================================
const DIGITS = 3;
// Print the given prompt and return an array with a three-digit number type by
// the user.
//
proc getInput(prompt: string): [0 ..< DIGITS] int {
var userDigit: [0 ..< DIGITS] int;
const ASCII_0 = '0';
label getLoop while true {
var input: string = acceptString(prompt);
if input.size != DIGITS {
writef("Remember it's a %i-digit number.\n", DIGITS);
continue getLoop;
}
for pos in 0 ..< input.size {
var digit: string = input[pos];
if input[pos].isDigit() {
userDigit[pos] = digit: int;
} else {
writeln("What?");
continue getLoop;
}
}
if isAnyRepeated(userDigit) {
writeln("Remember my number has no two digits the same.");
continue getLoop;
}
break;
}
return userDigit;
}
// Return three random digits.
//
proc randomNumber(): [0 ..< DIGITS] int {
var rsInt = new Random.randomStream(int);
var randomDigit: [0 ..< DIGITS] int;
for i in 0 ..< DIGITS {
label digitLoop while true {
randomDigit[i] = rsInt.next(0, 10 - 1);
for j in 0 ..< i {
if i != j && randomDigit[i] == randomDigit[j] {
continue digitLoop;
}
}
break;
}
}
return randomDigit;
}
// Return `true` if any of the given numbers is repeated; otherwise return
// `false`.
//
proc isAnyRepeated(numbers: [] int): bool {
for i0 in 0 ..< numbers.size {
for i1 in i0 + 1 ..< numbers.size {
if numbers[i0] == numbers[i1] {
return true;
}
}
}
return false;
}
// Init and run the game loop.
//
proc play() {
const TRIES = 20;
var score: int = 0;
var fermi: int = 0; // counter
var pico: int = 0; // counter
var computerNumber: [0 ..< DIGITS] int;
var userNumber: [0 ..< DIGITS] int;
while true {
clearScreen();
computerNumber = randomNumber();
writeln("O.K. I have a number in mind.");
for guess in 1 ..< TRIES + 1 {
//userNumber = getInput("Guess #%02i: ".format(guess)); // XXX TODO
userNumber = getInput("Guess #" + guess: string + ": "); // XXX TMP
fermi = 0;
pico = 0;
for i in 0 ..< DIGITS {
for j in 0 ..< DIGITS {
if userNumber[i] == computerNumber[j] {
if i == j {
fermi += 1;
} else {
pico += 1;
}
}
}
}
if pico + fermi == 0 {
writeln("BAGELS");
} else {
writeln( "PICO " * pico, "FERMI " * fermi);
if fermi == DIGITS {
break;
}
}
}
if fermi == DIGITS {
writeln("You got it!!!");
score += 1;
} else {
writeln("Oh well.");
writef("That's %i guesses. My number was ", TRIES);
for i in 0 ..< DIGITS {
write(computerNumber[i]);
}
writeln(".");
}
if !yes("Play again? ") {
break;
}
}
if score != 0 {
writef("A %i-point bagels, buff!!\n", score);
}
writeln("Hope you had fun. Bye.");
}
proc main() {
printCredits();
printInstructions();
play();
}
In Crystal
# Bagels
# Original version in BASIC:
# D. Resek, P. Rowe, 1978.
# Creative Computing (Morristown, New Jersey, USA), 1978.
# This version in Crystal:
# Copyright (c) 2023, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written in 2023-04, 2023-09, 2023-10.
#
# Last modified: 20250513T0043+0200.
# Moves the cursor to the home position.
def home
print "\e[H"
end
# Clears the screen and moves the cursor to the home position.
def clear
print "\e[2J"
home
end
# Prompts the user to enter a command and returns it.
def command(prompt = "> ") : String
s = nil
while s.is_a?(Nil)
print prompt
s = gets
end
s
end
# Prints the given prompt and waits until the user enters an empty string.
def press_enter(prompt : String)
until command(prompt) == ""
end
end
# Returns `true` if the given string is "yes" or a synonym.
def is_yes?(answer : String) : Bool
["ok", "yeah", "yes", "y"].any? { |yes| answer.downcase == yes }
end
# Returns `true` if the given string is "no" or a synonym.
def is_no?(answer : String) : Bool
["no", "nope", "n"].any? { |no| answer.downcase == no }
end
# Prints the given prompt, waits until the user enters a valid yes/no
# string, and returns `true` for "yes" or `false` for "no".
def yes?(prompt : String) : Bool
answer = ""
while !(is_yes?(answer) || is_no?(answer))
answer = command(prompt)
end
is_yes?(answer)
end
# Clears the screen, displays the credits and waits for a keypress.
def print_credits
clear
puts "Bagels"
puts "Number guessing game\n"
puts "Original source unknown but suspected to be:"
puts " Lawrence Hall of Science, U.C. Berkely.\n"
puts "Original version in BASIC:"
puts " D. Resek, P. Rowe, 1978."
puts " Creative computing (Morristown, New Jersey, USA), 1978.\n"
puts "This version in Crystal:"
puts " Copyright (c) 2023, Marcos Cruz (programandala.net)"
puts " SPDX-License-Identifier: Fair\n"
press_enter "Press Enter to read the instructions. "
end
# Clears the screen, prints the instructions and waits for a keypress.
def print_instructions
clear
puts "Bagels"
puts "Number guessing game\n"
puts "I am thinking of a three-digit number that has no two digits the same."
puts "Try to guess it and I will give you clues as follows:\n"
puts " PICO - one digit correct but in the wrong position"
puts " FERMI - one digit correct and in the right position"
puts " BAGELS - no digits correct"
press_enter "\nPress Enter to start. "
end
DIGITS = 3
TRIES = 20
# Returns three random digits.
def random : {Int32, Int32, Int32}
d = [] of Int32
while d.size < DIGITS
digit = rand(10)
while digit.in?(d)
digit = rand(10)
end
d << digit
end
{d[0], d[1], d[2]}
end
def other_than_digits?(text : String) : Bool
text.each_char do |char|
if !char.number?
return true
end
end
false
end
# Prints the given prompt and gets a three-digit number from the user.
def input(prompt : String) : {Int32, Int32, Int32}
user_digit = [] of Int32 # digit value
while true
input = command(prompt)
if input.size != DIGITS
puts "Remember it's a #{DIGITS}-digit number."
next
elsif other_than_digits?(input)
puts "What?"
next
end
user_digit.clear
input.each_char do |c|
user_digit << c.to_i
end
if user_digit.uniq.size != user_digit.size
puts "Remember my number has no two digits the same."
next
end
break
end
{user_digit[0], user_digit[1], user_digit[2]}
end
# Inits and runs the game loop.
def play
computer_number = [DIGITS] of Int32 # random number
user_number = [DIGITS] of Int32 # user guess
DIGITS.times do
computer_number << 0
user_number << 0
end
score = 0
fermi = 0 # counter
pico = 0 # counter
while true # game loop
clear
computer_number[0], computer_number[1], computer_number[2] = random
puts "O.K. I have a number in mind."
(0...TRIES).each do |guess|
user_number[0], user_number[1], user_number[2] = input("Guess ##{guess.to_s.rjust(2, '0')}: ")
fermi = 0
pico = 0
(0...DIGITS).each do |i|
(0...DIGITS).each do |j|
if computer_number[i] == user_number[j]
if i == j
fermi += 1
else
pico += 1
end
end
end
end
if pico + fermi == 0
print "BAGELS"
else
print "PICO " * pico
print "FERMI " * fermi
end
puts
if fermi == DIGITS
break
end
end # tries loop
if fermi == DIGITS
puts "You got it!!!"
score += 1
else
puts "Oh well."
print "That's #{TRIES} guesses. My number was "
print 100 * computer_number[0] + 10 * computer_number[1] + computer_number[2], "\n"
end
if !yes?("Play again? ")
break
end
end # game loop
if score != 0
puts "A #{score}-point bagels, buff!!"
end
puts "Hope you had fun. Bye."
end
print_credits
print_instructions
play
In D
// Bagels
// Original version in BASIC:
// D. Resek, P. Rowe, 1978.
// Creative Computing (Morristown, New Jersey, USA), 1978.
// This version in D:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2025-03-24.
//
// Last modified: 20251220T0636+0100.
module bagels;
// Terminal {{{1
// =============================================================================
enum NORMAL_STYLE = 0;
void moveCursorHome()
{
import std.stdio : write;
write("\x1B[H");
}
void setStyle(int style)
{
import std.stdio : writef;
writef("\x1B[%dm", style);
}
void resetAttributes()
{
setStyle(NORMAL_STYLE);
}
void eraseScreen()
{
import std.stdio : write;
write("\x1B[2J");
}
void clearScreen()
{
eraseScreen();
resetAttributes();
moveCursorHome();
}
// Credits and instructions {{{1
// =============================================================================
// Clear the screen, display the credits and wait for a keypress.
//
void printCredits()
{
import std.stdio : writeln;
clearScreen();
writeln("Bagels");
writeln("Number guessing game\n");
writeln("Original source unknown but suspected to be:");
writeln(" Lawrence Hall of Science, U.C. Berkely.\n");
writeln("Original version in BASIC:");
writeln(" D. Resek, P. Rowe, 1978.");
writeln(" Creative computing (Morristown, New Jersey, USA), 1978.\n");
writeln("This version in D:");
writeln(" Copyright (c) 2025, Marcos Cruz (programandala.net)");
writeln(" SPDX-License-Identifier: Fair\n");
acceptString("Press Enter to read the instructions. ");
}
// Clear the screen, print the instructions and wait for a keypress.
//
void printInstructions()
{
import std.stdio : writeln;
clearScreen();
writeln("Bagels");
writeln("Number guessing game\n");
writeln("I am thinking of a three-digit number that has no two digits the same.");
writeln("Try to guess it and I will give you clues as follows:\n");
writeln(" PICO - one digit correct but in the wrong position");
writeln(" FERMI - one digit correct and in the right position");
writeln(" BAGELS - no digits correct\n");
acceptString("Press Enter to start. ");
}
// User input {{{1
// =============================================================================
string acceptString(string prompt)
{
import std.stdio : readln;
import std.stdio : write;
import std.string : strip;
write(prompt);
return strip(readln());
}
// Return `true` if the given string is "yes" or a synonym.
//
bool isYes(string s)
{
import std.uni : toLower;
switch (toLower(s))
{
case "ok":
case "y":
case "yeah":
case "yes":
return true;
default:
return false;
}
}
// Return `true` if the given string is "no" or a synonym.
//
bool isNo(string s)
{
import std.uni : toLower;
switch (toLower(s))
{
case "n":
case "no":
case "nope":
return true;
default:
return false;
}
}
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
//
bool yes(string prompt)
{
while (true)
{
string answer = acceptString(prompt);
if (isYes(answer))
{
return true;
}
if (isNo(answer))
{
return false;
}
}
}
// Main {{{1
// =============================================================================
enum DIGITS = 3;
bool isDigit(int asciiCode)
{
return (asciiCode >= '0') && (asciiCode <= '9');
}
// Print the given prompt and return an array with a three-digit number typed
// by the user.
int[DIGITS] getInput(string prompt)
{
import std.stdio : writefln;
import std.stdio : writeln;
enum char ASCII_0 = '0';
int[DIGITS] userDigit;
getLoop: while (true)
{
string input = acceptString(prompt);
if (input.length != DIGITS)
{
writefln("Remember it's a %d-digit number.", DIGITS);
continue getLoop;
}
foreach (int pos; 0 .. cast(int)input.length)
{
int digit = input[pos];
if (isDigit(digit))
{
userDigit[pos] = digit - ASCII_0;
}
else
{
writeln("What?");
continue getLoop;
}
}
if (isAnyRepeated(userDigit))
{
writeln("Remember my number has no two digits the same.");
continue getLoop;
}
break;
}
return userDigit;
}
// Return three random digits.
int[DIGITS] randomNumber()
{
import std.random : uniform;
int[DIGITS] randomDigit;
foreach (int i; 0 .. DIGITS)
{
digitLoop: while (true)
{
randomDigit[i] = uniform(0, 10);
foreach (int j; 0 .. i)
{
if (i != j && randomDigit[i] == randomDigit[j])
{
continue digitLoop;
}
}
break;
}
}
return randomDigit;
}
// Return `true` if any of the given numbers is repeated; otherwise return
// `false`.
bool isAnyRepeated(int[] numbers)
{
import std.algorithm.comparison : equal;
import std.algorithm.iteration : uniq;
auto filteredNumbers = uniq(numbers);
return !equal(filteredNumbers, numbers);
}
// Init and run the game loop.
void play()
{
import std.array : replicate;
import std.format : format;
import std.stdio : write;
import std.stdio : writef;
import std.stdio : writefln;
import std.stdio : writeln;
enum TRIES = 20;
int score = 0;
int fermi = 0; // counter
int pico = 0; // counter
int[DIGITS] computerNumber;
int[DIGITS] userNumber;
while (true)
{
clearScreen();
computerNumber = randomNumber();
writeln("O.K. I have a number in mind.");
foreach (int guess; 1 .. TRIES + 1)
{
userNumber = getInput(format("Guess #%02d: ", guess));
fermi = 0;
pico = 0;
foreach (int i; 0 .. DIGITS)
{
foreach (int j; 0 .. DIGITS)
{
if (userNumber[i] == computerNumber[j])
{
if (i == j)
{
fermi += 1;
}
else
{
pico += 1;
}
}
}
}
if (pico + fermi == 0)
{
writeln("BAGELS");
}
else
{
writeln(
replicate("PICO ", pico),
replicate("FERMI ", fermi)
);
if (fermi == DIGITS)
{
break;
}
}
}
if (fermi == DIGITS)
{
writeln("You got it!!!");
score += 1;
}
else
{
writeln("Oh well.");
writef("That's %d guesses. My number was ", TRIES);
foreach (int i; 0 .. DIGITS)
{
write(computerNumber[i]);
}
writeln(".");
}
if (!yes("Play again? "))
{
break;
}
}
if (score != 0)
{
writefln("A %d-point bagels, buff!!", score);
}
writeln("Hope you had fun. Bye.");
}
void main()
{
printCredits();
printInstructions();
play();
}
In FreeBASIC
/'
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in FreeBASIC:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2025-05-09.
Last modified: 20250509T1728+0200.
'/
sub press_enter(prompt as string)
print prompt;
sleep
do while inkey <> ""
loop
end sub
sub print_credits()
cls
print "Bagels"
print !"Number guessing game\n"
print "Original source unknown but suspected to be:"
print !" Lawrence Hall of Science, U.C. Berkely.\n"
print "Original version in BASIC:"
print " D. Resek, P. Rowe, 1978."
print !" Creative computing (Morristown, New Jersey, USA), 1978.\n"
print "This version in FreeBASIC:"
print " Copyright (c) 2025, Marcos Cruz (programandala.net)"
print !" SPDX-License-Identifier: Fair\n"
press_enter("Press Enter to read the instructions. ")
end sub
sub print_instructions()
cls
print "Bagels"
print !"Number guessing game\n"
print "I am thinking of a three-digit number that has no two digits the same."
print !"Try to guess it and I will give you clues as follows:\n"
print " PICO - one digit correct but in the wrong position"
print " FERMI - one digit correct and in the right position"
print " BAGELS - no digits correct"
press_enter(!"\nPress Enter to start. ")
end sub
const NUMBER_OF_DIGITS = 3
const FIRST_DIGIT_INDEX = 0
const LAST_DIGIT_INDEX = NUMBER_OF_DIGITS - 1
sub fill_with_random_digits(d() as integer)
for i as integer = lbound(d) to ubound(d)
do while true
d(i) = int(rnd * 10)
for j as integer = 0 to i - 1
if i <> j and d(i) = d(j) then
goto choose_again
end if
next
exit do
choose_again:
loop
next
end sub
' Return `true` if any of the given numbers is repeated; otherwise return
' `false`.
'
function is_any_repeated(n() as integer) as boolean
for i0 as integer = lbound(n) to ubound(n)
for i1 as integer = i0 + 1 to ubound(n)
if n(i0) = n(i1) then
return true
end if
next
next
return false
end function
' Print the given prompt and update the given array with a three-digit number
' from the user.
'
sub get_input(prompt as string, user_digit() as integer)
' XXX TODO Create a local array, appending every digit after checking the contents,
' making `is_any_repeated` unnecessary.
do while true
get_loop:
dim user_input as string
print prompt;
line input user_input
if len(user_input) <> NUMBER_OF_DIGITS then
print "Remember it's a " & NUMBER_OF_DIGITS & "-digit number."
goto get_loop
end if
for i as integer = 1 to len(user_input)
dim digit as string = mid(user_input, i, 1)
if instr("0123456789", digit) > 0 then
user_digit(i - 1) = valint(digit)
else
print "What?"
goto get_loop
end if
next
if is_any_repeated(user_digit()) then
print "Remember my number has no two digits the same."
else
exit do
end if
loop
end sub
' Return `true` if the given string is "yes" or a synonym.
'
function is_yes(s as string) as boolean
select case lcase(s)
case "ok", "y", "yeah", "yes"
return true
case else
return false
end select
end function
' Return `true` if the given string is "no" or a synonym.
'
function is_no(s as string) as boolean
select case lcase(s)
case "n", "no", "nope"
return true
case else
return false
end select
end function
' Print the given prompt, wait until the user enters a valid yes/no string,
' and return `true` for "yes" or `false` for "no".
'
function yes(prompt as string) as boolean
do while true
dim answer as string
line input prompt, answer
if is_yes(answer) then
return true
end if
if is_no(answer) then
return false
end if
loop
end function
' Init and run the game loop.
'
sub play()
randomize
const TRIES = 20
var score = 0
dim fermi as integer ' counter
dim pico as integer ' counter
dim user_number(FIRST_DIGIT_INDEX to LAST_DIGIT_INDEX) as integer
do while true
cls
dim computer_number(FIRST_DIGIT_INDEX to LAST_DIGIT_INDEX) as integer
fill_with_random_digits(computer_number())
print "O.K. I have a number in mind."
for guess as integer = 1 to TRIES
' XXX TMP
/'
print "My number: "
for i as integer = FIRST_DIGIT_INDEX to LAST_DIGIT_INDEX
print computer_number(i);
next
print
'/
get_input("Guess #" & guess & ": ", user_number())
fermi = 0
pico = 0
for i as integer = FIRST_DIGIT_INDEX to LAST_DIGIT_INDEX
for j as integer = FIRST_DIGIT_INDEX to LAST_DIGIT_INDEX
if user_number(i) = computer_number(j) then
if i = j then
fermi += 1
else
pico += 1
end if
end if
next
next
if pico + fermi = 0 then
print "BAGELS"
else
for i as integer = 1 to pico
print "PICO ";
next
for i as integer = 1 to fermi
print "FERMI ";
next
print
end if
if fermi = NUMBER_OF_DIGITS then
exit for
end if
next
if fermi = NUMBER_OF_DIGITS then
print "You got it!!!"
score += 1
else
print "Oh well."
print "That's " & TRIES & " guesses. My number was "
for i as integer = FIRST_DIGIT_INDEX to LAST_DIGIT_INDEX
print computer_number(i);
next
print "."
end if
if not yes("Play again? ") then
exit do
end if
loop
if score <> 0 then
print "A " & score & "-point bagels, buff!!"
end if
print "Hope you had fun. Bye."
end sub
print_credits()
print_instructions()
play()
' vim: filetype=freebasic
In Go
/*
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Go:
Copyright (c) 2024, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2024-12-29
Last modified: 20250108T1445+0100.
*/
package main
import "fmt"
import "math/rand"
import "strings"
import "time"
import "unicode"
func clearScreen() {
fmt.Print("\x1B[0;0H\x1B[2J")
}
func input(prompt string) string {
fmt.Print(prompt)
var s = ""
fmt.Scanf("%s", &s)
return s
}
// Clear the screen, display the credits and wait for a keypress.
func printCredits() {
clearScreen()
fmt.Println("Bagels")
fmt.Println("Number guessing game\n")
fmt.Println("Original source unknown but suspected to be:")
fmt.Println(" Lawrence Hall of Science, U.C. Berkely.\n")
fmt.Println("Original version in BASIC:")
fmt.Println(" D. Resek, P. Rowe, 1978.")
fmt.Println(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
fmt.Println("This version in Go:")
fmt.Println(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
fmt.Println(" SPDX-License-Identifier: Fair\n")
input("Press Enter to read the instructions. ")
}
// Clear the screen, print the instructions and wait for a keypress.
func printInstructions() {
clearScreen()
fmt.Println("Bagels")
fmt.Println("Number guessing game\n")
fmt.Println("I am thinking of a three-digit number that has no two digits the same.")
fmt.Println("Try to guess it and I will give you clues as follows:\n")
fmt.Println(" PICO - one digit correct but in the wrong position")
fmt.Println(" FERMI - one digit correct and in the right position")
fmt.Println(" BAGELS - no digits correct")
input("\nPress Enter to start. ")
}
const DIGITS int = 3
var randomDigit [DIGITS]int
// Return three random digits.
func random() []int {
for i := 0; i < DIGITS; i++ {
digitLoop:
for {
randomDigit[i] = rand.Intn(10)
for j := 0; j < i; j++ {
if i != j && randomDigit[i] == randomDigit[j] {
continue digitLoop
}
}
break
}
}
return randomDigit[:]
}
// Return `true` if any of the given numbers is repeated; otherwise return
// `false`.
func isAnyRepeated(num []int) bool {
for i0, n0 := range num[:] {
for _, n1 := range num[i0+1:] {
if n0 == n1 {
return true
}
}
}
return false
}
// Print the given prompt and update the array whose address is given with a
// three-digit number from the user.
func getInput(prompt string, userDigit *[DIGITS]int) {
const ASCII_0 int = 48
getLoop:
for {
var input string = input(prompt)
if len(input) != DIGITS {
fmt.Printf("Remember it's a %v-digit number.\n", DIGITS)
continue getLoop
}
for pos, digit := range input {
if unicode.IsDigit(digit) {
// XXX TODO simplify
userDigit[pos] = int(digit) - ASCII_0
} else {
fmt.Println("What?")
continue getLoop
}
}
if isAnyRepeated(userDigit[:]) {
fmt.Println("Remember my number has no two digits the same.")
continue getLoop
}
break
}
}
// Return `true` if the given string is "yes" or a synonym.
func isYes(s string) bool {
s = strings.ToLower(s)
for _, valid := range []string{"ok", "y", "yeah", "yes"} {
if s == valid {
return true
}
}
return false
}
// Return `true` if the given string is "no" or a synonym.
func isNo(s string) bool {
s = strings.ToLower(s)
for _, valid := range []string{"n", "no", "nope"} {
if s == valid {
return true
}
}
return false
}
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
func yes(prompt string) bool {
for {
var answer = input(prompt)
if isYes(answer) {
return true
}
if isNo(answer) {
return false
}
}
}
// Init and run the game loop.
func play() {
rand.Seed(time.Now().UTC().UnixNano())
const TRIES int = 20
var score int
var fermi int // counter
var pico int // counter
var userNumber [DIGITS]int
for {
clearScreen()
var computerNumber = random()
fmt.Println("O.K. I have a number in mind.")
for guess := 1; guess <= TRIES; guess++ {
//fmt.Printf("My number: %v\n", computerNumber) // XXX TMP
getInput(fmt.Sprintf("Guess #%2v: ", guess), &userNumber)
fermi = 0
pico = 0
for i := 0; i < DIGITS; i++ {
for j := 0; j < DIGITS; j++ {
if userNumber[i] == computerNumber[j] {
if i == j {
fermi += 1
} else {
pico += 1
}
}
}
}
var picos = strings.Repeat("PICO ", pico)
var fermis = strings.Repeat("FERMI ", fermi)
fmt.Print(picos)
fmt.Print(fermis)
if pico+fermi == 0 {
fmt.Print("BAGELS")
}
fmt.Println()
if fermi == DIGITS {
break
}
}
if fermi == DIGITS {
fmt.Println("You got it!!!")
score += 1
} else {
fmt.Println("Oh well.")
fmt.Printf("That's %v guesses. My number was ", TRIES)
for i := 0; i < DIGITS; i++ {
fmt.Print(computerNumber[i])
}
fmt.Println(".")
}
if !yes("Play again? ") {
break
}
}
if score != 0 {
fmt.Printf("A %v-point bagels, buff!!\n", score)
}
fmt.Println("Hope you had fun. Bye.")
}
func main() {
printCredits()
printInstructions()
play()
}
In Hare
// Bagels
//
// Original version in BASIC:
// D. Resek, P. Rowe, 1978.
// Creative Computing (Morristown, New Jersey, USA), 1978.
//
// This version in Hare:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written in 2025-02-14/15.
//
// Last modified: 20260213T1645+0100.
// Modules {{{1
// =============================================================================
use ascii;
use bufio;
use fmt;
use math::random;
use os;
use strings;
use time;
// Terminal {{{1
// =============================================================================
def NORMAL_STYLE = 0;
fn move_cursor_home() void = {
fmt::print("\x1B[H")!;
};
fn set_style(style: int) void = {
fmt::printf("\x1B[{}m", style)!;
};
fn reset_attributes() void = {
set_style(NORMAL_STYLE);
};
fn erase_screen() void = {
fmt::print("\x1B[2J")!;
};
fn clear_screen() void = {
erase_screen();
reset_attributes();
move_cursor_home();
};
// Credits and instructions {{{1
// =============================================================================
// Clear the screen, display the credits and wait for a keypress.
//
fn print_credits() void = {
clear_screen();
fmt::println("Bagels")!;
fmt::println("Number guessing game\n")!;
fmt::println("Original source unknown but suspected to be:")!;
fmt::println(" Lawrence Hall of Science, U.C. Berkely.\n")!;
fmt::println("Original version in BASIC:")!;
fmt::println(" D. Resek, P. Rowe, 1978.")!;
fmt::println(" Creative computing (Morristown, New Jersey, USA), 1978.\n")!;
fmt::println("This version in Hare:")!;
fmt::println(" Copyright (c) 2025, Marcos Cruz (programandala.net)")!;
fmt::println(" SPDX-License-Identifier: Fair\n")!;
press_enter("Press Enter to read the instructions. ");
};
// Clear the screen, print the instructions and wait for a keypress.
//
fn print_instructions() void = {
clear_screen();
fmt::println("Bagels")!;
fmt::println("Number guessing game\n")!;
fmt::println("I am thinking of a three-digit number that has no two digits the same.")!;
fmt::println("Try to guess it and I will give you clues as follows:\n")!;
fmt::println(" PICO - one digit correct but in the wrong position")!;
fmt::println(" FERMI - one digit correct and in the right position")!;
fmt::println(" BAGELS - no digits correct\n")!;
press_enter("Press Enter to start. ");
};
// Strings {{{1
// =============================================================================
fn repeat(s: str, n: int) str = {
let result = "";
for (let i: int = 0; i < n; i += 1) {
result = strings::concat(result, s)!;
};
return result;
};
// User input {{{1
// =============================================================================
fn print_prompt(prompt: str = "") void = {
fmt::print(prompt)!;
bufio::flush(os::stdout)!;
};
fn accept_string(prompt: str = "") str = {
print_prompt(prompt);
const buffer = match (bufio::read_line(os::stdin)!) {
case let buffer: []u8 =>
yield buffer;
case =>
return "";
};
defer free(buffer);
return strings::dup(strings::fromutf8(buffer)!)!;
};
fn press_enter(prompt: str = "") void = {
free(accept_string(prompt));
};
// Return `true` if the given string is "yes" or a synonym.
//
fn is_yes(s: str) bool = {
const lowercase_s = ascii::strlower(s)!;
defer free(lowercase_s);
return switch(lowercase_s) {
case "ok", "y", "yeah", "yes" =>
yield true;
case =>
yield false;
};
};
// Return `true` if the given string is "no" or a synonym.
//
fn is_no(s: str) bool = {
const lowercase_s = ascii::strlower(s)!;
defer free(lowercase_s);
return switch(lowercase_s) {
case "n", "no", "nope" =>
yield true;
case =>
yield false;
};
};
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
//
fn yes(prompt: str) bool = {
for (true) {
let answer = accept_string(prompt);
defer free(answer);
if (is_yes(answer)) {
return true;
};
if (is_no(answer)) {
return false;
};
};
};
// Main {{{1
// =============================================================================
// Print the given prompt and update the array whose address is given with a
// three-digit number from the user.
//
fn get_input(prompt: str, user_digit: *[DIGITS]int) void = {
def ASCII_0 = 48;
for :get_loop (true) {
let input = accept_string(prompt);
defer free(input);
if (len(input) != DIGITS) {
fmt::printfln("Remember it's a {}-digit number.", DIGITS)!;
continue :get_loop;
};
for (let pos = 0; pos < len(input): int; pos += 1) {
let digit = strings::toutf8(input)[pos];
if (ascii::isdigit(digit: rune)) {
user_digit[pos] = digit: int - ASCII_0;
} else {
fmt::println("What?")!;
continue :get_loop;
};
};
if (is_any_repeated(user_digit)) {
fmt::println("Remember my number has no two digits the same.")!;
continue :get_loop;
};
break;
};
};
def DIGITS = 3;
let random_digit: [DIGITS]int = [0 ...];
// Return three random digits.
//
fn random_number() [DIGITS]int = {
for (let i = 0; i < DIGITS; i += 1) {
for :digit_loop (true) {
random_digit[i] = random::u64n(&rand, 10): int;
for (let j = 0; j < i; j += 1) {
if (i != j && random_digit[i] == random_digit[j]) {
continue :digit_loop;
};
};
break;
};
};
return random_digit;
};
// Return `true` if any of the given numbers is repeated; otherwise return
// `false`.
//
fn is_any_repeated(num: []int) bool = {
const length: int = len(num): int;
for (let i0 = 0; i0 < length; i0 += 1) {
for (let n1 .. num[i0 + 1 .. length]) {
if (num[i0] == n1) {
return true;
};
};
};
return false;
};
// Init and run the game loop.
//
fn play() void = {
def TRIES = 20;
let score = 0;
let fermi = 0; // counter
let pico = 0; // counter
let user_number: [DIGITS]int = [0...];
for (true) {
clear_screen();
let computer_number = random_number();
fmt::println("O.K. I have a number in mind.")!;
for (let guess = 1; guess <= TRIES; guess += 1) {
// XXX TMP
// fmt::print("My number: ")!;
// for (let i = 0; i < DIGITS; i += 1) {
// fmt::print(computer_number[i])!;
// };
// fmt::println()!;
get_input(fmt::asprintf("Guess #{:_02}: ", guess)!, &user_number);
fermi = 0;
pico = 0;
for (let i = 0; i < DIGITS; i += 1) {
for (let j = 0; j < DIGITS; j += 1) {
if (user_number[i] == computer_number[j]) {
if (i == j) {
fermi += 1;
} else {
pico += 1;
};
};
};
};
let picos = repeat("PICO ", pico);
defer free(picos);
let fermis = repeat("FERMI ", fermi);
defer free(fermis);
fmt::print(picos)!;
fmt::print(fermis)!;
if (pico + fermi == 0) {
fmt::print("BAGELS")!;
};
fmt::println()!;
if (fermi == DIGITS) {
break;
};
};
if (fermi == DIGITS) {
fmt::println("You got it!!!")!;
score += 1;
} else {
fmt::println("Oh well.")!;
fmt::printf("That's {} guesses. My number was ", TRIES)!;
for (let i = 0; i < DIGITS; i += 1) {
fmt::print(computer_number[i])!;
};
fmt::println(".")!;
};
if (!yes("Play again? ")) {
break;
};
};
if (score != 0) {
fmt::printfln("A {}-point bagels, buff!!", score)!;
};
fmt::println("Hope you had fun. Bye.")!;
};
let rand: random::random = 0;
fn randomize() void = {
rand = random::init(time::now(time::clock::MONOTONIC).sec: u64);
};
fn init() void = {
randomize();
};
export fn main() void = {
init();
print_credits();
print_instructions();
play();
};
In Janet
# Bagels
# Original version in BASIC:
# D. Resek, P. Rowe, 1978.
# Creative Computing (Morristown, New Jersey, USA), 1978.
# This version in Janet:
# Copyright (c) 2023, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written in 2025-12-26/27.
#
# Last modified: 20251227T1413+0100.
(defn move-cursor-home []
(prin "\e[H"))
(defn clear-screen []
(prin "\e[2J")
(move-cursor-home))
(defn command [&opt prompt-text]
(default prompt-text "> ")
(prin prompt-text)
(string/trim (getline)))
(defn press-enter [prompt-text]
(while (not= (command prompt-text) "")) (break))
(defn is-yes? [word]
(index-of (string/ascii-lower word) ["ok" "y" "yeah" "yes"]))
(defn is-no? [word]
(index-of (string/ascii-lower word) ["n" "no" "nope"]))
(defn yes? [question]
(var answer "")
(while (not (or (is-yes? answer) (is-no? answer)))
(set answer (command question)))
(is-yes? answer))
(defn print-credits []
(clear-screen)
(print "Bagels")
(print "Number guessing game\n")
(print "Original source unknown but suspected to be:")
(print " Lawrence Hall of Science, U.C. Berkely.\n")
(print "Original version in BASIC:")
(print " D. Resek, P. Rowe, 1978.")
(print " Creative computing (Morristown, New Jersey, USA), 1978.\n")
(print "This version in Janet:")
(print " Copyright (c) 2025, Marcos Cruz (programandala.net)")
(print " SPDX-License-Identifier: Fair\n")
(press-enter "Press Enter to read the instructions. "))
(defn print-instructions []
(clear-screen)
(print "Bagels")
(print "Number guessing game\n")
(print "I am thinking of a three-digit number that has no two digits the same.")
(print "Try to guess it and I will give you clues as follows:\n")
(print " PICO - one digit correct but in the wrong position")
(print " FERMI - one digit correct and in the right position")
(print " BAGELS - no digits correct\n")
(press-enter "Press Enter to start. "))
(def digits 3)
(def random-number-generator (math/rng (os/time)))
(defn random-digits
"Return an array containing `digits` random integer numbers in range [0, 9]"
[]
(var result @[])
(while (< (length result) digits)
(var digit (math/rng-int random-number-generator 10))
(when (not (has-value? result digit))
(array/push result digit)))
result)
(defn digit?
"Is the string a digit?"
[s]
(and
(= (length s) 1)
(scan-number s)))
(defn only-digits? [s]
(string/check-set "0123456789" s))
(defn input [prompt-text]
`Return an array containing three random integer numbers in range [0, 9],
out of the string typed in by the user.`
(var user-digit @[])
(forever
(def raw-input (command prompt-text))
(cond
(not= (length raw-input) digits)
(print "Remember it's a " digits "-digit number.")
(not (only-digits? raw-input))
(print "What?")
(not= digits (length (distinct raw-input)))
(print "Remember my number has no two digits the same.")
(do
(for c 0 digits
(put user-digit c (scan-number (string/slice raw-input c (+ c 1)))))
(break))))
user-digit)
(defn play []
(def tries 20)
(var computer-number (array/new digits))
(var user-number (array/new digits))
(var score 0)
(var fermi 0) # counter
(var pico 0) # counter
(forever
(clear-screen)
(set computer-number (random-digits))
(print "O.K. I have a number in mind.")
(for guess 0 tries
(set user-number
(input (string "Guess #" (string/format "%02d" guess) ": ")))
(set fermi 0)
(set pico 0)
(for i 0 digits
(for j 0 digits
(when (= (get computer-number i) (get user-number j))
(if (= i j)
(+= fermi 1)
(+= pico 1)))))
(if (= (+ pico fermi) 0)
(prin "BAGELS")
(do
(prin (string/repeat "PICO " pico))
(prin (string/repeat "FERMI " fermi))))
(print)
(when (= fermi digits)
(break)))
(if (= fermi digits)
(do
(print "You got it!!!")
(+= score 1))
(do
(print "Oh well.")
(print "That's " tries " guesses. My number was ")
(print (get computer-number 0) (get computer-number 1) (get computer-number 2) "\n")))
(when (not (yes? "Play again? "))
(break)))
(when (not= score 0)
(print "A " score "-point bagels, buff!!"))
(print "Hope you had fun. Bye."))
(defn main [& args]
(print-credits)
(print-instructions)
(play))
In Julia
# Bagels
# Original version in BASIC:
# D. Resek, P. Rowe, 1978.
# Creative Computing (Morristown, New Jersey, USA), 1978.
# This version in Julia:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written in 2024-07-03/04.
#
# Last modified: 20240704T1235+0200.
# Move the cursor to the home position.
function home()
print("\e[H")
end
# Clear the screen and move the cursor to the home position.
function clear_screen()
print("\e[2J")
home()
end
# Prompt the user to enter a command and return it.
function command(prompt = "> ")::String
print(prompt)
return readline()
end
# Print the given prompt and wait until the user enters an empty string.
function press_enter(prompt::String)
while command(prompt) != ""
end
end
# Return `true` if the given string is "yes" or a synonym; otherwise return
# `false`.
function is_yes(answer::String)::Bool
return lowercase(answer) in ["y", "yeah", "yes", "ok"]
end
# Return `true` if the given string is "no" or a synonym; otherwise return
# `false`.
function is_no(answer::String)::Bool
return lowercase(answer) in ["n", "no", "nope"]
end
# Print the given prompt, wait until the user enters a valid yes/no string, and
# return `true` for "yes" or `false` for "no".
function yes(prompt::String)::Bool
answer = ""
while ! (is_yes(answer) || is_no(answer))
answer = command(prompt)
end
return is_yes(answer)
end
# Clear the screen, display the credits and wait for a keypress.
function print_credits()
clear_screen()
println("Bagels")
println("Number guessing game\n")
println("Original source unknown but suspected to be:")
println(" Lawrence Hall of Science, U.C. Berkely.\n")
println("Original version in BASIC:")
println(" D. Resek, P. Rowe, 1978.")
println(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
println("This version in Julia:")
println(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
press_enter("Press Enter to read the instructions. ")
end
# Clear the screen, print the instructions and wait for a keypress.
function print_instructions()
clear_screen()
println("Bagels")
println("Number guessing game\n")
println("I am thinking of a three-digit number that has no two digits the same.")
println("Try to guess it and I will give you clues as follows:\n")
println(" PICO - one digit correct but in the wrong position")
println(" FERMI - one digit correct and in the right position")
println(" BAGELS - no digits correct")
press_enter("\nPress Enter to start. ")
end
const DIGITS = 3
const MIN_DIGIT = 0
const MAX_DIGIT = 9
const INVALID_DIGIT = MAX_DIGIT + 1
const TRIES = 20
function has_other_than_digits(text::String)::Bool
for char in text
if ! isdigit(char)
return true
end
end
return false
end
# Print the given prompt and get a three-digit number from the user.
function input(prompt::String)::Array{Int64, 1}
user_digit = Int[]
while true
user_input = command(prompt)
if length(user_input) != DIGITS
println("Remember it's a $DIGITS-digit number.")
continue
elseif has_other_than_digits(user_input)
println("What?")
continue
end
empty!(user_digit)
for c in user_input
push!(user_digit, parse(Int, c))
end
user_unique_digit = unique(user_digit)
if length(user_unique_digit) != length(user_digit)
println("Remember my number has no two digits the same.")
continue
end
break
end
return user_digit
end
# Init and run the game loop.
function play()
computer_number = [INVALID_DIGIT, INVALID_DIGIT, INVALID_DIGIT]
user_number = [INVALID_DIGIT, INVALID_DIGIT, INVALID_DIGIT]
score = 0
fermi = 0 # counter
pico = 0 # counter
while true # game loop
clear_screen()
for i in 1 : DIGITS
while true
digit = rand(MIN_DIGIT : MAX_DIGIT)
if digit in computer_number
continue
else
computer_number[i] = digit
break
end
end
end
println("O.K. I have a number in mind.")
for guess in 1 : TRIES
user_number = input("Guess #$(lpad(guess, 2, '0')): ")
fermi = 0
pico = 0
for i in 1 : DIGITS
for j in 1 : DIGITS
if computer_number[i] == user_number[j]
if i == j
fermi += 1
else
pico += 1
end
end
end
end
print(repeat("PICO ", pico))
print(repeat("FERMI ", fermi))
if pico + fermi == 0
print("BAGELS")
end
println()
if fermi == DIGITS
println("You got it!!!")
score += 1
break # tries loop
end
end # tries loop
if fermi != DIGITS
println("Oh well.")
print("That's $TRIES guesses. My number was ")
for i in 1 : DIGITS
print(computer_number[i])
end
println(".")
end
if ! yes("Play again? ")
break # game loop
end
end # game loop
if score != 0
println("A $score-point bagels, buff!!")
end
println("Hope you had fun. Bye.")
end
print_credits()
print_instructions()
play()
In Kotlin
/*
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Kotlin:
Copyright (c) 2023, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written in 2023-10.
Last modified: 20250420T0003+0200.
*/
// Move the cursor to the home position.
fun home() {
print("\u001B[H")
}
// Clear the screen and move the cursor to the home position.
fun clear() {
print("\u001B[2J")
home()
}
// Wait until the user presses the Enter key.
// Clear the screen, display the credits and wait for a keypress.
fun printCredits() {
clear()
println("Bagels")
println("Number guessing game\n")
println("Original source unknown but suspected to be:")
println(" Lawrence Hall of Science, U.C. Berkely.\n")
println("Original version in BASIC:")
println(" D. Resek, P. Rowe, 1978.")
println(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
println("This version in Kotlin:")
println(" Copyright (c) 2023, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
print("Press Enter to read the instructions. ")
readln()
}
// Clear the screen, print the instructions and wait for a keypress.
fun printInstructions() {
clear()
println("Bagels")
println("Number guessing game\n")
println("I am thinking of a three-digit number that has no two digits the same.")
println("Try to guess it and I will give you clues as follows:\n")
println(" PICO - one digit correct but in the wrong position")
println(" FERMI - one digit correct and in the right position")
println(" BAGELS - no digits correct")
print("\nPress Enter to start. ")
readln()
}
const val DIGITS = 3
// Return three random digits.
fun random(): IntArray {
var randomDigit = IntArray(DIGITS)
for (i in 0..<DIGITS) {
digitLoop@ while (true) {
randomDigit[i] = (0..9).random()
for (j in 0..<i) {
if (i != j && randomDigit[i] == randomDigit[j]) { continue@digitLoop }
}
break
}
}
return randomDigit
}
const val ASCII_0 = 48
// Print the given prompt and get a three-digit number from the user.
fun input(prompt: String): IntArray {
var userDigit = IntArray(DIGITS)
getLoop@ while (true) {
print(prompt)
var input = readln()
if (input.length != DIGITS) {
println("Remember it's a $DIGITS-digit number.")
continue@getLoop
}
for ((pos, digit) in input.withIndex()) {
if (digit.isDigit()) {
userDigit[pos] = digit.code - ASCII_0
} else {
println("What?")
continue@getLoop
}
}
if (userDigit.distinct().count() != DIGITS) {
println("Remember my number has no two digits the same.")
continue@getLoop
}
break
}
return userDigit
}
// Return `true` if the given String is "yes" or a synonym.
fun isYes(answer: String): Boolean {
when (answer.lowercase()) {
"ok", "yeah", "yes", "y" -> return true
else -> return false
}
}
// Return `true` if the given String is "no" or a synonym.
fun isNo(answer: String): Boolean {
when (answer.lowercase()) {
"no", "nope", "n" -> return true
else -> return false
}
}
// Print the given prompt, wait until the user enters a valid yes/no
// String, and return `true` for "yes" or `false` for "no".
fun yes(prompt: String): Boolean {
var answer = ""
while (!(isYes(answer) || isNo(answer))) {
print(prompt)
answer = readln()
}
return isYes(answer)
}
const val TRIES = 20
// Init and run the game loop.
fun play() {
var score = 0
while (true) {
clear()
var computerNumber = random()
var fermi = 0
println("O.K. I have a number in mind.")
for (guess in 1..TRIES) {
var userNumber = input("Guess #${guess.toString().padStart(2, '0')}: ")
fermi = 0
var pico = 0
for (i in 0..<DIGITS) {
for (j in 0..<DIGITS) {
if (userNumber[i] == computerNumber[j]) {
if (i == j) {
fermi += 1
} else {
pico += 1
}
}
}
}
print("PICO ".repeat(pico))
print("FERMI ".repeat(fermi))
if (pico + fermi == 0) { print("BAGELS") }
println()
if (fermi == DIGITS) { break }
}
if (fermi == DIGITS) {
println("You got it!!!")
score += 1
} else {
println("Oh well.")
print("That's $TRIES guesses. My number was ")
for (i in 0..<DIGITS) { print(computerNumber[i]) }
println(".")
}
if (!yes("Play again? ")) { break }
}
if (score != 0) {
println("A $score-point bagels, buff!!")
}
println("Hope you had fun. Bye.")
}
fun main() {
printCredits()
printInstructions()
play()
}
In Nim
#[
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Nim:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written in 2025-01-19/20.
Last modified: 20250124T0133+0100.
]#
import std/random
import std/sequtils
import std/strformat
import std/strutils
import std/terminal
import std/unicode
proc cursorHome() =
setCursorPos(0, 0)
proc clearScreen() =
eraseScreen()
cursorHome()
# Clear the screen, display the credits and wait for a keypress.
#
proc printCredits() =
clearScreen()
writeLine(stdout, "Bagels")
writeLine(stdout, "Number guessing game\n")
writeLine(stdout, "Original source unknown but suspected to be:")
writeLine(stdout, " Lawrence Hall of Science, U.C. Berkely.\n")
writeLine(stdout, "Original version in BASIC:")
writeLine(stdout, " D. Resek, P. Rowe, 1978.")
writeLine(stdout, " Creative computing (Morristown, New Jersey, USA), 1978.\n")
writeLine(stdout, "This version in Nim:")
writeLine(stdout, " Copyright (c) 2025, Marcos Cruz (programandala.net)")
writeLine(stdout, " SPDX-License-Identifier: Fair\n")
write(stdout, "Press Enter to read the instructions. ")
discard readLine(stdin)
# Clear the screen, print the instructions and wait for a keypress.
#
proc printInstructions() =
clearScreen()
writeLine(stdout, "Bagels")
writeLine(stdout, "Number guessing game\n")
writeLine(stdout, "I am thinking of a three-digit number that has no two digits the same.")
writeLine(stdout, "Try to guess it and I will give you clues as follows:\n")
writeLine(stdout, " PICO - one digit correct but in the wrong position")
writeLine(stdout, " FERMI - one digit correct and in the right position")
writeLine(stdout, " BAGELS - no digits correct")
write(stdout, "\nPress Enter to start. ")
discard readLine(stdin)
const digits = 3
# Return a sequence containing as many random digits as the value of the
# `digits` constant.
#
proc random(): seq[int] =
while len(result) < digits:
var digit = rand(9)
if digit notin result:
add(result, digit)
# Print the given prompt and update the array whose address is given with a
# three-digit number from the user.
#
proc getInput(prompt: string, userDigit: var array[digits, int]) =
var ok = false
while not ok:
write(stdout, prompt)
var input = readLine(stdin)
if len(input) != digits:
writeLine(stdout, "Remember it's a ", digits, "-digit number.")
continue
ok = true
for pos, charDigit in input:
if isDigit(charDigit):
var stringDigit = newStringOfCap(1)
add(stringDigit, charDigit)
userDigit[pos] = parseInt(stringDigit)
else:
ok = false
writeLine(stdout, "What?")
break
if ok and len(deduplicate(userDigit)) < digits:
writeLine(stdout, "Remember my number has no two digits the same.")
ok = false
# Return `true` if the given string is "yes" or a synonym.
#
proc isYes(s: string): bool =
return toLower(s) in ["ok", "y", "yeah", "yes"]
# Return `true` if the given string is "no" or a synonym.
#
proc isNo(s: string): bool =
return toLower(s) in ["n", "no", "nope"]
# Print the given prompt, wait until the user enters a valid yes/no string,
# and return `true` for "yes" or `false` for "no".
#
proc yes(prompt: string): bool =
while true:
write(stdout, prompt)
var answer = readLine(stdin)
if isYes(answer):
return true
if isNo(answer):
return false
# Init and run the game loop.
#
proc play() =
const tries = 20
var score = 0
var fermi: int # counter
var pico: int # counter
var userNumber: array[digits, int]
while true:
clearScreen()
var computerNumber = random()
writeLine(stdout, "O.K. I have a number in mind.")
for guess in 1 .. tries:
# writeLine(stdout, "My number: ", computerNumber) # XXX TMP
getInput(fmt"Guess #{guess:00}: ", userNumber)
fermi = 0
pico = 0
for i in 0 ..< digits:
for j in 0 ..< digits:
if userNumber[i] == computerNumber[j]:
if i == j:
fermi += 1
else:
pico += 1
write(stdout, repeat("PICO ", pico))
write(stdout, repeat("FERMI ", fermi))
if pico + fermi == 0:
write(stdout, "BAGELS")
writeLine(stdout, "")
if fermi == digits:
break
if fermi == digits:
writeLine(stdout, "You got it!!!")
score += 1
else:
writeLine(stdout, "Oh well.")
write(stdout, "That's ", tries, " guesses. My number was ")
for i in 0 ..< digits:
write(stdout, computerNumber[i])
writeLine(stdout, ".")
if not yes("Play again? "):
break
if score != 0:
writeLine(stdout, "A ", score, "-point bagels, buff!!")
writeLine(stdout, "Hope you had fun. Bye.")
printCredits()
printInstructions()
play()
In Odin
/*
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Odin:
Copyright (c) 2023, 2024, 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written in 2023-04, 2023-09/10, 2023-12, 2024-12, 2025-02.
Last modified: 20250407T1920+0200.
*/
package bagels
import "../lib/anodino/src/read"
import "../lib/anodino/src/term"
import "core:fmt"
import "core:math/rand"
import "core:slice"
import "core:strings"
import "core:unicode"
press_enter :: proc(prompt: string) {
s, _ := read.a_prompted_string(prompt)
delete(s)
}
// Clear the screen, display the credits and wait for a keypress.
//
print_credits :: proc() {
term.clear_screen()
fmt.println("Bagels")
fmt.println("Number guessing game\n")
fmt.println("Original source unknown but suspected to be:")
fmt.println(" Lawrence Hall of Science, U.C. Berkely.\n")
fmt.println("Original version in BASIC:")
fmt.println(" D. Resek, P. Rowe, 1978.")
fmt.println(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
fmt.println("This version in Odin:")
fmt.println(" Copyright (c) 2023, 2024, 2025, Marcos Cruz (programandala.net)")
fmt.println(" SPDX-License-Identifier: Fair\n")
press_enter("Press Enter to read the instructions. ")
}
// Clear the screen, print the instructions and wait for a keypress.
//
print_instructions :: proc() {
term.clear_screen()
fmt.println("Bagels")
fmt.println("Number guessing game\n")
fmt.println("I am thinking of a three-digit number that has no two digits the same.")
fmt.println("Try to guess it and I will give you clues as follows:\n")
fmt.println(" PICO - one digit correct but in the wrong position")
fmt.println(" FERMI - one digit correct and in the right position")
fmt.println(" BAGELS - no digits correct")
press_enter("\nPress Enter to start. ")
}
DIGITS :: 3
random_digit : [DIGITS]int
// Return three random digits.
//
random :: proc() -> []int {
for i in 0 ..< DIGITS {
digit_loop: for {
random_digit[i] = rand.int_max(10)
for j in 0 ..< i {
if i != j && random_digit[i] == random_digit[j] do continue digit_loop
}
break
}
}
return random_digit[:]
}
// Return `true` if any of the given numbers is repeated; otherwise return
// `false`.
//
is_any_repeated :: proc(num : []int) -> bool {
for n0, i0 in num[:] {
for n1 in num[i0 + 1 : len(num)] {
if n0 == n1 do return true
}
}
return false
}
// Print the given prompt and update the array whose address is given with a
// three-digit number from the user.
//
get_input :: proc(prompt : string, user_digit : ^[DIGITS]int) {
// XXX TODO Create a local array, appending every digit after checking the contents,
// making `is_any_repeated` unnecessary.
ASCII_0 :: 48
get_loop: for {
input, ok := read.a_prompted_string(prompt)
defer delete(input)
if !ok do input = ""
if len(input) != DIGITS {
fmt.printfln("Remember it's a %v-digit number.", DIGITS)
continue get_loop
}
for digit, pos in input {
if unicode.is_digit(digit) {
user_digit^[pos] = int(digit) - ASCII_0
} else {
fmt.println("What?")
continue get_loop
}
}
if is_any_repeated(user_digit[:]) {
fmt.println("Remember my number has no two digits the same.")
continue get_loop
}
break
}
}
// Return `true` if the given string is "yes" or a synonym.
//
is_yes :: proc(s : string) -> bool {
lowercase_s := strings.to_lower(s)
defer delete(lowercase_s)
return slice.any_of([]string{"ok", "y", "yeah", "yes"}, lowercase_s)
}
// Return `true` if the given string is "no" or a synonym.
//
is_no :: proc(s : string) -> bool {
lowercase_s := strings.to_lower(s)
defer delete(lowercase_s)
return slice.any_of([]string{"n", "no", "nope"}, lowercase_s)
}
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
//
yes :: proc(prompt : string) -> bool {
for {
answer, ok := read.a_prompted_string(prompt)
defer delete(answer)
if !ok do answer = ""
if is_yes(answer) do return true
if is_no(answer) do return false
}
}
// Init and run the game loop.
//
play :: proc() {
TRIES :: 20
score := 0
fermi : int // counter
pico : int // counter
user_number : [DIGITS]int
for {
term.clear_screen()
computer_number := random()
fmt.println("O.K. I have a number in mind.")
for guess in 1 ..= TRIES {
// fmt.printfln("My number: %v", computer_number) // XXX TMP
get_input(fmt.tprintf("Guess #%2v: ", guess), &user_number)
fermi = 0
pico = 0
for i in 0 ..< DIGITS {
for j in 0 ..< DIGITS {
if user_number[i] == computer_number[j] {
if i == j {
fermi += 1
} else {
pico += 1
}
}
}
}
picos := strings.repeat("PICO ", pico)
defer delete(picos)
fermis := strings.repeat("FERMI ", fermi)
defer delete(fermis)
fmt.print(picos)
fmt.print(fermis)
if pico + fermi == 0 do fmt.print("BAGELS")
fmt.println()
if fermi == DIGITS do break
}
if fermi == DIGITS {
fmt.println("You got it!!!")
score += 1
} else {
fmt.println("Oh well.")
fmt.printf("That's %v guesses. My number was ", TRIES)
for i in 0 ..< DIGITS do fmt.print(computer_number[i])
fmt.println(".")
}
if !yes("Play again? ") do break
}
if score != 0 {
fmt.printfln("A %v-point bagels, buff!!", score)
}
fmt.println("Hope you had fun. Bye.")
}
main :: proc() {
print_credits()
print_instructions()
play()
}
In Pike
#!/usr/bin/env pike
// Bagels
// Original version in BASIC:
// D. Resek, P. Rowe, 1978.
// Creative Computing (Morristown, New Jersey, USA), 1978.
// This version in Pike:
// Copyright (c) 2025, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2025-03-10.
//
// Last modified: 20250324T1737+0100.
// Terminal {{{1
// =============================================================================
constant NORMAL_STYLE = 0;
void move_cursor_home() {
write("\x1B[H");
}
void set_style(int style) {
write("\x1B[%dm", style);
}
void reset_attributes() {
set_style(NORMAL_STYLE);
}
void erase_screen() {
write("\x1B[2J");
}
void clear_screen() {
erase_screen();
reset_attributes();
move_cursor_home();
}
// Credits and instructions {{{1
// =============================================================================
// Clear the screen, display the credits and wait for a keypress.
//
void print_credits() {
clear_screen();
write("Bagels\n");
write("Number guessing game\n\n");
write("Original source unknown but suspected to be:\n");
write(" Lawrence Hall of Science, U.C. Berkely.\n\n");
write("Original version in BASIC:\n");
write(" D. Resek, P. Rowe, 1978.\n");
write(" Creative computing (Morristown, New Jersey, USA), 1978.\n\n");
write("This version in Pike:\n");
write(" Copyright (c) 2025, Marcos Cruz (programandala.net)\n");
write(" SPDX-License-Identifier: Fair\n\n");
accept_string("Press Enter to read the instructions. ");
}
// Clear the screen, print the instructions and wait for a keypress.
//
void print_instructions() {
clear_screen();
write("Bagels\n");
write("Number guessing game\n\n");
write("I am thinking of a three-digit number that has no two digits the same.\n");
write("Try to guess it and I will give you clues as follows:\n\n");
write(" PICO - one digit correct but in the wrong position\n");
write(" FERMI - one digit correct and in the right position\n");
write(" BAGELS - no digits correct\n\n");
accept_string("Press Enter to start. ");
}
// User input {{{1
// =============================================================================
string accept_string(string prompt) {
write(prompt);
return Stdio.stdin->gets();
}
// Return `true` if the given string is "yes" or a synonym.
//
bool is_yes(string s) {
switch(lower_case(s)) {
case "ok":
case "y":
case "yeah":
case "yes":
return true;
default:
return false;
}
}
// Return `true` if the given string is "no" or a synonym.
//
bool is_no(string s) {
switch(lower_case(s)) {
case "n":
case "no":
case "nope":
return true;
default:
return false;
}
}
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
//
bool yes(string prompt) {
while (true) {
string answer = accept_string(prompt);
if (is_yes(answer)) {
return true;
}
if (is_no(answer)) {
return false;
}
}
}
// Main {{{1
// =============================================================================
constant DIGITS = 3;
bool is_digit(int ascii_code) {
return (ascii_code >= '0') && (ascii_code <= '9');
}
// Print the given prompt and return an array with a three-digit number type by
// the user.
//
array(int) get_input(string prompt) {
array(int) user_digit = allocate(DIGITS);
constant ASCII_0 = '0';
get_loop: while (true) {
string input = accept_string(prompt);
if (sizeof(input) != DIGITS) {
write("Remember it's a %d-digit number.\n", DIGITS);
continue get_loop;
}
for (int pos = 0; pos < sizeof(input); pos += 1) {
int digit = input[pos];
if (is_digit(digit)) {
user_digit[pos] = digit - ASCII_0;
} else {
write("What?\n");
continue get_loop;
}
}
if (is_any_repeated(user_digit)) {
write("Remember my number has no two digits the same.\n");
continue get_loop;
}
break;
}
return user_digit;
}
// Return three random digits.
//
array(int) random_number() {
array(int) random_digit = allocate(DIGITS);
for (int i = 0; i < DIGITS; i += 1) {
digit_loop: while (true) {
random_digit[i] = random(10);
for (int j = 0; j < i; j += 1) {
if (i != j && random_digit[i] == random_digit[j]) {
continue digit_loop;
}
}
break;
}
}
return random_digit;
}
// Return `true` if any of the given numbers is repeated; otherwise return
// `false`.
//
bool is_any_repeated(array(int) numbers) {
array(int) filtered_numbers = Array.uniq(numbers);
return !equal(filtered_numbers, numbers);
}
// Init and run the game loop.
//
void play() {
constant TRIES = 20;
int score = 0;
int fermi = 0; // counter
int pico = 0; // counter
array(int) computer_number = allocate(DIGITS);
array(int) user_number = allocate(DIGITS);
while (true) {
clear_screen();
array(int) computer_number = random_number();
write("O.K. I have a number in mind.\n");
for (int guess = 1; guess <= TRIES; guess += 1) {
// XXX TMP
// write("My number: ");
// for (int i = 0; i < DIGITS; i += 1) {
// write("%d", computer_number[i]);
// }
// write("\n");
user_number = get_input(sprintf("Guess #%02d: ", guess));
fermi = 0;
pico = 0;
for (int i = 0; i < DIGITS; i += 1) {
for (int j = 0; j < DIGITS; j += 1) {
if (user_number[i] == computer_number[j]) {
if (i == j) {
fermi += 1;
} else {
pico += 1;
}
}
}
}
if (pico + fermi == 0) {
write("BAGELS\n");
} else {
write("%s%s\n", "PICO " * pico, "FERMI " * fermi);
if (fermi == DIGITS) {
break;
}
}
}
if (fermi == DIGITS) {
write("You got it!!!\n");
score += 1;
} else {
write("Oh well.\n");
write("That's %d guesses. My number was ", TRIES);
for (int i = 0; i < DIGITS; i += 1) {
write("%d", computer_number[i]);
}
write(".\n");
}
if (!yes("Play again? ")) {
break;
}
}
if (score != 0) {
write("A %d-point bagels, buff!!\n", score);
}
write("Hope you had fun. Bye.\n");
}
void main() {
print_credits();
print_instructions();
play();
}
In Python
# Bagels
# Original version in BASIC:
# D. Resek, P. Rowe, 1978.
# Creative Computing (Morristown, New Jersey, USA), 1978.
# This version in Python:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written on 2024-10-29.
#
# Last modified: 20241203T2230+0100.
import os
import random
# Clear the screen and move the cursor to the home position.
def clear_screen():
if os.name == 'nt':
_ = os.system('cls')
else:
# on mac and linux, `os.name` is 'posix'
_ = os.system('clear')
# Prompt the user to enter a command and return it.
def command(prompt = "> "):
return input(prompt)
# Print the given prompt and wait until the user enters an empty string.
def press_enter(prompt):
user_input = "X"
while user_input != "":
user_input = command(prompt)
# Return `True` if the given string is "yes" or a synonym; otherwise return
# `False`.
def is_yes(answer):
return answer.lower() in ["y", "yeah", "yes", "ok"]
# Return `True` if the given string is "no" or a synonym; otherwise return
# `False`.
def is_no(answer):
return answer.lower() in ["n", "no", "nope"]
# Print the given prompt, wait until the user enters a valid yes/no string, and
# return `True` for "yes" or `False` for "no".
def yes(prompt):
answer = ""
while not (is_yes(answer) or is_no(answer)):
answer = command(prompt)
return is_yes(answer)
# Clear the screen, display the credits and wait for a keypress.
def print_credits():
clear_screen()
print("Bagels")
print("Number guessing game\n")
print("Original source unknown but suspected to be:")
print(" Lawrence Hall of Science, U.C. Berkely.\n")
print("Original version in BASIC:")
print(" D. Resek, P. Rowe, 1978.")
print(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
print("This version in Python:")
print(" Copyright (c) 2024, Marcos Cruz (programandala.net)")
print(" SPDX-License-Identifier: Fair\n")
press_enter("Press Enter to read the instructions. ")
# Clear the screen, print the instructions and wait for a keypress.
def print_instructions():
clear_screen()
print("Bagels")
print("Number guessing game\n")
print("I am thinking of a three-digit number that has no two digits the same.")
print("Try to guess it and I will give you clues as follows:\n")
print(" PICO - one digit correct but in the wrong position")
print(" FERMI - one digit correct and in the right position")
print(" BAGELS - no digits correct")
press_enter("\nPress Enter to start. ")
DIGITS = 3
MIN_DIGIT = 0
MAX_DIGIT = 9
INVALID_DIGIT = MAX_DIGIT + 1
TRIES = 20
def has_other_than_digits(text):
for char in text:
if not char.isdigit():
return True
return False
# Print the given prompt and get a three-digit number from the user.
def input_digits(prompt):
user_digit = []
while True:
user_input = command(prompt)
if len(user_input) != DIGITS:
print(f"Remember it's a {DIGITS}-digit number.")
continue
elif has_other_than_digits(user_input):
print("What?")
continue
user_digit.clear()
for c in user_input:
user_digit.append(int(c))
if len(set(user_digit)) != len(user_digit):
print("Remember my number has no two digits the same.")
continue
break
return user_digit
# Init and run the game loop.
def play():
computer_number = [INVALID_DIGIT, INVALID_DIGIT, INVALID_DIGIT]
user_number = [INVALID_DIGIT, INVALID_DIGIT, INVALID_DIGIT]
score = 0
fermi = 0 # counter
pico = 0 # counter
while True: # game loop
clear_screen()
for i in range(0, DIGITS):
while True:
digit = random.randrange(MIN_DIGIT, MAX_DIGIT + 1)
if digit in computer_number:
continue
else:
computer_number[i] = digit
break
print("O.K. I have a number in mind.")
for guess in range(0, TRIES):
user_number = input_digits("Guess #" + str(guess).zfill(2) + ": ")
fermi = 0
pico = 0
for i in range(0, DIGITS):
for j in range(0, DIGITS):
if computer_number[i] == user_number[j]:
if i == j:
fermi += 1
else:
pico += 1
print("PICO " * pico, end = "")
print("FERMI " * fermi, end = "")
if pico + fermi == 0:
print("BAGELS", end = "")
print()
if fermi == DIGITS:
print("You got it!!!")
score += 1
break # tries loop
# end of tries loop
if fermi != DIGITS:
print("Oh well.")
print(f"That's {TRIES} guesses. My number was ", end = "")
for i in range(0, DIGITS):
print(computer_number[i], end = "")
print(".")
if not yes("Play again? "):
break # game loop
# end of game loop
if score != 0:
print(f"A {score}-point bagels, buff!!")
print("Hope you had fun. Bye.")
print_credits()
print_instructions()
play()
In Raku
# Bagels
# Original version in BASIC:
# D. Resek, P. Rowe, 1978.
# Creative Computing (Morristown, New Jersey, USA), 1978.
# This version in Raku:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written in 2024-12.
#
# Last modified: 20241211T1933+0100.
sub clear_screen {
print "\e[0;0H\e[2J";
}
sub print_credits {
clear_screen;
put "Bagels";
put "Number guessing game\n";
put "Original source unknown but suspected to be:";
put " Lawrence Hall of Science, U.C. Berkely.\n";
put "Original version in BASIC:";
put " D. Resek, P. Rowe, 1978.";
put " Creative computing (Morristown, New Jersey, USA), 1978.\n";
put "This version in Raku:";
put " Copyright (c) 2024, Marcos Cruz (programandala.net)";
put " SPDX-License-Identifier: Fair\n";
prompt "Press Enter to read the instructions. ";
}
sub print_instructions {
clear_screen;
put "Bagels";
put "Number guessing game\n";
put "I am thinking of a three-digit number that has no two digits the same.";
put "Try to guess it and I will give you clues as follows:\n";
put " PICO - one digit correct but in the wrong position";
put " FERMI - one digit correct and in the right position";
put " BAGELS - no digits correct";
prompt "\nPress Enter to start. ";
}
constant $DIGITS = 3;
# Return three random digits in an integer array.
sub random_number(--> Array) {
my Int @random_digit = ();
while @random_digit.elems < $DIGITS {
loop {
@random_digit.push((0 .. 9).pick);
if @random_digit.unique.elems == @random_digit.elems {
last;
}
@random_digit.pop
}
}
return @random_digit;
}
# Print the given prompt and get a three-digit number from the user.
sub input(Str $prompt --> Array) {
my Int @user_digit = ();
PROMPT: loop {
my $input = prompt($prompt);
if $input.chars != $DIGITS {
put "Remember it's a {$DIGITS}-digit number.";
next PROMPT;
}
for $input.comb -> $digit {
try {
@user_digit.push(+$digit);
CATCH {
default {
put "What?";
next PROMPT;
}
}
}
}
if @user_digit.unique.elems < $DIGITS {
put "Remember my number has no two digits the same.";
next PROMPT;
}
last;
}
return @user_digit;
}
# Return `True` if the given string is "yes" or a synonym.
sub is_yes(Str $answer --> Bool ) {
return $answer.lc (elem) ["ok", "y", "yeah", "yes"]
}
# Return `True` if the given string is "no" or a synonym.
sub is_no(Str $answer --> Bool) {
return $answer.lc (elem) ["n", "no", "nope"];
}
# Print the given prompt, wait until the user enters a valid yes/no
# string, and return `True` for "yes" or `False` for "no".
sub yes(Str $prompt --> Bool) {
loop {
my $answer = prompt($prompt);
if is_yes($answer) { return True };
if is_no($answer) { return False };
}
}
# Init and run the game loop.
sub play {
constant $TRIES = 20;
my Int $score = 0;
my Int $fermi; # counter
my Int $pico; # counter
loop {
clear_screen;
my @computer_number = random_number;
put "O.K. I have a number in mind.";
for 1 .. $TRIES -> $guess {
my @user_number = input(sprintf("Guess #%02d: ", $guess));
$fermi = 0;
$pico = 0;
for 0 ..^ $DIGITS -> $i {
for 0 ..^ $DIGITS -> $j {
if @user_number[$i] == @computer_number[$j] {
if $i == $j {
$fermi += 1;
} else {
$pico += 1;
}
}
}
}
print "PICO " x $pico;
print "FERMI " x $fermi;
if $pico + $fermi == 0 { print "BAGELS" };
put "";
if $fermi == $DIGITS { last };
}
if $fermi == $DIGITS {
put "You got it!!!";
$score += 1;
} else {
put "Oh well.";
put "That's $TRIES guesses. My number was {@computer_number.join}.";
}
if !yes("Play again? ") { last };
}
if $score != 0 {
put "A {$score}-point bagels, buff!!";
}
put "Hope you had fun. Bye.";
}
print_credits;
print_instructions;
play;
In Ring
# Bagels
# Original version in BASIC:
# D. Resek, P. Rowe, 1978.
# Creative Computing (Morristown, New Jersey, USA), 1978.
# This version in Ring:
# Copyright (c) 2024, Marcos Cruz (programandala.net)
# SPDX-License-Identifier: Fair
#
# Written in 2024-04-05/09
#
# Last modified: 20240409T1055+0200.
ASCII_0 = 48
DIGITS = 3
TRIES = 20
MAX_DIGIT = 9
# Clear the screen and move the cursor to the home position.
func clearScreen
system("clear")
end
# Prompt the user to enter a command and return it.
func command(prompt)
if prompt = null
prompt = "> "
end
print(prompt)
return getString()
end
# Print the given prompt and wait until the user enters an empty string.
func pressEnter(prompt)
while command(prompt) != ""
end
end
# Return `true` if the given string is "yes" or a synonym.
func isItYes(answer)
switch lower(answer)
case "ok"
return true
case "y"
return true
case "yeah"
return true
case "yes"
return true
else
return false
end
end
# Return `true` if the given string is "no" or a synonym.
func isItNo(answer)
switch lower(answer)
case "n"
return true
case "no"
return true
case "nope"
return true
else
return false
end
end
# Print the given prompt, wait until the user enters a valid yes/no
# string, and return `true` for "yes" or `false` for "no".
func yes(prompt)
answer = ""
while not (isItYes(answer) || isItNo(answer))
answer = command(prompt)
end
return isItYes(answer)
end
# Clear the screen, display the credits and wait for a keypress.
func printCredits
clearScreen()
print("Bagels\n")
print("Number guessing game\n\n")
print("Original source unknown but suspected to be:\n")
print(" Lawrence Hall of Science, U.C. Berkely.\n\n")
print("Original version in BASIC:\n")
print(" D. Resek, P. Rowe, 1978.\n")
print(" Creative computing (Morristown, New Jersey, USA), 1978.\n\n")
print("This version in Ring:\n")
print(" Copyright (c) 2024, Marcos Cruz (programandala.net)\n")
print(" SPDX-License-Identifier: Fair\n\n")
pressEnter("Press Enter to read the instructions. ")
end
# Clear the screen, print the instructions and wait for a keypress.
func printInstructions
clearScreen()
print("Bagels\n")
print("Number guessing game\n\n")
print("I am thinking of a three-digit number that has no two digits the same.\n")
print("Try to guess it and I will give you clues as follows:\n\n")
print(" PICO - one digit correct but in the wrong position\n")
print(" FERMI - one digit correct and in the right position\n")
print(" BAGELS - no digits correct\n")
pressEnter("\nPress Enter to start. ")
end
# Print the given prompt and return a three-digit number from the user.
func userInput(prompt)
userNumber = list(DIGITS)
while true
inputString = command(prompt)
if len(inputString) != DIGITS
print("Remember it's a #{DIGITS}-digit number.\n")
continue
end
if not isDigit(inputString)
print("What?\n")
continue
end
for digit = 1 to DIGITS
userNumber[digit] = inputString[digit]
next
for digit = 1 to DIGITS
if find(userNumber, userNumber[digit]) != digit
print("Remember my number has no two digits the same.\n")
continue 2
end
next
break
end
return userNumber
end
# Init and run the game loop.
func play
computerNumber = list(DIGITS) # random number
userNumber = list(DIGITS) # user guess
score = 0
fermi = 0 # counter
pico = 0 # counter
while true # game loop
clearScreen()
for digit = 1 to DIGITS
computerNumber[digit] = -1
end
for digit = 1 to DIGITS
computerNumber[digit] = random(MAX_DIGIT)
while find(computerNumber, computerNumber[digit]) != digit
computerNumber[digit] = random(MAX_DIGIT)
end
end
print("O.K. I have a number in mind.\n")
for guess = 1 to TRIES
if guess < 10
guessNumber = "#0" + guess
else
guessNumber = "#" + guess
end
userNumber = userInput("Guess " + guessNumber + ": ")
fermi = 0
pico = 0
for i = 1 to DIGITS
for j = 1 to DIGITS
if computerNumber[i] = userNumber[j]
if i = j
fermi += 1
else
pico += 1
end
end
next
next
for x = 1 to pico
print("PICO ")
next
for x = 1 to fermi
print("FERMI ")
next
if pico + fermi = 0
print("BAGELS")
end
print("\n")
if fermi = DIGITS
break
end
end # tries loop
if fermi = DIGITS
print("You got it!!!\n")
score += 1
else
print("Oh well.\n")
print("That's #{TRIES} guesses. My number was ")
print("" + computerNumber[1] + computerNumber[2] + computerNumber[3] + ".\n")
end
if not yes("Play again? ")
break
end
end # game loop
if score != 0
print("A #{score}-point bagels, buff!!\n")
end
print("Hope you had fun. Bye.\n")
end
func main()
printCredits()
printInstructions()
play()
end
In Scala
/*
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Scala:
Copyright (c) 2023, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written in 2023-09/10, 2023-11.
Last modified: 20231104T0112+0100.
*/
// Move the cursor to the home position.
def home() =
print("\u001B[H")
// Clear the screen and move the cursor to the home position.
def clear() =
print("\u001B[2J")
home()
// Print the given prompt and wait until the user enters an empty string.
def pressEnter(prompt : String) =
var ok = false
while !ok do
ok = io.StdIn.readLine(prompt) == ""
end while
def printTitle() =
clear()
println("Bagels")
println("Number guessing game\n")
// Clear the screen, display the credits and wait for a keypress.
def printCredits() =
printTitle()
println("Original source unknown but suspected to be:")
println(" Lawrence Hall of Science, U.C. Berkely.\n")
println("Original version in BASIC:")
println(" D. Resek, P. Rowe, 1978.")
println(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
println("This version in Scala:")
println(" Copyright (c) 2023, Marcos Cruz (programandala.net)")
println(" SPDX-License-Identifier: Fair\n")
pressEnter("Press Enter to read the instructions. ")
// Clear the screen, print the instructions and wait for a keypress.
def printInstructions() =
printTitle()
println("I am thinking of a three-digit number that has no two digits the same.")
println("Try to guess it and I will give you clues as follows:\n")
println(" PICO - one digit correct but in the wrong position")
println(" FERMI - one digit correct and in the right position")
println(" BAGELS - no digits correct")
pressEnter("\nPress Enter to start. ")
val Digits = 3
// Return three random digits.
def random() : Array[Int] =
val randomDigit = new Array[Int](Digits)
var digit = 0
for i <- 0 until Digits do
var validDigit = false
while !validDigit do
digit = util.Random.nextInt(10)
validDigit = !randomDigit.contains(digit)
end while
randomDigit(i) = digit
end for
randomDigit
// Prints the given prompt, waits until the user enters a valid integer and
// returns it.
def getNumber(prompt : String) : Int =
var number = 0
var ok = false
while !ok do
try
number = io.StdIn.readLine(prompt).trim.toInt
ok = true
catch
case _ => println("Invalid number.")
end while
number
// Prompts the user to enter a command and returns it trimmed.
def getString(prompt : String = "> ") : String =
io.StdIn.readLine(prompt).trim
// Return `true` if any of the elements of the given string is repeated;
// otherwise return `false`.
def isAnyRepeated(s: String) : Boolean =
s.size != s.toSet.size
def containsOnlyDigits(s: String) : Boolean =
var ok = true
s.foreach(char => ok = ok && char.toChar.isDigit)
ok
// Print the given prompt and get a three-digit number from the user.
def input(prompt : String) : Array[Int] =
val ASCII_0 = 48
val userDigit = new Array[Int](Digits)
var inputString = ""
var done = false
while !done do
inputString = getString(prompt)
if inputString.size != Digits then
println(s"Remember it's a ${Digits}-digit number.")
else
if containsOnlyDigits(inputString) then
if isAnyRepeated(inputString) then
println("Remember my number has no two digits the same.")
else
done = true
end if
else
println("What?")
end if
end if
end while
for i <- 0 until Digits do
userDigit(i) = inputString(i).asDigit
end for
userDigit
// Return `true` if the given string is "yes" or a synonym.
def isYes(answer : String) : Boolean =
Array("ok", "yeah", "yes", "y").contains(answer)
// Return `true` if the given string is "no" or a synonym.
def isNo(answer : String) : Boolean =
Array("no", "nope", "n").contains(answer)
// Print the given prompt, wait until the user enters a valid yes/no
// string, and return `true` for "yes" or `false` for "no".
def yes(prompt : String) : Boolean =
var answer = ""
while !(isYes(answer) || isNo(answer)) do
answer = getString(prompt)
isYes(answer)
// Init and run the game loop.
def play() =
val TRIES = 20
var score = 0
var playing = true
var userNumber = new Array[Int](Digits)
while playing do
clear()
var computerNumber = random()
println("O.K. I have a number in mind.")
var fermi = 0
var pico = 0
var guess = 1 // counter
while fermi != Digits && guess <= TRIES do
userNumber = input(s"Guess #${guess}: ")
fermi = 0
pico = 0
for i <- 0 until Digits do
for j <- 0 until Digits do
if computerNumber(i) == userNumber(j) then
if i == j then
fermi += 1
else
pico += 1
end if
end if
end for
end for
print("PICO ".repeat(pico))
print("FERMI ".repeat(fermi))
if pico + fermi == 0 then
print("BAGELS")
end if
println()
guess += 1
end while
if fermi == Digits then
println("You got it!!!")
score += 1
else
println("Oh well.")
print(s"That's $TRIES guesses. My number was ")
computerNumber.foreach(print)
println(".")
end if
if !yes("Play again? ") then
playing = false
end if
end while // play loop
if score != 0 then
println(s"A ${score}-point bagels, buff!!")
end if
println("Hope you had fun. Bye.")
@main def main() =
printCredits()
printInstructions()
play()
In Swift
/*
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Swift:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2025-04-24.
Last modified: 20250424T2222+0200.
*/
// Terminal {{{1
// =============================================================================
// Move the cursor to the home position.
func moveCursorHome() {
print("\u{001B}[H", terminator: "")
}
// Clear the screen and move the cursor to the home position.
func clearScreen() {
print("\u{001B}[2J", terminator: "")
moveCursorHome()
}
// User input {{{1
// =============================================================================
func promptedString(with prompt: String) -> String {
while true {
print(prompt, terminator: "")
if let input = readLine() {
return input
}
}
}
func promptedInteger(with prompt: String) -> Int {
while true {
print(prompt, terminator: "")
if let input = readLine(), let number = Int(input) {
return number
} else {
print("Integer expected.")
}
}
}
func pressEnter(prompt: String) {
print(prompt, terminator: "")
let _ = readLine()
}
// Return `true` if the given string is "yes" or a synonym.
//
func isYes(_ s: String) -> Bool {
return ["ok", "y", "yeah", "yes"].contains(s.lowercased())
}
// Return `true` if the given string is "no" or a synonym.
//
func isNo(_ s: String) -> Bool {
return ["n", "no", "nope"].contains(s.lowercased())
}
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
//
func yes(prompt: String) -> Bool {
while true {
let answer = promptedString(with: prompt)
if isYes(answer) {
return true
}
if isNo(answer) {
return false
}
}
}
// Credits and instructions {{{1
// =============================================================================
func printCredits() {
clearScreen()
print("Bagels")
print("Number guessing game\n")
print("Original source unknown but suspected to be:")
print(" Lawrence Hall of Science, U.C. Berkely.\n")
print("Original version in BASIC:")
print(" D. Resek, P. Rowe, 1978.")
print(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
print("This version in Swift:")
print(" Copyright (c) 2025, Marcos Cruz (programandala.net)")
print(" SPDX-License-Identifier: Fair\n")
pressEnter(prompt: "Press Enter to read the instructions. ")
}
func printInstructions() {
clearScreen()
print("Bagels")
print("Number guessing game\n")
print("I am thinking of a three-digit number that has no two digits the same.")
print("Try to guess it and I will give you clues as follows:\n")
print(" PICO - one digit correct but in the wrong position")
print(" FERMI - one digit correct and in the right position")
print(" BAGELS - no digits correct")
pressEnter(prompt: "\nPress Enter to start. ")
}
// Main {{{1
// =============================================================================
let DIGITS = 3
func randomNumber() -> [Int] {
var randomDigits = [Int]()
for _ in 0 ..< DIGITS {
var digit: Int
repeat {
digit = Int.random(in: 0 ..< 10)
} while randomDigits.contains(digit)
randomDigits.append(digit)
}
return randomDigits
}
func userInput(prompt: String) -> [Int] {
var number = [Int]()
askForNumber: while true {
let input = promptedString(with: prompt)
if (input).count != DIGITS {
print("Remember it's a \(DIGITS)-digit number.")
continue askForNumber
}
for digitPosition in 0 ..< DIGITS {
let digitIndex = input.index(input.startIndex, offsetBy: digitPosition)
let digit = input[digitIndex]
if "0" ... "9" ~= digit {
let numericDigit = Int(String(digit))!
if !number.contains(numericDigit) {
number.append(numericDigit)
} else {
print("Remember my number has no two digits the same.")
continue askForNumber
}
} else {
print("What?")
continue askForNumber
}
}
break
}
return number
}
// Game {{{1
// =============================================================================
// Init and run the game loop.
//
func play() {
let TRIES = 20
var score = 0
var fermi = 0 // counter
var pico = 0 // counter
var userNumber: [Int]
while true {
clearScreen()
let computerNumber = randomNumber()
print("O.K. I have a number in mind.")
for guess in 1 ... TRIES {
// print("My number: \(computerNumber)") // XXX TMP
userNumber = userInput(prompt: "Guess #" + String(guess) + ": ")
fermi = 0
pico = 0
for i in 0 ..< DIGITS {
for j in 0 ..< DIGITS {
if userNumber[i] == computerNumber[j] {
if i == j {
fermi += 1
} else {
pico += 1
}
}
}
}
if pico + fermi == 0 {
print("BAGELS")
} else {
print(String(repeating: "PICO ", count: pico), terminator: "")
print(String(repeating: "FERMI ", count: fermi))
}
if fermi == DIGITS {
break
}
}
if fermi == DIGITS {
print("You got it!!!")
score += 1
} else {
print("Oh well.")
print("That's \(TRIES) guesses. My number was ",terminator: "")
for i in 0 ..< DIGITS {
print(computerNumber[i], terminator: "")
}
print(".")
}
if !yes(prompt: "Play again? ") {
break
}
}
if score != 0 {
print("A \(score)-point bagels, buff!!")
}
print("Hope you had fun. Bye.")
}
printCredits()
printInstructions()
play()
In V
/*
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in V:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2025-01-03, 2025-01-18.
Last modified: 20250731T1954+0200.
*/
import arrays
import os
import rand
import strings
import term
fn print_credits() {
term.clear()
println('Bagels')
println('Number guessing game\n')
println('Original source unknown but suspected to be:')
println(' Lawrence Hall of Science, U.C. Berkely.\n')
println('Original version in BASIC:')
println(' D. Resek, P. Rowe, 1978.')
println(' Creative computing (Morristown, New Jersey, USA), 1978.\n')
println('This version in V:')
println(' Copyright (c) 2025, Marcos Cruz (programandala.net)')
println(' SPDX-License-Identifier: Fair\n')
os.input('Press Enter to read the instructions. ')
}
fn print_instructions() {
term.clear()
println('Bagels')
println('Number guessing game\n')
println('I am thinking of a three-digit number that has no two digits the same.')
println('Try to guess it and I will give you clues as follows:\n')
println(' PICO - one digit correct but in the wrong position')
println(' FERMI - one digit correct and in the right position')
println(' BAGELS - no digits correct')
os.input('\nPress Enter to start. ')
}
const digits = 3
// Print the given prompt and update the array whose address is given with a
// three-digit number from the user.
//
fn get_input(prompt string, mut user_digit []int) {
asking: for {
input := os.input(prompt)
if input.len != digits {
println("Remember it's a ${digits}-digit number.")
continue asking
}
for i, digit in input {
if u8(digit).is_digit() {
user_digit[i] = int(digit) - int(`0`)
} else {
println('What?')
continue asking
}
}
if arrays.distinct[int](*user_digit).len < digits {
println('Remember my number has no two digits the same.')
continue asking
}
break
}
}
// Return `true` if the given string is "yes" or a synonym.
//
fn is_yes(s string) bool {
return ['ok', 'y', 'yeah', 'yes'].any(it == s.to_lower())
}
// Return `true` if the given string is "no" or a synonym.
//
fn is_no(s string) bool {
return ['n', 'no', 'nope'].any(it == s.to_lower())
}
// Print the given prompt, wait until the user enters a valid yes/no string,
// and return `true` for "yes" or `false` for "no".
//
fn yes(prompt string) bool {
mut result := false
for {
answer := os.input(prompt)
if is_yes(answer) {
result = true
break
}
if is_no(answer) {
result = false
break
}
}
return result
}
const tries = 20
const all_digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// Init and run the game loop.
//
fn play() {
mut score := 0
mut fermi := 0 // counter
mut pico := 0 // counter
mut user_number := []int{len: digits}
for {
term.clear()
mut computer_number := rand.choose(all_digits, 3) or { [1, 2, 3] }
println('O.K. I have a number in mind.')
for guess := 1; guess <= tries; guess++ {
get_input('Guess #${guess:2}: ', mut user_number)
fermi = 0
pico = 0
for i in 0 .. digits {
for j in 0 .. digits {
if user_number[i] == computer_number[j] {
if i == j {
fermi += 1
} else {
pico += 1
}
}
}
}
print(strings.repeat_string('PICO ', pico))
print(strings.repeat_string('FERMI ', fermi))
if pico + fermi == 0 {
print('BAGELS')
}
println('')
if fermi == digits {
break
}
}
if fermi == digits {
println('You got it!!!')
score += 1
} else {
println('Oh well.')
print("That's ${tries} guesses. My number was ")
for i in 0 .. digits {
print(computer_number[i])
}
println('.')
}
if !yes('Play again? ') {
break
}
}
if score != 0 {
println('A ${score}-point bagels, buff!!')
}
println('Hope you had fun. Bye.')
}
fn main() {
print_credits()
print_instructions()
play()
}
