Bagels

Description of the page content

Conversion of Bagels to several programming languages.

Tags:

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()
}

Related pages

Basics off
Metaproject about the "Basics of…" projects.

External related links