Basics of Swift
Descrition del contenete del págine
Conversion de old BASIC-programas a Swift por aprender lu elementari de ti-ci lingue.
Etiquettes:
3D Plot
/*
3D Plot
Original version in BASIC:
Creative Computing (Morristown, New Jersey, USA), ca. 1980.
This version in Swift:
Copyright (c) 2023, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2023-11-02/03, 2023-11-17.
Last modified: 20231117T2222+0100.
*/
import Foundation // exp(), sqrt()
let SPACE = " "
let DOT = "*"
let WIDTH = 56
// Move the cursor to the top left position of the terminal.
func home() {
print("\u{001B}[H", terminator: "")
}
// Clear the terminal and move the cursor to the top left position.
func clear() {
print("\u{001B}[2J", terminator: "")
home()
}
// Display the credits and wait for a keypress.
func printCredits() {
print("3D Plot\n")
print("Original version in BASIC:")
print(" Creative computing (Morristown, New Jersey, USA), ca. 1980.\n")
print("This version in Swift:")
print(" Copyright (c) 2023, Marcos Cruz (programandala.net)")
print(" SPDX-License-Identifier: Fair\n")
print("Press Enter to start the program.")
let _ = readLine()
}
func a(_ z: Double) -> Double {
return 30.0 * exp(-z * z / 100.0)
}
func draw() {
var l = 0
var z = 0
var y1 = 0
var line = Array<String>(repeating: SPACE, count: WIDTH)
var x = -30.0
while x <= 30.0 {
for pos in 0 ..< WIDTH {
line[pos] = SPACE
}
l = 0
y1 = 5 * Int(sqrt(900.0 - x * x) / 5.0)
var y = y1
while y >= -y1 {
z = Int(25.0 + a(sqrt(x * x + Double(y * y))) - 0.7 * Double(y))
if z > l {
l = z
line[z] = DOT
}
y += -5
} // y loop
for pos in 0 ..< WIDTH {
print(line[pos], terminator: "")
}
print()
x += 1.5
} // x loop
}
clear()
printCredits()
clear()
draw()
Bagels
/*
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()
Bug
/*
Bug
Original version in BASIC:
Brian Leibowitz, 1978.
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Swift:
Copyright (c) 2023, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written in 2023-11-04/05.
Last modified: 20231105T0109+0100.
*/
struct Bug {
var body: Bool = false
var neck: Bool = false
var head: Bool = false
var feelers: Int = 0
var feelerType: Character = " "
var tail: Bool = false
var legs: Int = 0
}
struct Player {
var pronoun: String = ""
var possessive: String = ""
var bug: Bug = Bug()
}
// Players.
var computer = Player(pronoun: "I", possessive: "My")
computer.bug.feelerType = "F"
var human = Player(pronoun: "you", possessive: "Your")
human.bug.feelerType = "A"
enum Part: Int, CaseIterable {
case Body = 1, Neck, Head, Feeler, Tail, Leg
func quantity() -> Int {
switch self {
case .Body: return 1
case .Neck: return 1
case .Head: return 1
case .Feeler: return 2
case .Tail: return 1
case .Leg: return 6
}
}
}
// Bug body attributes.
let BODY_HEIGHT = 2
let FEELER_LENGTH = 4
let LEG_LENGTH = 2
let MAX_FEELERS = 2
let MAX_LEGS = 6
let NECK_LENGTH = 2
// Move the cursor to the home position.
func home() {
print("\u{001B}[H", terminator: "")
}
// Clear the screen and move the cursor to the home position.
func clear() {
print("\u{001B}[2J", terminator: "")
home()
}
// Move the cursor up by the given number of rows (defaults to 1), without
// changing the column position.
func cursorUp(rows: UInt8 = 1) {
print("\u{001B}[\(rows)A", terminator: "")
}
// Erase the current line, without moving the cursor position.
func eraseLine() {
print("\u{001B}[2K", terminator: "")
}
// Move the cursor to the previous row, without changing the column position,
// and erase its line.
func erasePreviousLine() {
cursorUp()
eraseLine()
}
// Clear the screen, display the credits and wait for a keypress.
func printCredits() {
clear()
print("Bug\n")
print("Original version in BASIC:")
print(" Brian Leibowitz, 1978.")
print(" Creative computing (Morristown, New Jersey, USA), 1978.\n")
print("This version in Swift:")
print(" Copyright (c) 2023, Marcos Cruz (programandala.net)")
print(" SPDX-License-Identifier: Fair\n")
print("Press Enter to read the instructions. ", terminator: "")
let _ = readLine()
}
let instructions = """
The object is to finish your bug before I finish mine. Each number
stands for a part of the bug body.
I will roll the die for you, tell you what I rolled for you, what the
number stands for, and if you can get the part. If you can get the
part I will give it to you. The same will happen on my turn.
If there is a change in either bug I will give you the option of
seeing the pictures of the bugs. The numbers stand for parts as
follows:
"""
extension String {
func capitalized() -> String {
return self.prefix(1).uppercased() + self.dropFirst()
}
}
func leftJustify(text: String, width: Int, pad: String) -> String {
return String((text + String(repeating: pad, count: width)).prefix(width))
}
// Print a table with the bug parts' description.
func printPartsTable() {
let COLUMNS = 3
let COLUMN_WIDTH = 8
let RULER = String(repeating: "-", count: COLUMN_WIDTH)
let COLUMN_SEPARATION = 2
let SEPARATOR = String(repeating: " ", count: COLUMN_SEPARATION)
let headers = ["Number", "Part", "Quantity"]
for header in headers {
print(
leftJustify(text: header, width: COLUMN_WIDTH, pad: " "),
terminator: SEPARATOR
)
}
print()
// Rulers
for _ in 0 ..< COLUMNS {
print(RULER, terminator: SEPARATOR)
}
print()
// Data
for part in Part.allCases {
print(
leftJustify(text: String(part.rawValue), width: COLUMN_WIDTH, pad: " "),
leftJustify(text: String(describing: part), width: COLUMN_WIDTH, pad: " "),
part.quantity(),
separator: SEPARATOR,
terminator: ""
)
print()
}
}
// Clear the screen, print the instructions and wait for a keypress.
func printInstructions() {
clear()
print("Bug\n")
print(instructions)
print()
printPartsTable()
print("\nPress Enter to start. ", terminator: "")
let _ = readLine()
}
// Print a bug head.
func printHead() {
print(" HHHHHHH")
print(" H H")
print(" H O O H")
print(" H H")
print(" H V H")
print(" HHHHHHH")
}
// Print the given bug.
func printBug(bug: Bug) {
if bug.feelers > 0 {
for _ in 0 ..< FEELER_LENGTH {
print(" ", terminator: "")
for _ in 0 ..< bug.feelers {
print(" ", bug.feelerType, terminator: "")
}
print()
}
}
if bug.head {
printHead()
}
if bug.neck {
for _ in 0 ..< NECK_LENGTH {
print(" N N")
}
}
if bug.body {
print(" BBBBBBBBBBBB")
for _ in 0 ..< BODY_HEIGHT {
print(" B B")
}
if bug.tail {
print("TTTTTB B")
}
print(" BBBBBBBBBBBB")
}
if bug.legs > 0 {
for _ in 0 ..< LEG_LENGTH {
print(" ", terminator: "")
for _ in 0 ..< bug.legs {
print(" L", terminator: "")
}
print()
}
}
}
// Return `true` if the given bug is finished; otherwise return `false`.
func finished(bug: Bug) -> Bool {
return bug.feelers == MAX_FEELERS && bug.tail && bug.legs == MAX_LEGS
}
// Array to convert a number to its equilavent text.
let asText = [
"no",
"a",
"two",
"three",
"four",
"five",
"six" ] // MAX_LEGS
// Return a string containing the given number and noun in their proper form.
func plural(number: Int, noun: String) -> String {
return "\(asText[number]) \(noun)\((number > 1) ? "s" : "")"
}
// Add the given part to the given player's bug.
func addPart(part: Part, player: inout Player) -> Bool {
var changed = false
switch part {
case Part.Body:
if player.bug.body {
print(", but", player.pronoun, "already have a body.")
} else {
print(";", player.pronoun, "now have a body:")
player.bug.body = true
changed = true
}
case Part.Neck:
if player.bug.neck {
print(", but", player.pronoun, "you already have a neck.")
} else if !player.bug.body {
print(", but", player.pronoun, "need a body first.")
} else {
print(";", player.pronoun, "now have a neck:")
player.bug.neck = true
changed = true
}
case Part.Head:
if player.bug.head {
print(", but", player.pronoun, "already have a head.")
} else if !player.bug.neck {
print(", but", player.pronoun, "need a a neck first.")
} else {
print(";", player.pronoun, "now have a head:")
player.bug.head = true
changed = true
}
case Part.Feeler:
if player.bug.feelers == MAX_FEELERS {
print(", but", player.pronoun, "have two feelers already.")
} else if !player.bug.head {
print(", but", player.pronoun, "need a head first.")
} else {
player.bug.feelers += 1
print("; \(player.pronoun) now have \(plural(number: player.bug.feelers, noun: "feeler")):")
changed = true
}
case Part.Tail:
if player.bug.tail {
print(", but", player.pronoun, "already have a tail.")
} else if !player.bug.body {
print(", but", player.pronoun, "need a body first.")
} else {
print(";", player.pronoun, "now have a tail:")
player.bug.tail = true
changed = true
}
case Part.Leg:
if player.bug.legs == MAX_LEGS {
print(", but", player.pronoun, "have",
asText[MAX_LEGS], "feet already.")
} else if !player.bug.body {
print(", but", player.pronoun, "need a body first.")
} else {
player.bug.legs += 1
print("; \(player.pronoun) now have \(plural(number: player.bug.legs, noun: "leg")):")
changed = true
}
}
return changed
}
// Ask the user to press the Enter key, wait for the input, then erase the
// prompt text.
func prompt() {
print("Press Enter to roll the dice. ", terminator: "")
let _ = readLine()
erasePreviousLine()
}
// Play one turn for the given player, rolling the dice and updating his bug.
func turn(_ player: inout Player) {
prompt()
let number = Int.random(in: 1...6)
let part = Part(rawValue: number)!
print("\(player.pronoun.capitalized()) rolled a \(number) (\(String(describing: part).lowercased()))", terminator: "")
if addPart(part: part, player: &player) {
print()
printBug(bug: player.bug)
}
print()
}
// Print a message about the winner.
func printWinner() {
if finished(bug: human.bug) && finished(bug: computer.bug) {
print("Both of our bugs are finished in the same number of turns!")
} else if finished(bug: human.bug) {
print(human.possessive, "bug is finished.")
} else if finished(bug: computer.bug) {
print(computer.possessive, "bug is finished.")
}
}
// Return `true` if either bug is finished, i.e. the game ending condition.
func gameOver() -> Bool {
return finished(bug: human.bug) || finished(bug: computer.bug)
}
// Execute the game loop.
func play() {
clear()
while !gameOver() {
turn(&human)
turn(&computer)
}
printWinner()
}
printCredits()
printInstructions()
play()
print("I hope you enjoyed the game, play it again soon!!")
Bunny
/*
Bunny
Original version in BASIC:
Creative Computing (Morristown, New Jersey, USA), 1978.
This version in Swift:
Copyright (c) 2023, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2023-11-03.
Last modified 20231103T1711+0100.
*/
// Move the cursor to the top left position of the terminal.
func home() {
print("\u{001B}[H", terminator: "")
}
// Clear the terminal and move the cursor to the top left position.
func clearScreen() {
print("\u{001B}[2J", terminator: "")
home()
}
// Print the credits and wait for a keypress.
func printCredits() {
print("Bunny\n")
print("Original version in BASIC:")
print(" Creative Computing (Morristown, New Jersey, USA), 1978.\n")
print("This version in Swift:")
print(" Copyright (c) 2023, Marcos Cruz (programandala.net)")
print(" SPDX-License-Identifier: Fair\n")
print("Press Enter to start the program.")
let _ = readLine()
}
let WIDTH = 53
let SPACE : Unicode.Scalar = " "
var line = Array<Unicode.Scalar>(repeating: SPACE, count: WIDTH)
// Clear the line buffer with spaces.
func clearLine() {
for column in 0 ..< line.count {
line[column] = SPACE
}
}
let letter : [Unicode.Scalar] = ["B", "U", "N", "N", "Y"]
let EOL : Int = -1 // end of line identifier
let data : [Int] = [
1, 2, EOL, 0, 2, 45, 50, EOL, 0, 5, 43, 52, EOL, 0, 7, 41, 52, EOL,
1, 9, 37, 50, EOL, 2, 11, 36, 50, EOL, 3, 13, 34, 49, EOL, 4, 14,
32, 48, EOL, 5, 15, 31, 47, EOL, 6, 16, 30, 45, EOL, 7, 17, 29, 44,
EOL, 8, 19, 28, 43, EOL, 9, 20, 27, 41, EOL, 10, 21, 26, 40, EOL,
11, 22, 25, 38, EOL, 12, 22, 24, 36, EOL, 13, 34, EOL, 14, 33, EOL,
15, 31, EOL, 17, 29, EOL, 18, 27, EOL, 19, 26, EOL, 16, 28, EOL,
13, 30, EOL, 11, 31, EOL, 10, 32, EOL, 8, 33, EOL, 7, 34, EOL, 6,
13, 16, 34, EOL, 5, 12, 16, 35, EOL, 4, 12, 16, 35, EOL, 3, 12, 15,
35, EOL, 2, 35, EOL, 1, 35, EOL, 2, 34, EOL, 3, 34, EOL, 4, 33,
EOL, 6, 33, EOL, 10, 32, 34, 34, EOL, 14, 17, 19, 25, 28, 31, 35,
35, EOL, 15, 19, 23, 30, 36, 36, EOL, 14, 18, 21, 21, 24, 30, 37, 37,
EOL, 13, 18, 23, 29, 33, 38, EOL, 12, 29, 31, 33, EOL, 11, 13, 17,
17, 19, 19, 22, 22, 24, 31, EOL, 10, 11, 17, 18, 22, 22, 24, 24, 29,
29, EOL, 22, 23, 26, 29, EOL, 27, 29, EOL, 28, 29, EOL ]
var dataIndex = 0 // data pointer
func datum() -> Int {
dataIndex += 1
return data[dataIndex - 1]
}
func printLine() {
for character in line {
print(character, terminator: "")
}
print()
}
// Draw the graphic out of `data` and `letter`.
func draw() {
clearLine()
while dataIndex < data.count {
let firstColumn = datum()
if firstColumn == EOL {
printLine()
clearLine()
} else {
let lastColumn = datum()
for column in firstColumn ... lastColumn {
line[column] = letter[Int(column) % letter.count]
}
}
}
}
clearScreen()
printCredits()
clearScreen()
draw()
Diamond
/*
Diamond
Original version in BASIC:
Example included in Vintage BASIC 1.0.3.
http://www.vintage-basic.net
This version in Swift:
Copyright (c) 2023, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2023-11-02.
Last modified 20231103T0050+0100.
*/
let LINES = 17
for i in 1 ... LINES / 2 + 1 {
for _ in 1 ... (LINES + 1) / 2 - i + 1 {
print(" ", terminator: "")
}
for _ in 1 ... i * 2 - 1 {
print("*", terminator: "")
}
print()
}
for i in 1 ... LINES / 2 {
for _ in 1 ... i + 1 {
print(" ", terminator: "")
}
for _ in 1 ... ((LINES + 1) / 2 - i) * 2 - 1 {
print("*", terminator: "")
}
print()
}
Math
/*
Math
Original version in BASIC:
Example included in Vintage BASIC 1.0.3.
http://www.vintage-basic.net
This version in Swift:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2025-04-23.
Last modified: 20250423T1508+0200.
*/
import Foundation
let n: Double
while true {
print("Enter a number: ", terminator: "")
if let input = readLine(), let number = Double(input) {
n = number
break
} else {
print("Number expected.")
}
}
func sign (_: Double) -> Int {
switch true {
case n < 0: return -1
case n > 0: return 1
default: return 0
}
}
print("ABS(\(n)) --> abs(\(n)) --> \(abs(n))")
print("ATN(\(n)) --> atan(\(n)) --> \(atan(n))")
print("COS(\(n)) --> cos(\(n)) --> \(cos(n))")
print("EXP(\(n)) --> exp(\(n)) --> \(exp(n))")
print("INT(\(n)) --> Int(\(n)) --> \(Int(n))")
print("LOG(\(n)) --> log2(\(n)) --> \(log(n))")
print("SGN(\(n)) --> \(n).sign == .minus ? -1 : +1 --> \(n.sign == .minus ? -1 : 1)")
print("SGN(\(n)) --> sign(\(n)) --> \(sign(n)) // ad hoc function")
print("SQR(\(n)) --> sqrt(\(n)) --> \(sqrt(n))")
print("TAN(\(n)) --> tan(\(n)) --> \(tan(n))")
Name
/*
Name
Original version in BASIC:
Example included in Vintage BASIC 1.0.3.
http://www.vintage-basic.net
This version in Swift:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2025-04-23.
Last modified: 20250423T1045+0200.
*/
var name = ""
while name == "" {
print("What is your name? ", terminator: "")
name = readLine() ?? ""
}
var number = 0
while number <= 0 {
print("Enter a number greater than 0: ", terminator: "")
number = Int(readLine() ?? "0") ?? 0
}
for _ in 0 ..< number {
print("Hello, \(name)!")
}
Sine Wave
/*
Sine Wave
Original version in BASIC:
Creative Computing (Morristown, New Jersey, USA), ca. 1980.
This version in Swift:
Copyright (c) 2023, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2023-11-03.
Last modified: 20231103T0142+0100.
*/
import Foundation // sin()
// Move the cursor to the top left position of the terminal.
func home() {
print("\u{001B}[H", terminator: "")
}
// Clear the terminal and move the cursor to the top left position.
func clear() {
print("\u{001B}[2J", terminator: "")
home()
}
var word = ["", ""]
// Ask the user to enter a word and return it.
func getWord(number: Int) -> String {
let order = ["first", "second"]
word[number] = ""
while word[number] == "" {
print("Enter the \(order[number]) word: ", terminator: "")
word[number] = readLine() ?? ""
}
return word[number]
}
// Ask the user to enter two words and store them.
func getWords() {
clear()
for n in 0 ... 1 {
word[n] = getWord(number: n)
}
}
// Clear the screen, display the credits and wait for a keypress.
func printCredits() {
clear()
print("Sine Wave\n")
print("Original version in BASIC:")
print(" Creative Computing (Morristown, New Jersey, USA), ca. 1980.\n")
print("This version in Swift:")
print(" Copyright (c) 2023, Marcos Cruz (programandala.net)")
print(" SPDX-License-Identifier: Fair\n")
print("Press Enter to start the program.")
let _ = readLine()
}
func draw() {
clear()
var even = true
var angle = 0.0
while angle <= 40.0 {
print(String(repeating: " ", count: Int(26 + 25 * sin(angle))), terminator: "")
print(word[even ? 0 : 1])
even = !even
angle += 0.25
}
}
printCredits()
getWords()
draw()
Stars
/*
Stars
Original version in BASIC:
Example included in Vintage BASIC 1.0.3.
http://www.vintage-basic.net
This version in Swift:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2025-04-23.
Last modified: 20250423T1940+0200.
*/
var name = ""
while name == "" {
print("What is your name? ", terminator: "")
name = readLine() ?? ""
}
print("Hello, \(name).")
var numberOfStars: Int
play: while true {
while true {
print("How many stars do you want? ", terminator: "")
if let input = readLine(), let number = Int(input) {
numberOfStars = number
break
} else {
print("Integer expected.")
}
}
print(String(repeating: "*", count: numberOfStars))
print("Do you want more stars? ", terminator: "")
let answer = (readLine() ?? "").lowercased()
if !["ok", "yeah", "yes", "y"].contains(answer) {
break play
}
}
Strings
/*
Strings
Original version in BASIC:
Example included in Vintage BASIC 1.0.3.
http://www.vintage-basic.net
This version in Swift:
Copyright (c) 2025, Marcos Cruz (programandala.net)
SPDX-License-Identifier: Fair
Written on 2025-04-24.
Last modified: 20250424T1551+0200.
*/
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.")
}
}
}
var s = promptedString(with: "Enter a string: ")
var n = promptedInteger(with: "Enter an integer: ")
var start: String.Index
var end: String.Index
var result: String.SubSequence
print()
print("ASC(\"\(s)\") --> ", terminator: "")
print("\"s\".unicodeScalars.map { $0.value } [0] --> \(s.unicodeScalars.map { $0.value } [0])")
print("CHR$(\(n)) --> ", terminator: "")
print("Character(UnicodeScalar(\(n))!) --> \"\(Character(UnicodeScalar(n)!))\"")
// XXX TODO check limits of substrings in order to mimic the behaviour of the
// original BASIC functions
print("LEFT$(\"\(s)\", \(n)) -->")
print("""
let s: \"\(s)\"
let n: \(n)
let end: String.Index = s.index(s.startIndex, offsetBy: n)
let result: StringSubSequence = s[..<end]
""")
end = s.index(s.startIndex, offsetBy: n)
result = s[..<end]
print("--> \"\(result)\"")
print("MID$(\"\(s)\", \(n)) -->")
print("""
let s: \"\(s)\"
let n: \(n)
let start: String.Index = s.index(s.startIndex, offsetBy: n - 1)
let result: String.SubSequence = s[start...]
""")
start = s.index(s.startIndex, offsetBy: n - 1)
result = s[start...]
print("--> \"\(result)\"")
print("MID$(\"\(s)\", \(n), 3) -->")
print("""
let s: \"\(s)\"
let n: \(n)
let start: String.Index = s.index(s.startIndex, offsetBy: n - 1)
let end: String.Index = s.index(start, offsetBy: 3)
let result String.SubSequence = s[start..<end]
""")
start = s.index(s.startIndex, offsetBy: n - 1)
end = s.index(start, offsetBy: 3)
result = s[start..<end]
print("--> \"\(result)\"")
print("RIGHT$(\"\(s)\", \(n)) --> ")
print("""
let s: \"\(s)\"
let n: \(n)
let start: String.Index = s.index(s.endIndex, offsetBy: -n)
let result: String.SubSequence = s[start...]
""")
start = s.index(s.endIndex, offsetBy: -n)
result = s[start...]
print("--> \"\(result)\"")
print("LEN(\"\(s)\") --> ", terminator: "")
print("\"\(s)\".count --> \(s.count)")
print("VAL(\"\(s)\") --> ", terminator: "")
print("Double(\"\(s)\") ?? 0 --> \(Double(s) ?? 0)")
print("STR$(\(n)) --> ", terminator: "")
print("String(\(n)) --> \"\(String(n))\"")
print("SPC(\(n)) --> ", terminator: "")
print("String(repeating: \" \", count: \(n)) --> \"\(String(repeating: " ", count: n))\"")
