Bagels
Description of the page content
Conversion of Bagels to several programming languages.
This program has been converted to 22 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: 20260902T2307+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
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
function is_yes(s as string) as boolean
select case lcase(trim(s))
case "ok", "y", "yeah", "yes"
return true
case else
return false
end select
end function
function is_no(s as string) as boolean
select case lcase(trim(s))
case "n", "no", "nope"
return true
case else
return false
end select
end function
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
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: 20260527T2101+0200.
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;
}
sub is_yes(Str $answer --> Bool ) {
return $answer.lc (elem) ["ok", "y", "yeah", "yes"]
}
sub is_no(Str $answer --> Bool) {
return $answer.lc (elem) ["n", "no", "nope"];
}
sub yes(Str $prompt --> Bool) {
loop {
my $answer = prompt($prompt);
if is_yes($answer) { return True };
if is_no($answer) { return False };
}
}
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()
}
In Vala
// Bagels
// Original version in BASIC:
// D. Resek, P. Rowe, 1978.
// Creative Computing (Morristown, New Jersey, USA), 1978.
// This version in Vala:
// Copyright (c) 2026, Marcos Cruz (programandala.net)
// SPDX-License-Identifier: Fair
//
// Written on 2026-08-30.
//
// Last modified: 20260830T1340+0200.
// Terminal {{{1
// =============================================================================
const int NORMAL_STYLE = 0;
void move_cursor_home() {
stdout.printf("\x1B[H");
}
void set_style(int style) {
stdout.printf("\x1B[%dm", style);
}
void reset_attributes() {
set_style(NORMAL_STYLE);
}
void erase_screen() {
stdout.printf("\x1B[2J");
}
void clear_screen() {
erase_screen();
reset_attributes();
move_cursor_home();
}
// Credits and instructions {{{1
// =============================================================================
void print_credits() {
clear_screen();
stdout.printf("Bagels\n");
stdout.printf("Number guessing game\n\n");
stdout.printf("Original source unknown but suspected to be:\n");
stdout.printf(" Lawrence Hall of Science, U.C. Berkely.\n\n");
stdout.printf("Original version in BASIC:\n");
stdout.printf(" D. Resek, P. Rowe, 1978.\n");
stdout.printf(" Creative computing (Morristown, New Jersey, USA), 1978.\n\n");
stdout.printf("This version in Vala:\n");
stdout.printf(" Copyright (c) 2026, Marcos Cruz (programandala.net)\n");
stdout.printf(" SPDX-License-Identifier: Fair\n\n");
accept_string("Press Enter to read the instructions. ");
}
void print_instructions() {
clear_screen();
stdout.printf("Bagels\n");
stdout.printf("Number guessing game\n\n");
stdout.printf("I am thinking of a three-digit number that has no two digits the same.\n");
stdout.printf("Try to guess it and I will give you clues as follows:\n\n");
stdout.printf(" PICO - one digit correct but in the wrong position\n");
stdout.printf(" FERMI - one digit correct and in the right position\n");
stdout.printf(" BAGELS - no digits correct\n\n");
accept_string("Press Enter to start. ");
}
// User input {{{1
// =============================================================================
string accept_string(string prompt) {
stdout.printf(prompt);
return stdin.read_line().strip();
}
bool is_yes(string s) {
switch (s.down()) {
case "ok":
case "y":
case "yeah":
case "yes":
return true;
default:
return false;
}
}
bool is_no(string s) {
switch (s.down()) {
case "n":
case "no":
case "nope":
return true;
default:
return false;
}
}
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
// =============================================================================
const int DIGITS = 3;
bool is_digit(int ascii_code) {
return (ascii_code >= '0') && (ascii_code <= '9');
}
int[] accept_input(string prompt)
ensures(result.length == DIGITS)
{
const char ASCII_0 = '0';
int[] user_digit = new int[DIGITS];
while (true) {
string input = accept_string(prompt);
if (input.length != DIGITS) {
stdout.printf("Remember it's a %d-digit number.\n", DIGITS);
continue;
}
{
bool error = false;
for (int pos = 0; pos < input.length; pos++) {
int digit = input[pos];
if (is_digit(digit)) {
user_digit[pos] = digit - ASCII_0;
} else {
stdout.printf("What?\n");
error = true;
break;
}
}
if (error) {
continue;
}
}
if (is_any_repeated(user_digit)) {
stdout.printf("Remember my number has no two digits the same.\n");
continue;
} else {
break;
}
}
return user_digit;
}
// Return three random digits.
int[] random_number() {
int[] random_digit = new int[DIGITS];
for (int i = 0; i < DIGITS; i++) {
bool found = true;
do {
random_digit[i] = GLib.Random.int_range(0, 10);
for (int j = 0; j < i; j++) {
if (i != j && random_digit[i] == random_digit[j]) {
found = false;
break;
}
}
} while (!found);
}
return random_digit;
}
bool is_any_repeated(int[] number)
requires(number.length == DIGITS)
{
for (int i = 0; i < DIGITS; i++) {
for (int j = i + 1; j < DIGITS; j++) {
if (number[i] == number[j]) {
return true;
}
}
}
return false;
}
string replicate(string s, int count) {
string result = "";
for (int i = 0; i < count; i++) {
result += s;
}
return result;
}
void play() {
const int TRIES = 20;
int score = 0;
int fermi = 0; // counter
int pico = 0; // counter
int[] computer_number = new int[DIGITS];
int[] user_number = new int[DIGITS];
while (true) {
clear_screen();
computer_number = random_number();
stdout.printf("O.K. I have a number in mind.\n");
for (int guess = 1; guess < TRIES + 1; guess++) {
user_number = accept_input(@"Guess #$guess: ");
fermi = 0;
pico = 0;
for (int i = 0; i < DIGITS; i++) {
for (int j = 0; j < DIGITS; j++) {
if (user_number[i] == computer_number[j]) {
if (i == j) {
fermi += 1;
}
else {
pico += 1;
}
}
}
}
if (pico + fermi == 0) {
stdout.printf("BAGELS\n");
}
else {
stdout.printf(
"%s%s\n",
replicate("PICO ", pico),
replicate("FERMI ", fermi)
);
if (fermi == DIGITS) {
break;
}
}
}
if (fermi == DIGITS) {
stdout.printf("You got it!!!\n");
score += 1;
}
else {
stdout.printf("Oh well.\n");
stdout.printf("That's %d guesses. My number was ", TRIES);
for (int i = 0; i < DIGITS; i++) {
stdout.printf(computer_number[i].to_string());
}
stdout.printf(".\n");
}
if (!yes("Play again? ")) {
break;
}
}
if (score != 0) {
stdout.printf("A %d-point bagels, buff!!\n", score);
}
stdout.printf("Hope you had fun. Bye.\n");
}
void main() {
print_credits();
print_instructions();
play();
}
In Zen C
/*
Bagels
Original version in BASIC:
D. Resek, P. Rowe, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Zen C:
Copyright (c) 2026, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2026-04-20.
Last modified: 20260421T0015+0200.
*/
import "ctype.h" // tolower
import "std/random.zc"
import "std/utf8.zc"
def ANSI = "\x1B[" // code prefix
fn clear_screen() {
print "{ANSI}2J{ANSI}0m{ANSI}H"
}
fn typed(prompt: string) -> string {
print "{prompt}"
return readln()
}
fn 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 Zen C:"
println " Copyright (c) 2026, Marcos Cruz (programandala.net)"
println " SPDX-License-Identifier: Fair\n"
typed("Press Enter to read the instructions. ")
}
fn 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"
typed("\nPress Enter to start. ")
}
def DIGITS = 3
fn is_any_repeated<T>(array: T[DIGITS]) -> bool {
for i in 0 ..< DIGITS - 1 {
for j in i + 1 ..< DIGITS {
if array[i] == array[j] {
return true
}
}
}
return false
}
// Print the given prompt and update the given array with a three-digit number
// from the user.
fn get_input(prompt: string, user_digit: int[DIGITS]) {
asking:
loop {
let input: string = typed(prompt)
if strlen(input) != DIGITS {
println "Remember it's a {DIGITS}-digit number."
continue asking
}
for i in 0 ..< DIGITS {
if Utf8::is_digit(input[i]) {
user_digit[i] = input[i] - '0'
} else {
println "What?"
continue asking
}
}
if is_any_repeated(user_digit) {
println "Remember my number has no two digits the same."
continue asking
}
break
}
}
fn to_lowercase(s: string) -> string {
for i in 0 .. strlen(s) {
s[i] = tolower(s[i])
}
return s
}
fn is_yes(s: string) -> bool {
match to_lowercase(s) {
"ok", "y", "yeah", "yes" => { return true }
_ => { return false }
}
}
fn is_no(s: string) -> bool {
match to_lowercase(s) {
"n", "no", "nope" => { return true }
_ => { return false }
}
}
fn yes(prompt: string) -> bool {
loop {
let answer: string = typed(prompt)
if is_yes(answer) {
return true
}
if is_no(answer) {
return false
}
}
}
fn randomize(digit: int[DIGITS]) {
let rng = Random::new()
for let i: int = 0; i < DIGITS; i += 1 {
choose_digit:
loop {
digit[i] = rng.next_int_range(0, 9)
for let j: int = 0; j < i; j += 1 {
if i != j && digit[i] == digit[j] {
continue choose_digit
}
}
break
}
}
}
fn play() {
def TRIES = 20
let score: int = 0
let fermi: int = 0 // counter
let pico: int = 0 // counter
let user_number: int[DIGITS]
loop {
clear_screen()
let computer_number: int[DIGITS]
randomize(computer_number)
println "O.K. I have a number in mind."
for let guess: int = 1; guess <= TRIES; guess += 1 {
get_input("Guess #{guess:2}: ", 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
}
}
}
}
for _ in 0 ..< pico print "PICO "
for _ in 0 ..< fermi print "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()
}
